1
0
mirror of https://github.com/haiwen/seafile-server.git synced 2025-09-09 11:18:54 +00:00

Optimize cleaning-up of virtual repos and renaming, deleting operations.

This commit is contained in:
cuihaikuo
2019-03-19 11:58:44 +08:00
parent f491ea95e8
commit 7fe43a0248
6 changed files with 101 additions and 82 deletions

View File

@@ -1105,7 +1105,6 @@ put_update_branch_cb (evhtp_request_t *req, void *arg)
goto out; goto out;
} }
seaf_repo_manager_cleanup_virtual_repos (seaf->repo_mgr, repo_id);
seaf_repo_manager_merge_virtual_repo (seaf->repo_mgr, repo_id, NULL); seaf_repo_manager_merge_virtual_repo (seaf->repo_mgr, repo_id, NULL);
schedule_repo_size_computation (seaf->size_sched, repo_id); schedule_repo_size_computation (seaf->size_sched, repo_id);

View File

@@ -204,7 +204,6 @@ update_repo (void *vprocessor)
goto out; goto out;
} }
seaf_repo_manager_cleanup_virtual_repos (seaf->repo_mgr, repo_id);
seaf_repo_manager_merge_virtual_repo (seaf->repo_mgr, repo_id, NULL); seaf_repo_manager_merge_virtual_repo (seaf->repo_mgr, repo_id, NULL);
out: out:

View File

@@ -337,7 +337,6 @@ update_repo (void *vprocessor)
goto out; goto out;
} }
seaf_repo_manager_cleanup_virtual_repos (seaf->repo_mgr, repo_id);
seaf_repo_manager_merge_virtual_repo (seaf->repo_mgr, repo_id, NULL); seaf_repo_manager_merge_virtual_repo (seaf->repo_mgr, repo_id, NULL);
out: out:

View File

@@ -1490,7 +1490,8 @@ static char *
del_file_recursive(SeafRepo *repo, del_file_recursive(SeafRepo *repo,
const char *dir_id, const char *dir_id,
const char *to_path, const char *to_path,
const char *filename) const char *filename,
int *mode, int *deleted_num, char **desc_file)
{ {
SeafDir *olddir, *newdir; SeafDir *olddir, *newdir;
SeafDirent *dent; SeafDirent *dent;
@@ -1523,6 +1524,12 @@ del_file_recursive(SeafRepo *repo,
for (i = 0; i < file_num; i++) { for (i = 0; i < file_num; i++) {
if (strcmp(old->name, file_names[i]) == 0) { if (strcmp(old->name, file_names[i]) == 0) {
found_flag = 1; found_flag = 1;
if (deleted_num)
(*deleted_num)++;
if (mode)
*mode = old->mode;
if (desc_file && *desc_file==NULL)
*desc_file = g_strdup(old->name);
break; break;
} }
} }
@@ -1538,6 +1545,13 @@ del_file_recursive(SeafRepo *repo,
if (strcmp(old->name, filename) != 0) { if (strcmp(old->name, filename) != 0) {
new = seaf_dirent_dup (old); new = seaf_dirent_dup (old);
newentries = g_list_prepend (newentries, new); newentries = g_list_prepend (newentries, new);
} else {
if (deleted_num)
(*deleted_num)++;
if (mode)
*mode = old->mode;
if (desc_file && *desc_file==NULL)
*desc_file = g_strdup(old->name);
} }
} }
} }
@@ -1567,7 +1581,8 @@ del_file_recursive(SeafRepo *repo,
if (strcmp(dent->name, to_path_dup) != 0) if (strcmp(dent->name, to_path_dup) != 0)
continue; continue;
id = del_file_recursive(repo, dent->id, remain, filename); id = del_file_recursive(repo, dent->id, remain, filename,
mode, deleted_num, desc_file);
if (id != NULL) { if (id != NULL) {
memcpy(dent->id, id, 40); memcpy(dent->id, id, 40);
dent->id[40] = '\0'; dent->id[40] = '\0';
@@ -1599,13 +1614,15 @@ static char *
do_del_file(SeafRepo *repo, do_del_file(SeafRepo *repo,
const char *root_id, const char *root_id,
const char *parent_dir, const char *parent_dir,
const char *file_name) const char *file_name,
int *mode, int *deleted_num, char **desc_file)
{ {
/* if parent_dir is a absolutely path, we will remove the first '/' */ /* if parent_dir is a absolutely path, we will remove the first '/' */
if (*parent_dir == '/') if (*parent_dir == '/')
parent_dir = parent_dir + 1; parent_dir = parent_dir + 1;
return del_file_recursive(repo, root_id, parent_dir, file_name); return del_file_recursive(repo, root_id, parent_dir, file_name,
mode, deleted_num, desc_file);
} }
int int
@@ -1618,15 +1635,14 @@ seaf_repo_manager_del_file (SeafRepoManager *mgr,
{ {
SeafRepo *repo = NULL; SeafRepo *repo = NULL;
SeafCommit *head_commit = NULL; SeafCommit *head_commit = NULL;
SeafDir *dir = NULL;
char *canon_path = NULL; char *canon_path = NULL;
char **file_names;
char buf[SEAF_PATH_MAX]; char buf[SEAF_PATH_MAX];
char *root_id = NULL; char *root_id = NULL;
char *desc_file; char *desc_file = NULL;
int i = 0;
int mode = 0; int mode = 0;
int ret = 0; int ret = 0;
int file_num = 0, empty_num = 0; int deleted_num = 0;
GET_REPO_OR_FAIL(repo, repo_id); GET_REPO_OR_FAIL(repo, repo_id);
GET_COMMIT_OR_FAIL(head_commit, repo->id, repo->version, repo->head->commit_id); GET_COMMIT_OR_FAIL(head_commit, repo->id, repo->version, repo->head->commit_id);
@@ -1634,39 +1650,19 @@ seaf_repo_manager_del_file (SeafRepoManager *mgr,
if (!canon_path) if (!canon_path)
canon_path = get_canonical_path (parent_dir); canon_path = get_canonical_path (parent_dir);
if (strchr(file_name, '\t')) { dir = seaf_fs_manager_get_seafdir_by_path (seaf->fs_mgr,
file_names = g_strsplit (file_name, "\t", -1); repo->store_id, repo->version,
file_num = g_strv_length (file_names); head_commit->root_id, canon_path, NULL);
if (!dir) {
for (i = 0; i < file_num; i++) { seaf_warning ("parent_dir %s doesn't exist in repo %s.\n",
if (strcmp(file_names[i], "") == 0) { canon_path, repo->store_id);
empty_num++; ret = -1;
continue;
}
if (!check_file_exists(repo->store_id, repo->version,
head_commit->root_id, canon_path, file_names[i], &mode)) {
char *tmp_path;
if (strcmp(canon_path, "") == 0)
tmp_path = "/";
else
tmp_path = canon_path;
seaf_warning ("[del file] File \'%s\' dosen't exist in %s in repo %s.\n",
file_names[i], tmp_path, repo->id);
empty_num++;
continue;
}
desc_file = file_names[i];
}
file_num -= empty_num;
if (file_num <= 0)
goto out;
} else if (!check_file_exists(repo->store_id, repo->version,
head_commit->root_id, canon_path, file_name, &mode)) {
goto out; goto out;
} }
root_id = do_del_file (repo, root_id = do_del_file (repo,
head_commit->root_id, canon_path, file_name); head_commit->root_id, canon_path, file_name, &mode,
&deleted_num, &desc_file);
if (!root_id) { if (!root_id) {
seaf_warning ("[del file] Failed to del file from %s in repo %s.\n", seaf_warning ("[del file] Failed to del file from %s in repo %s.\n",
canon_path, repo->id); canon_path, repo->id);
@@ -1675,15 +1671,23 @@ seaf_repo_manager_del_file (SeafRepoManager *mgr,
ret = -1; ret = -1;
goto out; goto out;
} }
if (deleted_num == 0) {
seaf_warning ("[del file] Nothing to be deleted in dir %s in repo %.8s.\n ",
parent_dir, repo->id);
g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL,
"File doesn't exist");
ret = -1;
goto out;
}
/* Commit. */ /* Commit. */
if (file_num > 1) { if (deleted_num > 1) {
snprintf(buf, SEAF_PATH_MAX, "Deleted \"%s\" and %d more files", snprintf(buf, SEAF_PATH_MAX, "Deleted \"%s\" and %d more files",
desc_file, file_num - 1); desc_file, deleted_num - 1);
} else if (S_ISDIR(mode)) { } else if (S_ISDIR(mode)) {
snprintf(buf, SEAF_PATH_MAX, "Removed directory \"%s\"", file_name); snprintf(buf, SEAF_PATH_MAX, "Removed directory \"%s\"", desc_file);
} else { } else {
snprintf(buf, SEAF_PATH_MAX, "Deleted \"%s\"", file_name); snprintf(buf, SEAF_PATH_MAX, "Deleted \"%s\"", desc_file);
} }
if (gen_new_commit (repo_id, head_commit, root_id, if (gen_new_commit (repo_id, head_commit, root_id,
@@ -1692,8 +1696,6 @@ seaf_repo_manager_del_file (SeafRepoManager *mgr,
goto out; goto out;
} }
seaf_repo_manager_cleanup_virtual_repos (mgr, repo_id);
seaf_repo_manager_merge_virtual_repo (mgr, repo_id, NULL); seaf_repo_manager_merge_virtual_repo (mgr, repo_id, NULL);
out: out:
@@ -1701,10 +1703,11 @@ out:
seaf_repo_unref (repo); seaf_repo_unref (repo);
if (head_commit) if (head_commit)
seaf_commit_unref(head_commit); seaf_commit_unref(head_commit);
if (file_num) if (dir)
g_strfreev (file_names); seaf_dir_free (dir);
g_free (root_id); g_free (root_id);
g_free (canon_path); g_free (canon_path);
g_free (desc_file);
if (ret == 0) { if (ret == 0) {
update_repo_size (repo_id); update_repo_size (repo_id);
@@ -2600,7 +2603,8 @@ move_file_same_repo (const char *repo_id,
ret = -1; ret = -1;
goto out; goto out;
} }
root_id = do_del_file (repo, root_id_after_put, src_path, filenames_str->str); root_id = do_del_file (repo, root_id_after_put, src_path, filenames_str->str,
NULL, NULL, NULL);
if (!root_id) { if (!root_id) {
g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "move file failed"); g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "move file failed");
@@ -2855,7 +2859,6 @@ seaf_repo_manager_move_file (SeafRepoManager *mgr,
goto out; 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); update_repo_size (dst_repo_id);
@@ -3086,7 +3089,6 @@ seaf_repo_manager_move_multiple_files (SeafRepoManager *mgr,
ret = -1; ret = -1;
goto out; 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); update_repo_size (dst_repo_id);
@@ -3704,7 +3706,6 @@ seaf_repo_manager_rename_file (SeafRepoManager *mgr,
goto out; goto out;
} }
seaf_repo_manager_cleanup_virtual_repos (mgr, repo_id);
seaf_repo_manager_merge_virtual_repo (mgr, repo_id, NULL); seaf_repo_manager_merge_virtual_repo (mgr, repo_id, NULL);
out: out:

View File

@@ -521,7 +521,8 @@ seaf_repo_manager_merge_virtual_repo (SeafRepoManager *mgr,
*/ */
static void static void
handle_missing_virtual_repo (SeafRepoManager *mgr, handle_missing_virtual_repo (SeafRepoManager *mgr,
SeafRepo *repo, SeafCommit *head, SeafVirtRepo *vinfo) SeafRepo *repo, SeafCommit *head, SeafVirtRepo *vinfo,
char **return_new_path)
{ {
SeafCommit *parent = NULL; SeafCommit *parent = NULL;
char *old_dir_id = NULL; char *old_dir_id = NULL;
@@ -569,9 +570,7 @@ handle_missing_virtual_repo (SeafRepoManager *mgr,
} }
char de_id[41]; char de_id[41];
char *new_path; char *new_path, *new_name;
char *new_name;
char **parts = NULL;
for (ptr = diff_res; ptr; ptr = ptr->next) { for (ptr = diff_res; ptr; ptr = ptr->next) {
de = ptr->data; de = ptr->data;
@@ -586,17 +585,23 @@ handle_missing_virtual_repo (SeafRepoManager *mgr,
vinfo->repo_id, new_path); vinfo->repo_id, new_path);
set_virtual_repo_base_commit_path (vinfo->repo_id, set_virtual_repo_base_commit_path (vinfo->repo_id,
head->commit_id, new_path); head->commit_id, new_path);
parts = g_strsplit(new_path, "/", 0); if (return_new_path)
new_name = parts[g_strv_length(parts) - 1]; *return_new_path = g_strdup(new_path);
/* 'sub_path = NUll' means the virtual dir itself has been renamed,
seaf_repo_manager_edit_repo (vinfo->repo_id, * we need to make a new commit for the virtual repo
new_name, */
"Changed library name", if (sub_path == NULL) {
NULL, new_name = g_path_get_basename(new_path);
&error); seaf_repo_manager_edit_repo (vinfo->repo_id,
if (error) { new_name,
seaf_warning ("Failed to rename repo %s", de->new_name); "Changed library name",
g_clear_error (&error); NULL,
&error);
if (error) {
seaf_warning ("Failed to rename repo %s", new_name);
g_clear_error (&error);
}
g_free(new_name);
} }
is_renamed = TRUE; is_renamed = TRUE;
g_free (new_path); g_free (new_path);
@@ -605,7 +610,6 @@ handle_missing_virtual_repo (SeafRepoManager *mgr,
} }
} }
g_free (old_dir_id); g_free (old_dir_id);
g_strfreev (parts);
if (is_renamed) if (is_renamed)
break; break;
@@ -676,7 +680,7 @@ seaf_repo_manager_cleanup_virtual_repos (SeafRepoManager *mgr,
&error); &error);
if (error) { if (error) {
if (error->code == SEAF_ERR_PATH_NO_EXIST) { if (error->code == SEAF_ERR_PATH_NO_EXIST) {
handle_missing_virtual_repo (mgr, repo, head, vinfo); handle_missing_virtual_repo (mgr, repo, head, vinfo, NULL);
} }
g_clear_error (&error); g_clear_error (&error);
} else } else
@@ -740,6 +744,31 @@ static void *merge_virtual_repo (void *vtask)
goto out; goto out;
} }
orig_root = seaf_fs_manager_get_seafdir_id_by_path (seaf->fs_mgr,
orig_repo->store_id,
orig_repo->version,
orig_head->root_id,
vinfo->path,
NULL);
if (!orig_root) {
seaf_debug("Path %s not found in origin repo %.8s, delete or rename virtual repo %.8s\n",
vinfo->path, vinfo->origin_repo_id, repo_id);
char *new_path = NULL;
handle_missing_virtual_repo (mgr, orig_repo, orig_head, vinfo, &new_path);
if (new_path != NULL) {
orig_root = seaf_fs_manager_get_seafdir_id_by_path (seaf->fs_mgr,
orig_repo->store_id,
orig_repo->version,
orig_head->root_id,
new_path,
NULL);
g_free (new_path);
}
if (!orig_root)
goto out;
}
base = seaf_commit_manager_get_commit (seaf->commit_mgr, base = seaf_commit_manager_get_commit (seaf->commit_mgr,
orig_repo->id, orig_repo->version, orig_repo->id, orig_repo->version,
vinfo->base_commit); vinfo->base_commit);
@@ -766,19 +795,6 @@ static void *merge_virtual_repo (void *vtask)
goto out; goto out;
} }
orig_root = seaf_fs_manager_get_seafdir_id_by_path (seaf->fs_mgr,
orig_repo->store_id,
orig_repo->version,
orig_head->root_id,
vinfo->path,
NULL);
if (!orig_root) {
seaf_warning ("Cannot find seafdir for repo %.10s path %s.\n",
vinfo->origin_repo_id, vinfo->path);
ret = -1;
goto out;
}
if (strcmp (root, orig_root) == 0) { if (strcmp (root, orig_root) == 0) {
/* Nothing to merge. */ /* Nothing to merge. */
seaf_debug ("Nothing to merge.\n"); seaf_debug ("Nothing to merge.\n");

View File

@@ -1,4 +1,5 @@
import pytest import pytest
import time
from seaserv import seafile_api as api from seaserv import seafile_api as api
from seaserv import ccnet_api from seaserv import ccnet_api
@@ -114,6 +115,8 @@ def test_share_dir_to_user(repo, permission):
assert api.del_file(repo.id, '/', 'dir1', USER) == 0 assert api.del_file(repo.id, '/', 'dir1', USER) == 0
assert api.unshare_subdir_for_user(repo.id, '/dir2', USER, USER2) == 0 assert api.unshare_subdir_for_user(repo.id, '/dir2', USER, USER2) == 0
time.sleep(1)
assert api.get_shared_repo_by_path(repo.id, '/dir1', USER2) is None assert api.get_shared_repo_by_path(repo.id, '/dir1', USER2) is None
assert api.get_shared_repo_by_path(repo.id, '/dir2', USER2) is None assert api.get_shared_repo_by_path(repo.id, '/dir2', USER2) is None
@@ -135,6 +138,8 @@ def test_share_dir_to_group(repo, group, permission):
assert api.del_file(repo.id, '/', 'dir1', USER) == 0 assert api.del_file(repo.id, '/', 'dir1', USER) == 0
assert api.unshare_subdir_for_group(repo.id, '/dir2', USER, group.id) == 0 assert api.unshare_subdir_for_group(repo.id, '/dir2', USER, group.id) == 0
time.sleep(1)
assert api.check_permission(v_repo_id_1, USER2) is None assert api.check_permission(v_repo_id_1, USER2) is None
assert api.check_permission(v_repo_id_2, USER2) is None assert api.check_permission(v_repo_id_2, USER2) is None