mirror of
https://github.com/haiwen/seafile-server.git
synced 2025-09-03 16:34:33 +00:00
Optimize copy and move file.
This commit is contained in:
@@ -78,6 +78,8 @@ seaf_copy_manager_get_task (SeafCopyManager *mgr,
|
||||
"canceled", task->canceled, "failed", task->failed,
|
||||
"successful", task->successful,
|
||||
NULL);
|
||||
if (task->canceled || task->failed || task->successful)
|
||||
g_hash_table_remove(priv->copy_tasks, task_id);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock (&priv->lock);
|
||||
@@ -135,7 +137,6 @@ seaf_copy_manager_add_task (SeafCopyManager *mgr,
|
||||
const char *dst_filename,
|
||||
int replace,
|
||||
const char *modifier,
|
||||
gint64 total_files,
|
||||
CopyTaskFunc function,
|
||||
gboolean need_progress)
|
||||
{
|
||||
@@ -148,7 +149,6 @@ seaf_copy_manager_add_task (SeafCopyManager *mgr,
|
||||
task_id = gen_uuid();
|
||||
task = g_new0 (CopyTask, 1);
|
||||
memcpy (task->task_id, task_id, 36);
|
||||
task->total = total_files;
|
||||
|
||||
pthread_mutex_lock (&priv->lock);
|
||||
g_hash_table_insert (priv->copy_tasks, g_strdup(task_id), task);
|
||||
|
@@ -47,7 +47,6 @@ seaf_copy_manager_add_task (SeafCopyManager *mgr,
|
||||
const char *dst_filename,
|
||||
int replace,
|
||||
const char *modifier,
|
||||
gint64 total_files,
|
||||
CopyTaskFunc function,
|
||||
gboolean need_progress);
|
||||
|
||||
|
473
server/repo-op.c
473
server/repo-op.c
@@ -38,6 +38,10 @@ should_ignore_file(const char *filename, void *data);
|
||||
static gboolean
|
||||
is_virtual_repo_and_origin (SeafRepo *repo1, SeafRepo *repo2);
|
||||
|
||||
static gboolean
|
||||
check_file_count_and_size (SeafRepo *repo, SeafDirent *dent, gint64 total_files,
|
||||
gint64 *multi_file_size, GError **error);
|
||||
|
||||
int
|
||||
post_files_and_gen_commit (GList *filenames,
|
||||
SeafRepo *repo,
|
||||
@@ -1960,6 +1964,41 @@ copy_recursive (SeafRepo *src_repo, SeafRepo *dst_repo,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static GHashTable *
|
||||
get_sub_dirents_hash_map(SeafRepo *repo, const char *parent_dir)
|
||||
{
|
||||
GError *error;
|
||||
GList *p;
|
||||
SeafDir *dir = seaf_fs_manager_get_seafdir_by_path (seaf->fs_mgr, repo->store_id,
|
||||
repo->version, repo->root_id, parent_dir, &error);
|
||||
if (!dir) {
|
||||
if (error) {
|
||||
seaf_warning ("Failed to get dir %s repo %.8s: %s.\n",
|
||||
parent_dir, repo->store_id, error->message);
|
||||
g_clear_error(&error);
|
||||
} else {
|
||||
seaf_warning ("dir %s doesn't exist in repo %.8s.\n",
|
||||
parent_dir, repo->store_id);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GHashTable *dirent_hash = g_hash_table_new_full(g_str_hash,
|
||||
g_str_equal,
|
||||
g_free,
|
||||
(GDestroyNotify)seaf_dirent_free);
|
||||
for (p = dir->entries; p; p = p->next) {
|
||||
SeafDirent *d = p->data;
|
||||
g_hash_table_insert(dirent_hash, g_strdup(d->name), d);
|
||||
}
|
||||
|
||||
g_list_free (dir->entries);
|
||||
g_free (dir->ondisk);
|
||||
g_free(dir);
|
||||
|
||||
return dirent_hash;
|
||||
}
|
||||
|
||||
static int
|
||||
cross_repo_copy (const char *src_repo_id,
|
||||
const char *src_path,
|
||||
@@ -1979,6 +2018,8 @@ cross_repo_copy (const char *src_repo_id,
|
||||
guint64 new_size = 0;
|
||||
int ret = 0, i = 0;
|
||||
int file_num = 1;
|
||||
GError *error = NULL;
|
||||
GHashTable *dirent_hash = NULL;
|
||||
|
||||
src_repo = seaf_repo_manager_get_repo (seaf->repo_mgr, src_repo_id);
|
||||
if (!src_repo) {
|
||||
@@ -2001,21 +2042,51 @@ cross_repo_copy (const char *src_repo_id,
|
||||
src_dents = g_new0 (SeafDirent *, file_num);
|
||||
dst_dents = g_new0 (SeafDirent *, file_num);
|
||||
|
||||
dirent_hash = get_sub_dirents_hash_map (src_repo, src_path);
|
||||
if (!dirent_hash) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
gint64 total_files = -1;
|
||||
gint64 total_files_all = 0;
|
||||
gint64 total_size_all = 0;
|
||||
/* check filename, size and file count */
|
||||
for (i = 0; i < file_num; i++) {
|
||||
if (strcmp(src_names[i], "") == 0) {
|
||||
ret = -1;
|
||||
seaf_warning ("[copy files] Bad args: Empty src_filename.\n");
|
||||
goto out;
|
||||
}
|
||||
src_dents[i] = get_dirent_by_path (src_repo, NULL,
|
||||
src_path, src_names[i], NULL);
|
||||
src_dents[i] = g_hash_table_lookup (dirent_hash, src_names[i]);
|
||||
if (!src_dents[i]) {
|
||||
ret = -1;
|
||||
seaf_warning ("[copy files] File %s not Found.\n", src_names[i]);
|
||||
goto out;
|
||||
}
|
||||
if (S_ISDIR(src_dents[i]->mode))
|
||||
total_files = seaf_fs_manager_count_fs_files (seaf->fs_mgr,
|
||||
src_repo->store_id,
|
||||
src_repo->version,
|
||||
src_dents[i]->id);
|
||||
else
|
||||
total_files = 1;
|
||||
if (total_files < 0) {
|
||||
seaf_warning ("Failed to get file count.\n");
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
total_files_all += total_files;
|
||||
if (!check_file_count_and_size (src_repo, src_dents[i], total_files_all,
|
||||
&total_size_all, &error)) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
if (task)
|
||||
task->total = total_files_all;
|
||||
|
||||
/* do copy */
|
||||
for (i = 0; i < file_num; i++) {
|
||||
new_id = copy_recursive (src_repo, dst_repo,
|
||||
src_dents[i]->id, src_dents[i]->mode, modifier, task,
|
||||
@@ -2035,9 +2106,32 @@ cross_repo_copy (const char *src_repo_id,
|
||||
src_dent = get_dirent_by_path (src_repo, NULL,
|
||||
src_path, src_filename, NULL);
|
||||
if (!src_dent) {
|
||||
seaf_warning ("[move file] File %s not Found.\n", src_filename);
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
gint64 total_files = -1;
|
||||
if (S_ISDIR(src_dent->mode))
|
||||
total_files = seaf_fs_manager_count_fs_files (seaf->fs_mgr,
|
||||
src_repo->store_id,
|
||||
src_repo->version,
|
||||
src_dent->id);
|
||||
else
|
||||
total_files = 1;
|
||||
if (total_files < 0) {
|
||||
seaf_warning ("Failed to get file count.\n");
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!check_file_count_and_size (src_repo, src_dent, total_files, NULL, &error)) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
if (task)
|
||||
task->total = total_files;
|
||||
|
||||
new_id = copy_recursive (src_repo, dst_repo,
|
||||
src_dent->id, src_dent->mode, modifier, task,
|
||||
&new_size);
|
||||
@@ -2077,16 +2171,18 @@ out:
|
||||
seaf_dirent_free(src_dent);
|
||||
if (dst_dent)
|
||||
seaf_dirent_free(dst_dent);
|
||||
if (dirent_hash)
|
||||
g_hash_table_unref(dirent_hash);
|
||||
if (file_num > 1) {
|
||||
for (i = 0; i < file_num; i++) {
|
||||
seaf_dirent_free(src_dents[i]);
|
||||
seaf_dirent_free(dst_dents[i]);
|
||||
}
|
||||
g_free (src_dents);
|
||||
g_free(src_dents);
|
||||
for (i = 0; i < file_num; i++)
|
||||
seaf_dirent_free (dst_dents[i]);
|
||||
g_free (dst_dents);
|
||||
g_strfreev(src_names);
|
||||
g_strfreev(dst_names);
|
||||
}
|
||||
if (error)
|
||||
g_clear_error(&error);
|
||||
|
||||
if (ret == 0) {
|
||||
update_repo_size (dst_repo_id);
|
||||
@@ -2118,6 +2214,7 @@ check_file_count_and_size (SeafRepo *repo, SeafDirent *dent, gint64 total_files,
|
||||
total_files > seaf->copy_mgr->max_files) {
|
||||
g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL,
|
||||
"Too many files");
|
||||
seaf_warning("Failed to copy/move file from repo %.8s: Too many files\n", repo->id);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -2148,6 +2245,8 @@ check_file_count_and_size (SeafRepo *repo, SeafDirent *dent, gint64 total_files,
|
||||
if (*multi_file_size > seaf->copy_mgr->max_size) {
|
||||
g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL,
|
||||
"Folder or file size is too large");
|
||||
seaf_warning("Failed to copy/move file from repo %.8s: "
|
||||
"Folder or file size is too large.\n", repo->id);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
@@ -2155,6 +2254,8 @@ check_file_count_and_size (SeafRepo *repo, SeafDirent *dent, gint64 total_files,
|
||||
if (size > seaf->copy_mgr->max_size) {
|
||||
g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL,
|
||||
"Folder or file size is too large");
|
||||
seaf_warning("Failed to copy/move file from repo %.8s: "
|
||||
"Folder or file size is too large.\n", repo->id);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
@@ -2219,17 +2320,18 @@ seaf_repo_manager_copy_file (SeafRepoManager *mgr,
|
||||
/* FAIL_IF_FILE_EXISTS(dst_repo->store_id, dst_repo->version,
|
||||
dst_head_commit->root_id, dst_canon_path, dst_filename, NULL); */
|
||||
|
||||
/* get src dirent */
|
||||
src_dent = get_dirent_by_path (src_repo, NULL,
|
||||
src_canon_path, src_filename, error);
|
||||
if (!src_dent) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (strcmp (src_repo_id, dst_repo_id) == 0 ||
|
||||
is_virtual_repo_and_origin (src_repo, dst_repo)) {
|
||||
|
||||
/* get src dirent */
|
||||
src_dent = get_dirent_by_path (src_repo, NULL,
|
||||
src_canon_path, src_filename, error);
|
||||
if (!src_dent) {
|
||||
seaf_warning("[copy file] file %s/%s doesn't exist.\n", src_canon_path, src_filename);
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
gint64 file_size = (src_dent->version > 0) ? src_dent->size : -1;
|
||||
|
||||
/* duplicate src dirent with new name */
|
||||
@@ -2256,26 +2358,6 @@ seaf_repo_manager_copy_file (SeafRepoManager *mgr,
|
||||
update_repo_size (dst_repo_id);
|
||||
} else if (!synchronous) {
|
||||
background = TRUE;
|
||||
|
||||
gint64 total_files = -1;
|
||||
if (S_ISDIR(src_dent->mode))
|
||||
total_files = seaf_fs_manager_count_fs_files (seaf->fs_mgr,
|
||||
src_repo->store_id,
|
||||
src_repo->version,
|
||||
src_dent->id);
|
||||
else
|
||||
total_files = 1;
|
||||
if (total_files < 0) {
|
||||
seaf_warning ("Failed to get file count.\n");
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!check_file_count_and_size (src_repo, src_dent, total_files, NULL, error)) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
task_id = seaf_copy_manager_add_task (seaf->copy_mgr,
|
||||
src_repo_id,
|
||||
src_canon_path,
|
||||
@@ -2285,7 +2367,6 @@ seaf_repo_manager_copy_file (SeafRepoManager *mgr,
|
||||
dst_filename,
|
||||
0,
|
||||
user,
|
||||
total_files,
|
||||
cross_repo_copy,
|
||||
need_progress);
|
||||
if (need_progress && !task_id) {
|
||||
@@ -2362,6 +2443,7 @@ seaf_repo_manager_copy_multiple_files (SeafRepoManager *mgr,
|
||||
char *task_id = NULL;
|
||||
char **src_names = NULL, **dst_names = NULL;
|
||||
SeafileCopyResult *res = NULL;
|
||||
GHashTable *dirent_hash = NULL;
|
||||
|
||||
GET_REPO_OR_FAIL(src_repo, src_repo_id);
|
||||
|
||||
@@ -2389,29 +2471,42 @@ seaf_repo_manager_copy_multiple_files (SeafRepoManager *mgr,
|
||||
/*FAIL_IF_FILE_EXISTS(dst_repo->store_id, dst_repo->version,
|
||||
dst_head_commit->root_id, dst_canon_path, dst_filename, NULL);*/
|
||||
|
||||
/* get src dirents */
|
||||
if (strchr(src_filenames, '\t') && strchr(dst_filenames, '\t')) {
|
||||
src_names = g_strsplit (src_filenames, "\t", -1);
|
||||
dst_names = g_strsplit (dst_filenames, "\t", -1);
|
||||
file_num = g_strv_length (src_names);
|
||||
int dst_file_num = g_strv_length (dst_names);
|
||||
if (dst_file_num != file_num) {
|
||||
ret = -1;
|
||||
seaf_warning ("[copy files] Bad args.\n");
|
||||
goto out;
|
||||
}
|
||||
if (!strchr(src_filenames, '\t') || !strchr(dst_filenames, '\t')) {
|
||||
ret = -1;
|
||||
seaf_warning ("[copy files] Bad args: Split filenames with '\\t'.\n");
|
||||
goto out;
|
||||
}
|
||||
src_names = g_strsplit (src_filenames, "\t", -1);
|
||||
dst_names = g_strsplit (dst_filenames, "\t", -1);
|
||||
file_num = g_strv_length (src_names);
|
||||
int dst_file_num = g_strv_length (dst_names);
|
||||
if (dst_file_num != file_num) {
|
||||
ret = -1;
|
||||
seaf_warning ("[copy files] Bad args.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* copy file within the same repo */
|
||||
if (src_repo == dst_repo ||
|
||||
is_virtual_repo_and_origin (src_repo, dst_repo)) {
|
||||
|
||||
/* get src dirents */
|
||||
src_dents = g_new0 (SeafDirent *, file_num);
|
||||
file_sizes = g_new0 (gint64, file_num);
|
||||
|
||||
dirent_hash = get_sub_dirents_hash_map (src_repo, src_path);
|
||||
if (!dirent_hash) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; i < file_num; i++) {
|
||||
if (strcmp(src_names[i], "") == 0) {
|
||||
ret = -1;
|
||||
seaf_warning ("[copy files] Bad args: Empty src_filenames.\n");
|
||||
goto out;
|
||||
}
|
||||
src_dents[i] = get_dirent_by_path (src_repo, NULL,
|
||||
src_canon_path, src_names[i], error);
|
||||
src_dents[i] = g_hash_table_lookup(dirent_hash, src_names[i]);
|
||||
if (!src_dents[i]) {
|
||||
ret = -1;
|
||||
seaf_warning ("[copy files] File %s not Found.\n", src_names[i]);
|
||||
@@ -2419,15 +2514,7 @@ seaf_repo_manager_copy_multiple_files (SeafRepoManager *mgr,
|
||||
}
|
||||
file_sizes[i] = (src_dents[i]->version > 0) ? src_dents[i]->size : -1;
|
||||
}
|
||||
} else {
|
||||
ret = -1;
|
||||
seaf_warning ("[copy files] Bad args: Split filenames with '\\t'.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* copy file within the same repo */
|
||||
if (src_repo == dst_repo ||
|
||||
is_virtual_repo_and_origin (src_repo, dst_repo)) {
|
||||
dst_dents = g_new0 (SeafDirent *, file_num);
|
||||
for (i = 0; i < file_num; i++) {
|
||||
if (strcmp(dst_names[i], "") == 0) {
|
||||
@@ -2462,30 +2549,6 @@ seaf_repo_manager_copy_multiple_files (SeafRepoManager *mgr,
|
||||
if (!synchronous) {
|
||||
background = TRUE;
|
||||
|
||||
gint64 total_files = -1;
|
||||
gint64 total_files_all = 0;
|
||||
gint64 total_size_all = 0;
|
||||
|
||||
for (i = 0; i < file_num; i++) {
|
||||
if (S_ISDIR(src_dents[i]->mode))
|
||||
total_files = seaf_fs_manager_count_fs_files (seaf->fs_mgr,
|
||||
src_repo->store_id,
|
||||
src_repo->version,
|
||||
src_dents[i]->id);
|
||||
else
|
||||
total_files = 1;
|
||||
if (total_files < 0) {
|
||||
seaf_warning ("Failed to get file count.\n");
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
total_files_all += total_files;
|
||||
if (!check_file_count_and_size (src_repo, src_dents[i], total_files_all,
|
||||
&total_size_all, error)) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
task_id = seaf_copy_manager_add_task (seaf->copy_mgr,
|
||||
src_repo_id,
|
||||
src_canon_path,
|
||||
@@ -2495,7 +2558,6 @@ seaf_repo_manager_copy_multiple_files (SeafRepoManager *mgr,
|
||||
dst_filenames,
|
||||
0,
|
||||
user,
|
||||
total_files_all,
|
||||
cross_repo_copy,
|
||||
need_progress);
|
||||
if (need_progress && !task_id) {
|
||||
@@ -2539,16 +2601,15 @@ out:
|
||||
g_strfreev (dst_names);
|
||||
if (file_sizes)
|
||||
g_free (file_sizes);
|
||||
if (src_dents) {
|
||||
for (i = 0; i < file_num; i++)
|
||||
seaf_dirent_free (src_dents[i]);
|
||||
if (src_dents)
|
||||
g_free (src_dents);
|
||||
}
|
||||
if (dst_dents) {
|
||||
for (i = 0; i < file_num; i++)
|
||||
seaf_dirent_free (dst_dents[i]);
|
||||
g_free (dst_dents);
|
||||
}
|
||||
if (dirent_hash)
|
||||
g_hash_table_unref(dirent_hash);
|
||||
if (ret == 0) {
|
||||
res = seafile_copy_result_new ();
|
||||
g_object_set (res, "background", background, "task_id", task_id, NULL);
|
||||
@@ -2656,6 +2717,8 @@ cross_repo_move (const char *src_repo_id,
|
||||
guint64 new_size = 0;
|
||||
int ret = 0, i = 0;
|
||||
int file_num = 1;
|
||||
GError *error = NULL;
|
||||
GHashTable *dirent_hash = NULL;
|
||||
|
||||
src_repo = seaf_repo_manager_get_repo (seaf->repo_mgr, src_repo_id);
|
||||
if (!src_repo) {
|
||||
@@ -2678,21 +2741,51 @@ cross_repo_move (const char *src_repo_id,
|
||||
src_dents = g_new0 (SeafDirent *, file_num);
|
||||
dst_dents = g_new0 (SeafDirent *, file_num);
|
||||
|
||||
dirent_hash = get_sub_dirents_hash_map (src_repo, src_path);
|
||||
if (!dirent_hash) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
gint64 total_files = -1;
|
||||
gint64 total_files_all = 0;
|
||||
gint64 total_size_all = 0;
|
||||
/* check filename, size and file count */
|
||||
for (i = 0; i < file_num; i++) {
|
||||
if (strcmp(src_names[i], "") == 0) {
|
||||
ret = -1;
|
||||
seaf_warning ("[move files] Bad args: Empty src_filename.\n");
|
||||
goto out;
|
||||
}
|
||||
src_dents[i] = get_dirent_by_path (src_repo, NULL,
|
||||
src_path, src_names[i], NULL);
|
||||
src_dents[i] = g_hash_table_lookup (dirent_hash, src_names[i]);
|
||||
if (!src_dents[i]) {
|
||||
ret = -1;
|
||||
seaf_warning ("[move files] File %s not Found.\n", src_names[i]);
|
||||
goto out;
|
||||
}
|
||||
if (S_ISDIR(src_dents[i]->mode))
|
||||
total_files = seaf_fs_manager_count_fs_files (seaf->fs_mgr,
|
||||
src_repo->store_id,
|
||||
src_repo->version,
|
||||
src_dents[i]->id);
|
||||
else
|
||||
total_files = 1;
|
||||
if (total_files < 0) {
|
||||
seaf_warning ("Failed to get file count.\n");
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
total_files_all += total_files;
|
||||
if (!check_file_count_and_size (src_repo, src_dents[i], total_files_all,
|
||||
&total_size_all, &error)) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
if (task)
|
||||
task->total = total_files_all;
|
||||
|
||||
/* do copy */
|
||||
for (i = 0; i < file_num; i++) {
|
||||
new_id = copy_recursive (src_repo, dst_repo,
|
||||
src_dents[i]->id, src_dents[i]->mode, modifier, task,
|
||||
@@ -2711,9 +2804,32 @@ cross_repo_move (const char *src_repo_id,
|
||||
src_dent = get_dirent_by_path (src_repo, NULL,
|
||||
src_path, src_filename, NULL);
|
||||
if (!src_dent) {
|
||||
seaf_warning ("[move file] File %s not Found.\n", src_filename);
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
gint64 total_files = -1;
|
||||
if (S_ISDIR(src_dent->mode))
|
||||
total_files = seaf_fs_manager_count_fs_files (seaf->fs_mgr,
|
||||
src_repo->store_id,
|
||||
src_repo->version,
|
||||
src_dent->id);
|
||||
else
|
||||
total_files = 1;
|
||||
if (total_files < 0) {
|
||||
seaf_warning ("Failed to get file count.\n");
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!check_file_count_and_size (src_repo, src_dent, total_files, NULL, &error)) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
if (task)
|
||||
task->total = total_files;
|
||||
|
||||
new_id = copy_recursive (src_repo, dst_repo,
|
||||
src_dent->id, src_dent->mode, modifier, task,
|
||||
&new_size);
|
||||
@@ -2762,16 +2878,18 @@ out:
|
||||
seaf_dirent_free(src_dent);
|
||||
if (dst_dent)
|
||||
seaf_dirent_free(dst_dent);
|
||||
if (dirent_hash)
|
||||
g_hash_table_unref(dirent_hash);
|
||||
if (file_num > 1) {
|
||||
for (i = 0; i < file_num; i++) {
|
||||
seaf_dirent_free(src_dents[i]);
|
||||
seaf_dirent_free(dst_dents[i]);
|
||||
}
|
||||
g_free (src_dents);
|
||||
for (i = 0; i < file_num; i++)
|
||||
seaf_dirent_free(dst_dents[i]);
|
||||
g_free (dst_dents);
|
||||
g_strfreev(src_names);
|
||||
g_strfreev(dst_names);
|
||||
}
|
||||
if (error)
|
||||
g_clear_error(&error);
|
||||
|
||||
if (ret == 0) {
|
||||
update_repo_size (dst_repo_id);
|
||||
@@ -2832,16 +2950,18 @@ seaf_repo_manager_move_file (SeafRepoManager *mgr,
|
||||
/*FAIL_IF_FILE_EXISTS(dst_repo->store_id, dst_repo->version,
|
||||
dst_head_commit->root_id, dst_canon_path, dst_filename, NULL);*/
|
||||
|
||||
/* get src dirent */
|
||||
src_dent = get_dirent_by_path (src_repo, NULL,
|
||||
src_canon_path, src_filename, error);
|
||||
if (!src_dent) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
gint64 file_size = (src_dent->version > 0) ? src_dent->size : -1;
|
||||
/* same repo */
|
||||
if (src_repo == dst_repo ) {
|
||||
/* get src dirent */
|
||||
src_dent = get_dirent_by_path (src_repo, NULL,
|
||||
src_canon_path, src_filename, error);
|
||||
if (!src_dent) {
|
||||
seaf_warning("[move file] file %s/%s doesn't exist.\n", src_canon_path, src_filename);
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
gint64 file_size = (src_dent->version > 0) ? src_dent->size : -1;
|
||||
|
||||
if (src_repo == dst_repo) {
|
||||
/* duplicate src dirent with new name */
|
||||
dst_dent = seaf_dirent_new (dir_version_from_repo_version (dst_repo->version),
|
||||
src_dent->id, src_dent->mode, dst_filename,
|
||||
@@ -2862,8 +2982,17 @@ seaf_repo_manager_move_file (SeafRepoManager *mgr,
|
||||
update_repo_size (dst_repo_id);
|
||||
} else {
|
||||
/* move between different repos */
|
||||
|
||||
/* virtual repo */
|
||||
if (is_virtual_repo_and_origin (src_repo, dst_repo)) {
|
||||
/* get src dirent */
|
||||
src_dent = get_dirent_by_path (src_repo, NULL,
|
||||
src_canon_path, src_filename, error);
|
||||
if (!src_dent) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
gint64 file_size = (src_dent->version > 0) ? src_dent->size : -1;
|
||||
|
||||
/* duplicate src dirent with new name */
|
||||
dst_dent = seaf_dirent_new (dir_version_from_repo_version(dst_repo->version),
|
||||
src_dent->id, src_dent->mode, dst_filename,
|
||||
@@ -2898,25 +3027,6 @@ seaf_repo_manager_move_file (SeafRepoManager *mgr,
|
||||
} else if (!synchronous) {
|
||||
background = TRUE;
|
||||
|
||||
gint64 total_files = -1;
|
||||
if (S_ISDIR(src_dent->mode))
|
||||
total_files = seaf_fs_manager_count_fs_files (seaf->fs_mgr,
|
||||
src_repo->store_id,
|
||||
src_repo->version,
|
||||
src_dent->id);
|
||||
else
|
||||
total_files = 1;
|
||||
if (total_files < 0) {
|
||||
seaf_warning ("Failed to get file count.\n");
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!check_file_count_and_size (src_repo, src_dent, total_files, NULL, error)) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
task_id = seaf_copy_manager_add_task (seaf->copy_mgr,
|
||||
src_repo_id,
|
||||
src_canon_path,
|
||||
@@ -2926,7 +3036,6 @@ seaf_repo_manager_move_file (SeafRepoManager *mgr,
|
||||
dst_filename,
|
||||
replace,
|
||||
user,
|
||||
total_files,
|
||||
cross_repo_move,
|
||||
need_progress);
|
||||
if (need_progress && !task_id) {
|
||||
@@ -3001,6 +3110,7 @@ seaf_repo_manager_move_multiple_files (SeafRepoManager *mgr,
|
||||
char *task_id = NULL;
|
||||
char **src_names = NULL, **dst_names = NULL;
|
||||
SeafileCopyResult *res = NULL;
|
||||
GHashTable *dirent_hash = NULL;
|
||||
|
||||
GET_REPO_OR_FAIL(src_repo, src_repo_id);
|
||||
|
||||
@@ -3028,45 +3138,49 @@ seaf_repo_manager_move_multiple_files (SeafRepoManager *mgr,
|
||||
/*FAIL_IF_FILE_EXISTS(dst_repo->store_id, dst_repo->version,
|
||||
dst_head_commit->root_id, dst_canon_path, dst_filename, NULL);*/
|
||||
|
||||
/* get src dirents */
|
||||
if (strchr(src_filenames, '\t') && strchr(dst_filenames, '\t')) {
|
||||
src_names = g_strsplit (src_filenames, "\t", -1);
|
||||
dst_names = g_strsplit (dst_filenames, "\t", -1);
|
||||
file_num = g_strv_length (src_names);
|
||||
int dst_file_num = g_strv_length (dst_names);
|
||||
if (dst_file_num != file_num) {
|
||||
ret = -1;
|
||||
seaf_warning ("[move files] Bad args.\n");
|
||||
goto out;
|
||||
}
|
||||
if (!strchr(src_filenames, '\t') || !strchr(dst_filenames, '\t')) {
|
||||
ret = -1;
|
||||
seaf_warning ("[move files] Bad args: Split filenames with '\\t'.\n");
|
||||
goto out;
|
||||
}
|
||||
src_names = g_strsplit (src_filenames, "\t", -1);
|
||||
dst_names = g_strsplit (dst_filenames, "\t", -1);
|
||||
file_num = g_strv_length (src_names);
|
||||
int dst_file_num = g_strv_length (dst_names);
|
||||
if (dst_file_num != file_num) {
|
||||
ret = -1;
|
||||
seaf_warning ("[move files] Bad args.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
gboolean is_virtual_origin = is_virtual_repo_and_origin (src_repo, dst_repo);
|
||||
if (src_repo == dst_repo || is_virtual_origin) {
|
||||
/* get src dirents */
|
||||
|
||||
src_dents = g_new0 (SeafDirent *, file_num);
|
||||
file_sizes = g_new0 (gint64, file_num);
|
||||
|
||||
dirent_hash = get_sub_dirents_hash_map (src_repo, src_path);
|
||||
if (!dirent_hash) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; i < file_num; i++) {
|
||||
if (strcmp(src_names[i], "") == 0) {
|
||||
ret = -1;
|
||||
seaf_warning ("[move files] Bad args: Empty src_filenames.\n");
|
||||
goto out;
|
||||
}
|
||||
src_dents[i] = get_dirent_by_path (src_repo, NULL,
|
||||
src_canon_path, src_names[i], error);
|
||||
src_dents[i] = g_hash_table_lookup(dirent_hash, src_names[i]);
|
||||
if (!src_dents[i]) {
|
||||
ret = -1;
|
||||
seaf_warning ("[move files] File %s not Found.\n", src_names[i]);
|
||||
goto out;
|
||||
}
|
||||
file_sizes[i] = (src_dents[i]->version > 0) ? src_dents[i]->size : -1;
|
||||
|
||||
}
|
||||
} else {
|
||||
ret = -1;
|
||||
seaf_warning ("[move files] Bad args: Split filenames with '\\t'.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* move file within the same repo */
|
||||
if (src_repo == dst_repo) {
|
||||
dst_dents = g_new0 (SeafDirent *, file_num);
|
||||
for (i = 0; i < file_num; i++) {
|
||||
if (strcmp(dst_names[i], "") == 0) {
|
||||
@@ -3080,26 +3194,16 @@ seaf_repo_manager_move_multiple_files (SeafRepoManager *mgr,
|
||||
src_dents[i]->mtime, user, file_sizes[i]);
|
||||
}
|
||||
/* move file within the same repo */
|
||||
if (move_file_same_repo (src_repo_id,
|
||||
src_canon_path, src_dents,
|
||||
dst_canon_path, dst_dents,
|
||||
file_num, replace, user, error) < 0) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
seaf_repo_manager_cleanup_virtual_repos (mgr, src_repo_id);
|
||||
seaf_repo_manager_merge_virtual_repo (mgr, src_repo_id, NULL);
|
||||
|
||||
update_repo_size (dst_repo_id);
|
||||
} else {
|
||||
/* move between virtual and origin repos */
|
||||
if (is_virtual_repo_and_origin (src_repo, dst_repo)) {
|
||||
dst_dents = g_new0 (SeafDirent *, file_num);
|
||||
for (i = 0; i < file_num; i++) {
|
||||
dst_dents[i] = seaf_dirent_new (dir_version_from_repo_version(dst_repo->version),
|
||||
src_dents[i]->id, src_dents[i]->mode, dst_names[i],
|
||||
src_dents[i]->mtime, user, src_dents[i]->size);
|
||||
if (src_repo == dst_repo) {
|
||||
if (move_file_same_repo (src_repo_id,
|
||||
src_canon_path, src_dents,
|
||||
dst_canon_path, dst_dents,
|
||||
file_num, replace, user, error) < 0) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
/* move between virtual and origin repo */
|
||||
if (put_dirent_and_commit (dst_repo,
|
||||
dst_path,
|
||||
dst_dents,
|
||||
@@ -3117,38 +3221,16 @@ seaf_repo_manager_move_multiple_files (SeafRepoManager *mgr,
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
seaf_repo_manager_cleanup_virtual_repos (mgr, src_repo_id);
|
||||
seaf_repo_manager_merge_virtual_repo (mgr, src_repo_id, NULL);
|
||||
|
||||
seaf_repo_manager_merge_virtual_repo (mgr, src_repo->id, NULL);
|
||||
|
||||
update_repo_size (dst_repo->id);
|
||||
} else if (!synchronous) {
|
||||
/* move between different repos */
|
||||
update_repo_size (dst_repo_id);
|
||||
} else {
|
||||
/* move between different repos */
|
||||
if (!synchronous) {
|
||||
background = TRUE;
|
||||
|
||||
gint64 total_files = -1;
|
||||
gint64 total_files_all = 0;
|
||||
gint64 total_size_all = 0;
|
||||
|
||||
for (i = 0; i < file_num; i++) {
|
||||
if (S_ISDIR(src_dents[i]->mode))
|
||||
total_files = seaf_fs_manager_count_fs_files (seaf->fs_mgr,
|
||||
src_repo->store_id,
|
||||
src_repo->version,
|
||||
src_dents[i]->id);
|
||||
else
|
||||
total_files = 1;
|
||||
if (total_files < 0) {
|
||||
seaf_warning ("Failed to get file count.\n");
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
total_files_all += total_files;
|
||||
if (!check_file_count_and_size (src_repo, src_dents[i], total_files_all,
|
||||
&total_size_all, error)) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
task_id = seaf_copy_manager_add_task (seaf->copy_mgr,
|
||||
src_repo_id,
|
||||
src_canon_path,
|
||||
@@ -3158,7 +3240,6 @@ seaf_repo_manager_move_multiple_files (SeafRepoManager *mgr,
|
||||
dst_filenames,
|
||||
0,
|
||||
user,
|
||||
total_files_all,
|
||||
cross_repo_move,
|
||||
need_progress);
|
||||
if (need_progress && !task_id) {
|
||||
@@ -3202,11 +3283,11 @@ out:
|
||||
g_strfreev (dst_names);
|
||||
if (file_sizes)
|
||||
g_free (file_sizes);
|
||||
if (src_dents) {
|
||||
for (i = 0; i < file_num; i++)
|
||||
seaf_dirent_free (src_dents[i]);
|
||||
|
||||
if (dirent_hash)
|
||||
g_hash_table_unref(dirent_hash);
|
||||
if (src_dents)
|
||||
g_free (src_dents);
|
||||
}
|
||||
if (dst_dents) {
|
||||
for (i = 0; i < file_num; i++)
|
||||
seaf_dirent_free (dst_dents[i]);
|
||||
|
Reference in New Issue
Block a user