Fix a few bugs related to deleting repos on server.

Server:
- Delete entries from Branch and RepoHead tables;
- Restore entries to Branch and RepoHead tables from repo trash.
- When client checks head commit, return DELTED if no entry in
  Repo table.
- When client checks upload/download permission, return DELETED
  if repo doesn't exist.

Client:
- Handle repo DELETED situation in upload/download thread.
This commit is contained in:
Jiaqiang Xu 2015-06-27 15:59:17 +08:00
parent ba7373372d
commit 91928b9396
6 changed files with 106 additions and 51 deletions

View File

@ -37,6 +37,7 @@
#define HTTP_NOT_FOUND 404
#define HTTP_NO_QUOTA 443
#define HTTP_REPO_DELETED 444
#define HTTP_REPO_CORRUPTED 445
#define HTTP_INTERNAL_SERVER_ERROR 500
#define RESET_BYTES_INTERVAL_MSEC 1000
@ -907,6 +908,10 @@ handle_http_errors (HttpTxTask *task, int status)
task->error = HTTP_TASK_ERR_SERVER;
else if (status == HTTP_NO_QUOTA)
task->error = HTTP_TASK_ERR_NO_QUOTA;
else if (status == HTTP_REPO_DELETED)
task->error = HTTP_TASK_ERR_REPO_DELETED;
else if (status == HTTP_REPO_CORRUPTED)
task->error = HTTP_TASK_ERR_REPO_CORRUPTED;
else
task->error = HTTP_TASK_ERR_UNKNOWN;
}

View File

@ -43,6 +43,8 @@ enum HttpTaskError {
HTTP_TASK_ERR_WRITE_LOCAL_DATA,
HTTP_TASK_ERR_NO_QUOTA,
HTTP_TASK_ERR_FILES_LOCKED,
HTTP_TASK_ERR_REPO_DELETED,
HTTP_TASK_ERR_REPO_CORRUPTED,
HTTP_TASK_ERR_UNKNOWN,
N_HTTP_TASK_ERROR,
};

View File

@ -1288,6 +1288,24 @@ remove_blocks_done (void *vtask)
transition_sync_state (task, SYNC_STATE_DONE);
}
static void
on_repo_deleted_on_server (SyncTask *task, SeafRepo *repo)
{
seaf_sync_manager_set_task_error (task, SYNC_ERROR_NOREPO);
seaf_warning ("repo %s(%.8s) not found on server\n",
repo->name, repo->id);
if (!seafile_session_config_get_allow_repo_not_found_on_server(seaf)) {
seaf_message ("remove repo %s(%.8s) since it's deleted on relay\n",
repo->name, repo->id);
seaf_mq_manager_publish_notification (seaf->mq_mgr,
"repo.deleted_on_relay",
repo->name);
seaf_repo_manager_del_repo (seaf->repo_mgr, repo);
}
}
static void
update_sync_status (SyncTask *task)
{
@ -1339,21 +1357,8 @@ update_sync_status (SyncTask *task)
/* If repo doesn't exist on relay and we have "master",
* it was deleted on relay. In this case we remove this repo.
*/
else {
seaf_sync_manager_set_task_error (task, SYNC_ERROR_NOREPO);
seaf_warning ("repo %s(%.8s) not found on server\n",
repo->name, repo->id);
if (!seafile_session_config_get_allow_repo_not_found_on_server(seaf)) {
seaf_debug ("remove repo %s(%.8s) since it's deleted on relay\n",
repo->name, repo->id);
seaf_mq_manager_publish_notification (seaf->mq_mgr,
"repo.deleted_on_relay",
repo->name);
seaf_repo_manager_del_repo (seaf->repo_mgr, repo);
}
}
else
on_repo_deleted_on_server (task, repo);
} else {
/* branch deleted on relay */
if (info->branch_deleted_on_relay) {
@ -1457,19 +1462,7 @@ update_sync_status_v2 (SyncTask *task)
if (info->repo_corrupted) {
seaf_sync_manager_set_task_error (task, SYNC_ERROR_REPO_CORRUPT);
} else if (info->deleted_on_relay) {
seaf_sync_manager_set_task_error (task, SYNC_ERROR_NOREPO);
seaf_warning ("repo %s(%.8s) not found on server\n",
repo->name, repo->id);
if (!seafile_session_config_get_allow_repo_not_found_on_server(seaf)) {
seaf_message ("remove repo %s(%.8s) since it's deleted on relay\n",
repo->name, repo->id);
seaf_mq_manager_publish_notification (seaf->mq_mgr,
"repo.deleted_on_relay",
repo->name);
seaf_repo_manager_del_repo (seaf->repo_mgr, repo);
}
on_repo_deleted_on_server (task, repo);
} else {
/* If local head is the same as remote head, already in sync. */
if (strcmp (local->commit_id, info->head_commit) == 0) {
@ -2817,6 +2810,8 @@ on_repo_http_fetched (SeafileSession *seaf,
}
} else if (tx_task->error == HTTP_TASK_ERR_FILES_LOCKED) {
seaf_sync_manager_set_task_error (task, SYNC_ERROR_FILES_LOCKED);
} else if (tx_task->error == HTTP_TASK_ERR_REPO_DELETED) {
on_repo_deleted_on_server (task, task->repo);
} else
seaf_sync_manager_set_task_error (task, SYNC_ERROR_FETCH);
}
@ -2864,6 +2859,8 @@ on_repo_http_uploaded (SeafileSession *seaf,
send_sync_error_notification (task->repo, "sync.quota_full");
task->repo->quota_full_notified = 1;
}
} else if (tx_task->error == HTTP_TASK_ERR_REPO_DELETED) {
on_repo_deleted_on_server (task, task->repo);
} else
seaf_sync_manager_set_task_error (task, SYNC_ERROR_UPLOAD);
}

View File

@ -523,6 +523,16 @@ get_check_permission_cb (evhtp_request_t *req, void *arg)
const char *token;
SeafRepo *repo = NULL;
repo = seaf_repo_manager_get_repo_ex (seaf->repo_mgr, repo_id);
if (!repo) {
evhtp_send_reply (req, SEAF_HTTP_RES_REPO_DELETED);
goto out;
}
if (repo->is_corrupted || repo->repaired) {
evhtp_send_reply (req, SEAF_HTTP_RES_REPO_CORRUPTED);
goto out;
}
int token_status = validate_token (htp_server, req, repo_id, &username, TRUE);
if (token_status != EVHTP_RES_OK) {
evhtp_send_reply (req, token_status);
@ -538,12 +548,6 @@ get_check_permission_cb (evhtp_request_t *req, void *arg)
goto out;
}
repo = seaf_repo_manager_get_repo (seaf->repo_mgr, repo_id);
if (!repo || repo->repaired) {
evhtp_send_reply (req, SEAF_HTTP_RES_REPO_CORRUPTED);
goto out;
}
ip = get_client_ip_addr (req);
if (!ip) {
evhtp_send_reply (req, EVHTP_RES_SERVERR);
@ -659,16 +663,31 @@ get_head_commit_cb (evhtp_request_t *req, void *arg)
HttpServer *htp_server = arg;
char **parts = g_strsplit (req->uri->path->full + 1, "/", 0);
char *repo_id = parts[1];
gboolean db_err = FALSE, exists = TRUE;
int token_status;
char commit_id[41];
char *sql;
int token_status = validate_token (htp_server, req, repo_id, NULL, FALSE);
sql = "SELECT 1 FROM Repo WHERE repo_id=?";
exists = seaf_db_statement_exists (seaf->db, sql, &db_err, 1, "string", repo_id);
if (!exists) {
if (db_err) {
seaf_warning ("DB error when check repo existence.\n");
evbuffer_add_printf (req->buffer_out,
"{\"is_corrupted\": 1}");
evhtp_send_reply (req, EVHTP_RES_OK);
goto out;
}
evhtp_send_reply (req, SEAF_HTTP_RES_REPO_DELETED);
goto out;
}
token_status = validate_token (htp_server, req, repo_id, NULL, FALSE);
if (token_status != EVHTP_RES_OK) {
evhtp_send_reply (req, token_status);
goto out;
}
char commit_id[41];
char *sql;
commit_id[0] = 0;
sql = "SELECT commit_id FROM Branch WHERE name='master' AND repo_id=?";

View File

@ -128,7 +128,8 @@ send_repo_branch_info (void *vprocessor)
commit_id[0] = 0;
sql = "SELECT commit_id FROM Branch WHERE name='master' AND repo_id=?";
sql = "SELECT commit_id FROM Repo r, Branch b "
"WHERE name='master' AND r.repo_id=? AND r.repo_id = b.repo_id";
if (seaf_db_statement_foreach_row (seaf->db, sql,
get_branch, commit_id,
1, "string", priv->repo_id) < 0) {

View File

@ -566,7 +566,15 @@ del_repo:
return -1;
}
/* Repo branches are not removed at this point. */
/* remove branch */
GList *p;
GList *branch_list = seaf_branch_manager_get_branch_list (seaf->branch_mgr, repo_id);
for (p = branch_list; p; p = p->next) {
SeafBranch *b = (SeafBranch *)p->data;
seaf_repo_manager_branch_repo_unmap (mgr, b);
seaf_branch_manager_del_branch (seaf->branch_mgr, repo_id, b->name);
}
seaf_branch_list_free (branch_list);
seaf_db_statement_query (mgr->seaf->db, "DELETE FROM RepoOwner WHERE repo_id = ?",
1, "string", repo_id);
@ -2140,7 +2148,7 @@ seaf_repo_manager_get_repo_from_trash (SeafRepoManager *mgr,
char *sql;
int rc;
sql = "SELECT repo_id, repo_name, head_id, owner_id, size FROM RepoTrash "
sql = "SELECT repo_id, repo_name, head_id, owner_id, size, del_time FROM RepoTrash "
"WHERE repo_id = ?";
rc = seaf_db_statement_foreach_row (mgr->seaf->db, sql,
collect_trash_repo, &trash_repos,
@ -2171,16 +2179,6 @@ seaf_repo_manager_del_repo_from_trash (SeafRepoManager *mgr,
return -1;
}
/* remove branch */
GList *p;
GList *branch_list = seaf_branch_manager_get_branch_list (seaf->branch_mgr, repo_id);
for (p = branch_list; p; p = p->next) {
SeafBranch *b = (SeafBranch *)p->data;
seaf_repo_manager_branch_repo_unmap (mgr, b);
seaf_branch_manager_del_branch (seaf->branch_mgr, repo_id, b->name);
}
seaf_branch_list_free (branch_list);
seaf_db_statement_query (mgr->seaf->db,
"DELETE FROM RepoTrash WHERE repo_id = ?",
1, "string", repo_id);
@ -2287,6 +2285,39 @@ seaf_repo_manager_restore_repo_from_trash (SeafRepoManager *mgr,
}
}
exists = seaf_db_trans_check_for_existence (trans,
"SELECT 1 FROM Branch WHERE repo_id=?",
&db_err, 1, "string", repo_id);
if (!exists) {
ret = seaf_db_trans_query (trans,
"INSERT INTO Branch VALUES ('master', ?, ?)",
2, "string", repo_id,
"string", seafile_trash_repo_get_head_id(repo));
if (ret < 0) {
g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL,
"DB error: Insert Branch.");
seaf_db_rollback (trans);
seaf_db_trans_close (trans);
goto out;
}
}
exists = seaf_db_trans_check_for_existence (trans,
"SELECT 1 FROM RepoHead WHERE repo_id=?",
&db_err, 1, "string", repo_id);
if (!exists) {
ret = seaf_db_trans_query (trans,
"INSERT INTO RepoHead VALUES (?, 'master')",
1, "string", repo_id);
if (ret < 0) {
g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL,
"DB error: Set RepoHead.");
seaf_db_rollback (trans);
seaf_db_trans_close (trans);
goto out;
}
}
ret = seaf_db_trans_query (trans,
"DELETE FROM RepoTrash WHERE repo_id = ?",
1, "string", repo_id);