1
0
mirror of https://github.com/haiwen/seafile-server.git synced 2025-08-01 23:33:42 +00:00

A few optimizations for SQL queries related to repos.

- Support paging for listing owned repos
- Reduce SQL queries for getting and listing repos.
This commit is contained in:
Jonathan Xu 2017-04-06 14:58:59 +08:00
parent 345d4ad286
commit a9ed059634
8 changed files with 163 additions and 61 deletions

View File

@ -77,6 +77,7 @@ convert_repo (SeafRepo *r)
g_object_set (repo, "store_id", r->store_id,
"repaired", r->repaired,
"size", r->size, "file_count", r->file_count, NULL);
g_object_set (repo, "is_corrupted", r->is_corrupted, NULL);
#endif
#ifndef SEAFILE_SERVER
@ -1973,32 +1974,32 @@ seafile_get_orphan_repo_list(GError **error)
}
GList *
seafile_list_owned_repos (const char *email, int ret_corrupted, GError **error)
seafile_list_owned_repos (const char *email, int ret_corrupted,
int start, int limit, GError **error)
{
GList *ret = NULL;
GList *repos, *ptr;
char *repo_id = NULL;
int is_shared;
repos = seaf_repo_manager_get_repos_by_owner (seaf->repo_mgr, email, ret_corrupted);
repos = seaf_repo_manager_get_repos_by_owner (seaf->repo_mgr, email, ret_corrupted,
start, limit);
ret = convert_repo_list (repos);
for (ptr = ret; ptr; ptr = ptr->next) {
g_object_get (ptr->data, "repo_id", &repo_id, NULL);
is_shared = seaf_share_manager_is_repo_shared (seaf->share_mgr, repo_id);
if (is_shared < 0) {
g_free (repo_id);
break;
} else {
g_object_set (ptr->data, "is_shared", is_shared, NULL);
g_free (repo_id);
}
}
/* for (ptr = ret; ptr; ptr = ptr->next) { */
/* g_object_get (ptr->data, "repo_id", &repo_id, NULL); */
/* is_shared = seaf_share_manager_is_repo_shared (seaf->share_mgr, repo_id); */
/* if (is_shared < 0) { */
/* g_free (repo_id); */
/* break; */
/* } else { */
/* g_object_set (ptr->data, "is_shared", is_shared, NULL); */
/* g_free (repo_id); */
/* } */
/* } */
while (ptr) {
g_object_set (ptr->data, "is_shared", FALSE, NULL);
ptr = ptr->prev;
}
/* while (ptr) { */
/* g_object_set (ptr->data, "is_shared", FALSE, NULL); */
/* ptr = ptr->prev; */
/* } */
for(ptr = repos; ptr; ptr = ptr->next) {
seaf_repo_unref ((SeafRepo *)ptr->data);

View File

@ -446,7 +446,8 @@ GList *
seafile_get_orphan_repo_list(GError **error);
GList *
seafile_list_owned_repos (const char *email, int ret_corrupted, GError **error);
seafile_list_owned_repos (const char *email, int ret_corrupted, int start, int limit,
GError **error);
/**
* seafile_add_chunk_server:

View File

@ -72,6 +72,7 @@ func_table = [
[ "objlist", ["string"] ],
[ "objlist", ["string", "int"] ],
[ "objlist", ["string", "int", "int"] ],
[ "objlist", ["string", "int", "int", "int"] ],
[ "objlist", ["string", "int", "string"] ],
[ "objlist", ["string", "string"] ],
[ "objlist", ["string", "string", "string"] ],

View File

@ -375,8 +375,8 @@ class SeafServerThreadedRpcClient(ccnet.RpcClientBase):
pass
get_orphan_repo_list = seafile_get_orphan_repo_list
@searpc_func("objlist", ["string", "int"])
def seafile_list_owned_repos(user_id, ret_corrupted):
@searpc_func("objlist", ["string", "int", "int", "int"])
def seafile_list_owned_repos(user_id, ret_corrupted, start, limit):
pass
list_owned_repos = seafile_list_owned_repos

View File

@ -107,12 +107,13 @@ class SeafileAPI(object):
"""
return seafserv_threaded_rpc.get_repo_owner(repo_id)
def get_owned_repo_list(self, username, ret_corrupted=False):
def get_owned_repo_list(self, username, ret_corrupted=False, start=-1, limit=-1):
"""
Return: a list of Repo objects
"""
return seafserv_threaded_rpc.list_owned_repos(username,
1 if ret_corrupted else 0)
1 if ret_corrupted else 0,
start, limit)
def get_orphan_repo_list(self):
return seafserv_threaded_rpc.get_orphan_repo_list()

View File

@ -635,15 +635,24 @@ gboolean
create_repo_fill_size (SeafDBRow *row, void *data)
{
SeafRepo **repo = data;
SeafBranch *head;
const char *repo_id = seaf_db_row_get_column_text (row, 0);
gint64 size = seaf_db_row_get_column_int64 (row, 1);
const char *commit_id = seaf_db_row_get_column_text (row, 2);
*repo = seaf_repo_new (repo_id, NULL, NULL);
if (!*repo)
return FALSE;
if (!commit_id) {
(*repo)->is_corrupted = TRUE;
return FALSE;
}
(*repo)->size = size;
head = seaf_branch_new ("master", repo_id, commit_id);
(*repo)->head = head;
return TRUE;
}
@ -652,8 +661,18 @@ static SeafRepo*
get_repo_from_db (SeafRepoManager *mgr, const char *id, gboolean *db_err)
{
SeafRepo *repo = NULL;
const char *sql = "SELECT r.repo_id, s.size FROM Repo r left join RepoSize s "
"ON r.repo_id = s.repo_id WHERE r.repo_id = ?";
const char *sql;
if (seaf_db_type(mgr->seaf->db) != SEAF_DB_TYPE_PGSQL)
sql = "SELECT r.repo_id, s.size, b.commit_id FROM "
"Repo r LEFT JOIN Branch b ON r.repo_id = b.repo_id "
"LEFT JOIN RepoSize s ON r.repo_id = s.repo_id "
"WHERE r.repo_id = ? AND b.name = 'master'";
else
sql = "SELECT r.repo_id, s.\"size\", b.commit_id FROM "
"Repo r LEFT JOIN Branch b ON r.repo_id = b.repo_id "
"LEFT JOIN RepoSize s ON r.repo_id = s.repo_id "
"WHERE r.repo_id = ? AND b.name = 'master'";
int ret = seaf_db_statement_foreach_row (mgr->seaf->db, sql,
create_repo_fill_size, &repo,
@ -668,15 +687,20 @@ SeafRepo*
seaf_repo_manager_get_repo (SeafRepoManager *manager, const gchar *id)
{
int len = strlen(id);
gboolean db_err = FALSE;
SeafRepo *repo = NULL;
gboolean has_err = FALSE;
if (len >= 37)
return NULL;
repo = get_repo_from_db (manager, id, &db_err);
repo = get_repo_from_db (manager, id, &has_err);
if (repo) {
if (repo->is_corrupted) {
seaf_repo_unref (repo);
return NULL;
}
load_repo (manager, repo);
if (repo->is_corrupted) {
seaf_repo_unref (repo);
@ -691,20 +715,24 @@ SeafRepo*
seaf_repo_manager_get_repo_ex (SeafRepoManager *manager, const gchar *id)
{
int len = strlen(id);
gboolean db_err = FALSE;
gboolean has_err = FALSE;
SeafRepo *ret = NULL;
if (len >= 37)
return NULL;
ret = get_repo_from_db (manager, id, &db_err);
if (db_err) {
ret = get_repo_from_db (manager, id, &has_err);
if (has_err) {
ret = seaf_repo_new(id, NULL, NULL);
ret->is_corrupted = TRUE;
return ret;
}
if (ret) {
if (ret->is_corrupted) {
return ret;
}
load_repo (manager, ret);
}
@ -765,21 +793,19 @@ seaf_repo_manager_branch_repo_unmap (SeafRepoManager *manager, SeafBranch *branc
static void
load_repo_commit (SeafRepoManager *manager,
SeafRepo *repo,
SeafBranch *branch)
SeafRepo *repo)
{
SeafCommit *commit;
commit = seaf_commit_manager_get_commit_compatible (manager->seaf->commit_mgr,
repo->id,
branch->commit_id);
repo->head->commit_id);
if (!commit) {
seaf_warning ("Commit %s:%s is missing\n", repo->id, branch->commit_id);
seaf_warning ("Commit %s:%s is missing\n", repo->id, repo->head->commit_id);
repo->is_corrupted = TRUE;
return;
}
set_head_common (repo, branch);
seaf_repo_from_commit (repo, commit);
seaf_commit_unref (commit);
@ -788,18 +814,9 @@ load_repo_commit (SeafRepoManager *manager,
static void
load_repo (SeafRepoManager *manager, SeafRepo *repo)
{
SeafBranch *branch;
repo->manager = manager;
branch = seaf_branch_manager_get_branch (seaf->branch_mgr, repo->id, "master");
if (!branch) {
seaf_warning ("Failed to get master branch of repo %.8s.\n", repo->id);
repo->is_corrupted = TRUE;
} else {
load_repo_commit (manager, repo, branch);
seaf_branch_unref (branch);
}
load_repo_commit (manager, repo);
if (repo->is_corrupted) {
return;
@ -2032,36 +2049,115 @@ seaf_repo_manager_get_orphan_repo_list (SeafRepoManager *mgr)
return ret;
}
gboolean
collect_repos_fill_size_commit (SeafDBRow *row, void *data)
{
GList **prepos = data;
SeafRepo *repo;
SeafBranch *head;
const char *repo_id = seaf_db_row_get_column_text (row, 0);
gint64 size = seaf_db_row_get_column_int64 (row, 1);
const char *commit_id = seaf_db_row_get_column_text (row, 2);
repo = seaf_repo_new (repo_id, NULL, NULL);
if (!repo)
return TRUE;
if (!commit_id) {
repo->is_corrupted = TRUE;
goto out;
}
repo->size = size;
head = seaf_branch_new ("master", repo_id, commit_id);
repo->head = head;
out:
*prepos = g_list_prepend (*prepos, repo);
return TRUE;
}
GList *
seaf_repo_manager_get_repos_by_owner (SeafRepoManager *mgr,
const char *email,
int ret_corrupted)
int ret_corrupted,
int start,
int limit)
{
GList *id_list = NULL, *ptr;
GList *repo_list = NULL, *ptr;
GList *ret = NULL;
char *sql;
SeafRepo *repo = NULL;
int db_type = seaf_db_type(mgr->seaf->db);
sql = "SELECT repo_id FROM RepoOwner WHERE owner_id=?";
if (start == -1 && limit == -1) {
if (db_type != SEAF_DB_TYPE_PGSQL)
sql = "SELECT o.repo_id, s.size, b.commit_id FROM "
"RepoOwner o LEFT JOIN RepoSize s ON o.repo_id = s.repo_id "
"LEFT JOIN Branch b ON o.repo_id = b.repo_id "
"WHERE owner_id=? AND "
"o.repo_id NOT IN (SELECT v.repo_id FROM VirtualRepo v)";
else
sql = "SELECT o.repo_id, s.\"size\", b.commit_id FROM "
"RepoOwner o LEFT JOIN RepoSize s ON o.repo_id = s.repo_id "
"LEFT JOIN Branch b ON o.repo_id = b.repo_id "
"WHERE owner_id=? AND "
"o.repo_id NOT IN (SELECT v.repo_id FROM VirtualRepo v)";
if (seaf_db_statement_foreach_row (mgr->seaf->db, sql,
collect_repo_id, &id_list,
1, "string", email) < 0)
return NULL;
if (seaf_db_statement_foreach_row (mgr->seaf->db, sql,
collect_repos_fill_size_commit, &repo_list,
1, "string", email) < 0)
return NULL;
} else {
if (db_type != SEAF_DB_TYPE_PGSQL)
sql = "SELECT o.repo_id, s.size, b.commit_id FROM "
"RepoOwner o LEFT JOIN RepoSize s ON o.repo_id = s.repo_id "
"LEFT JOIN Branch b ON o.repo_id = b.repo_id "
"WHERE owner_id=? AND "
"o.repo_id NOT IN (SELECT v.repo_id FROM VirtualRepo v) "
"LIMIT ? OFFSET ?";
else
sql = "SELECT o.repo_id, s.\"size\", b.commit_id FROM "
"RepoOwner o LEFT JOIN RepoSize s ON o.repo_id = s.repo_id "
"LEFT JOIN Branch b ON o.repo_id = b.repo_id "
"WHERE owner_id=? AND "
"o.repo_id NOT IN (SELECT v.repo_id FROM VirtualRepo v) "
"LIMIT ? OFFSET ?";
for (ptr = id_list; ptr; ptr = ptr->next) {
char *repo_id = ptr->data;
if (seaf_db_statement_foreach_row (mgr->seaf->db, sql,
collect_repos_fill_size_commit,
&repo_list,
3, "string", email,
"int", limit,
"int", start) < 0) {
return NULL;
}
}
for (ptr = repo_list; ptr; ptr = ptr->next) {
repo = ptr->data;
if (ret_corrupted) {
repo = seaf_repo_manager_get_repo_ex (mgr, repo_id);
if (!repo->is_corrupted)
load_repo (mgr, repo);
} else {
repo = seaf_repo_manager_get_repo (mgr, repo_id);
if (repo->is_corrupted) {
seaf_repo_unref (repo);
continue;
}
load_repo (mgr, repo);
if (repo->is_corrupted) {
seaf_repo_unref (repo);
continue;
}
}
if (repo != NULL)
ret = g_list_prepend (ret, repo);
}
string_list_free (id_list);
return ret;
}

View File

@ -552,7 +552,9 @@ seaf_repo_manager_get_orphan_repo_list (SeafRepoManager *mgr);
GList *
seaf_repo_manager_get_repos_by_owner (SeafRepoManager *mgr,
const char *email,
int ret_corrupted);
int ret_corrupted,
int start,
int limit);
GList *
seaf_repo_manager_get_repo_ids_by_owner (SeafRepoManager *mgr,

View File

@ -174,7 +174,7 @@ static void start_rpc_service (CcnetClient *client, int cloud_mode)
searpc_server_register_function ("seafserv-threaded-rpcserver",
seafile_list_owned_repos,
"seafile_list_owned_repos",
searpc_signature_objlist__string_int());
searpc_signature_objlist__string_int_int_int());
searpc_server_register_function ("seafserv-threaded-rpcserver",
seafile_server_repo_size,