Merge pull request #2234 from haiwen/refactor-sync-error

Refactor sync error
This commit is contained in:
Jiaqiang Xu 2019-08-27 15:42:42 +08:00 committed by GitHub
commit afe5c026af
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 487 additions and 636 deletions

View File

@ -335,8 +335,7 @@ seafile_get_clone_tasks (GError **error)
task = ptr->data;
t = g_object_new (SEAFILE_TYPE_CLONE_TASK,
"state", clone_task_state_to_str(task->state),
"error_str", clone_task_error_to_str(task->error),
"err_detail", task->err_detail,
"error_str", task->error,
"repo_id", task->repo_id,
"repo_name", task->repo_name,
"worktree", task->worktree,
@ -368,7 +367,6 @@ convert_http_task (HttpTxTask *task)
"repo_id", task->repo_id,
"state", http_task_state_to_str(task->state),
"rt_state", http_task_rt_state_to_str(task->runtime_state),
"error_str", http_task_error_str(task->error),
NULL);
if (task->type == HTTP_TASK_TYPE_DOWNLOAD) {
@ -427,31 +425,6 @@ seafile_get_download_rate(GError **error)
return seaf->sync_mgr->last_recv_bytes;
}
GObject *
seafile_get_repo_sync_info (const char *repo_id, GError **error)
{
SyncInfo *info;
info = seaf_sync_manager_get_sync_info (seaf->sync_mgr, repo_id);
if (!info)
return NULL;
SeafileSyncInfo *sinfo;
sinfo = g_object_new (SEAFILE_TYPE_SYNC_INFO,
"repo_id", info->repo_id,
"head_commit", info->head_commit,
"deleted_on_relay", info->deleted_on_relay,
"need_fetch", info->need_fetch,
"need_upload", info->need_upload,
"need_merge", info->need_merge,
/* "last_sync_time", info->last_sync_time, */
NULL);
return (GObject *)sinfo;
}
GObject *
seafile_get_repo_sync_task (const char *repo_id, GError **error)
{
@ -482,44 +455,13 @@ seafile_get_repo_sync_task (const char *repo_id, GError **error)
s_task = g_object_new (SEAFILE_TYPE_SYNC_TASK,
"force_upload", task->is_manual_sync,
"state", sync_state,
"error", sync_error_to_str(task->error),
"err_detail", task->err_detail,
"error", task->error,
"repo_id", info->repo_id,
NULL);
return (GObject *)s_task;
}
GList *
seafile_get_sync_task_list (GError **error)
{
GHashTable *sync_info_tbl = seaf->sync_mgr->sync_infos;
GHashTableIter iter;
SeafileSyncTask *s_task;
GList *task_list = NULL;
gpointer key, value;
g_hash_table_iter_init (&iter, sync_info_tbl);
while (g_hash_table_iter_next (&iter, &key, &value)) {
SyncInfo *info = value;
if (!info->in_sync)
continue;
SyncTask *task = info->current_task;
if (!task)
continue;
s_task = g_object_new (SEAFILE_TYPE_SYNC_TASK,
"force_upload", task->is_manual_sync,
"state", sync_state_to_str(task->state),
"error", sync_error_to_str(task->error),
"repo_id", info->repo_id,
NULL);
task_list = g_list_prepend (task_list, s_task);
}
return task_list;
}
int
seafile_set_repo_property (const char *repo_id,
const char *key,

View File

@ -31,7 +31,8 @@ noinst_HEADERS = \
sync-status-tree.h \
filelock-mgr.h \
set-perm.h \
change-set.h
change-set.h \
seafile-error-impl.h
if LINUX
wt_monitor_src = wt-monitor.c wt-monitor-linux.c wt-monitor-structs.c
@ -53,6 +54,7 @@ common_src = \
../common/seafile-crypt.c ../common/diff-simple.c $(wt_monitor_src) \
clone-mgr.c \
seafile-config.c \
seafile-error.c \
../common/branch-mgr.c ../common/fs-mgr.c \
repo-mgr.c ../common/commit-mgr.c \
../common/log.c \

View File

@ -5,7 +5,7 @@
#define DEBUG_FLAG SEAFILE_DEBUG_SYNC
#include "log.h"
#include "seafile-error.h"
#include "seafile-error-impl.h"
#include "seafile-session.h"
#include "vc-utils.h"
#include "utils.h"
@ -47,17 +47,6 @@ static const char *state_str[] = {
"merge",
};
static const char *error_str[] = {
"ok",
"check server",
"index",
"fetch",
"password",
"checkout",
"merge",
"internal",
};
static void
mark_clone_done_v2 (SeafRepo *repo, CloneTask *task)
{
@ -71,7 +60,7 @@ mark_clone_done_v2 (SeafRepo *repo, CloneTask *task)
if (!local) {
seaf_warning ("Cannot get branch local for repo %s(%.10s).\n",
repo->name, repo->id);
transition_to_error (task, CLONE_ERROR_INTERNAL);
transition_to_error (task, SYNC_ERROR_ID_LOCAL_DATA_CORRUPT);
return;
}
/* Set repo head to mark checkout done. */
@ -83,7 +72,7 @@ mark_clone_done_v2 (SeafRepo *repo, CloneTask *task)
repo,
task->passwd) < 0) {
seaf_warning ("[Clone mgr] failed to set passwd for %s.\n", repo->id);
transition_to_error (task, CLONE_ERROR_INTERNAL);
transition_to_error (task, SYNC_ERROR_ID_GENERAL_ERROR);
return;
}
}
@ -106,7 +95,7 @@ mark_clone_done_v2 (SeafRepo *repo, CloneTask *task)
if (seaf_wt_monitor_watch_repo (seaf->wt_monitor,
repo->id, repo->worktree) < 0) {
seaf_warning ("failed to watch repo %s(%.10s).\n", repo->name, repo->id);
transition_to_error (task, CLONE_ERROR_INTERNAL);
transition_to_error (task, SYNC_ERROR_ID_GENERAL_ERROR);
return;
}
}
@ -135,7 +124,7 @@ start_clone_v2 (CloneTask *task)
g_mkdir_with_parents (task->worktree, 0777) < 0) {
seaf_warning ("[clone mgr] Failed to create worktree %s.\n",
task->worktree);
transition_to_error (task, CLONE_ERROR_FETCH);
transition_to_error (task, SYNC_ERROR_ID_WRITE_LOCAL_DATA);
return;
}
@ -159,7 +148,7 @@ start_clone_v2 (CloneTask *task)
if (add_transfer_task (task, &error) == 0)
transition_state (task, CLONE_STATE_FETCH);
else
transition_to_error (task, CLONE_ERROR_FETCH);
transition_to_error (task, SYNC_ERROR_ID_NOT_ENOUGH_MEMORY);
}
static void
@ -176,9 +165,7 @@ check_head_commit_done (HttpHeadCommit *result, void *user_data)
memcpy (task->server_head_id, result->head_commit, 40);
start_clone_v2 (task);
} else {
transition_to_error (task, CLONE_ERROR_CHECK_SERVER);
if (result->error_code != 0)
task->err_detail = g_strdup(http_task_error_str(result->error_code));
transition_to_error (task, result->error_code);
}
}
@ -194,7 +181,7 @@ http_check_head_commit (CloneTask *task)
check_head_commit_done,
task);
if (ret < 0)
transition_to_error (task, CLONE_ERROR_CHECK_SERVER);
transition_to_error (task, SYNC_ERROR_ID_NOT_ENOUGH_MEMORY);
}
static char *
@ -241,9 +228,7 @@ check_http_fileserver_protocol_done (HttpProtocolVersion *result, void *user_dat
http_check_head_commit (task);
} else {
/* Wait for periodic retry. */
transition_to_error (task, CLONE_ERROR_CHECK_SERVER);
if (result->error_code != 0)
task->err_detail = g_strdup(http_task_error_str(result->error_code));
transition_to_error (task, result->error_code);
}
}
@ -268,13 +253,11 @@ check_http_protocol_done (HttpProtocolVersion *result, void *user_data)
TRUE,
check_http_fileserver_protocol_done,
task) < 0)
transition_to_error (task, CLONE_ERROR_CHECK_SERVER);
transition_to_error (task, SYNC_ERROR_ID_NOT_ENOUGH_MEMORY);
g_free (host_fileserver);
} else {
/* Wait for periodic retry. */
transition_to_error (task, CLONE_ERROR_CHECK_SERVER);
if (result->error_code != 0)
task->err_detail = g_strdup(http_task_error_str(result->error_code));
transition_to_error (task, result->error_code);
}
}
@ -286,7 +269,7 @@ check_http_protocol (CloneTask *task)
FALSE,
check_http_protocol_done,
task) < 0) {
transition_to_error (task, CLONE_ERROR_CHECK_SERVER);
transition_to_error (task, SYNC_ERROR_ID_NOT_ENOUGH_MEMORY);
return;
}
@ -317,6 +300,7 @@ clone_task_new (const char *repo_id,
task->repo_name = g_strdup(repo_name);
if (passwd)
task->passwd = g_strdup (passwd);
task->error = SYNC_ERROR_ID_NO_ERROR;
return task;
}
@ -335,7 +319,6 @@ clone_task_free (CloneTask *task)
g_free (task->random_key);
g_free (task->server_url);
g_free (task->effective_url);
g_free (task->err_detail);
g_free (task);
}
@ -348,14 +331,6 @@ clone_task_state_to_str (int state)
return state_str[state];
}
const char *
clone_task_error_to_str (int error)
{
if (error < 0 || error >= N_CLONE_ERRORS)
return NULL;
return error_str[error];
}
SeafCloneManager *
seaf_clone_manager_new (SeafileSession *session)
{
@ -521,7 +496,7 @@ restart_task (sqlite3_stmt *stmt, void *data)
if (task->server_url) {
check_http_protocol (task);
} else {
transition_to_error (task, CLONE_ERROR_CHECK_SERVER);
transition_to_error (task, SYNC_ERROR_ID_GENERAL_ERROR);
return TRUE;
}
}
@ -579,10 +554,8 @@ static int check_connect_pulse (void *vmanager)
task = value;
if (task->state == CLONE_STATE_ERROR &&
task->repo_version > 0 &&
is_http_task_net_error (task->err_detail)) {
g_free (task->err_detail);
task->err_detail = NULL;
task->error = 0;
sync_error_level (task->error) == SYNC_ERROR_LEVEL_NETWORK) {
task->error = SYNC_ERROR_ID_NO_ERROR;
check_http_protocol (task);
}
}
@ -732,7 +705,7 @@ transition_to_error (CloneTask *task, int error)
seaf_message ("Transition clone state for %.8s from [%s] to [error]: %s.\n",
task->repo_id,
state_str[task->state],
error_str[error]);
sync_error_id_to_str(error));
task->state = CLONE_STATE_ERROR;
task->error = error;
@ -1538,8 +1511,7 @@ on_repo_http_fetched (SeafileSession *seaf,
transition_state (task, CLONE_STATE_CANCELED);
return;
} else if (tx_task->state == HTTP_TASK_STATE_ERROR) {
transition_to_error (task, CLONE_ERROR_FETCH);
task->err_detail = g_strdup(http_task_error_str(tx_task->error));
transition_to_error (task, tx_task->error);
return;
}
@ -1548,7 +1520,7 @@ on_repo_http_fetched (SeafileSession *seaf,
if (repo == NULL) {
seaf_warning ("[Clone mgr] cannot find repo %s after fetched.\n",
tx_task->repo_id);
transition_to_error (task, CLONE_ERROR_INTERNAL);
transition_to_error (task, SYNC_ERROR_ID_LOCAL_DATA_CORRUPT);
return;
}
@ -1578,7 +1550,7 @@ check_folder_perms_done (HttpFolderPerms *result, void *user_data)
if (repo == NULL) {
seaf_warning ("[Clone mgr] cannot find repo %s after fetched.\n",
task->repo_id);
transition_to_error (task, CLONE_ERROR_INTERNAL);
transition_to_error (task, SYNC_ERROR_ID_LOCAL_DATA_CORRUPT);
return;
}
@ -1615,7 +1587,7 @@ check_folder_permissions (CloneTask *task)
if (repo == NULL) {
seaf_warning ("[Clone mgr] cannot find repo %s after fetched.\n",
task->repo_id);
transition_to_error (task, CLONE_ERROR_INTERNAL);
transition_to_error (task, SYNC_ERROR_ID_LOCAL_DATA_CORRUPT);
return;
}
@ -1638,5 +1610,5 @@ check_folder_permissions (CloneTask *task)
requests,
check_folder_perms_done,
task) < 0)
transition_to_error (task, CLONE_ERROR_INTERNAL);
transition_to_error (task, SYNC_ERROR_ID_NOT_ENOUGH_MEMORY);
}

View File

@ -28,23 +28,10 @@ enum {
N_CLONE_STATES,
};
enum {
CLONE_OK,
CLONE_ERROR_CHECK_SERVER,
CLONE_ERROR_INDEX,
CLONE_ERROR_FETCH,
CLONE_ERROR_PASSWD,
CLONE_ERROR_CHECKOUT,
CLONE_ERROR_MERGE,
CLONE_ERROR_INTERNAL,
N_CLONE_ERRORS,
};
struct _CloneTask {
SeafCloneManager *manager;
int state;
int error;
char *err_detail;
char repo_id[37];
int repo_version;
char peer_id[41];
@ -77,9 +64,6 @@ struct _CloneTask {
const char *
clone_task_state_to_str (int state);
const char *
clone_task_error_to_str (int error);
struct _SeafCloneManager {
struct _SeafileSession *seaf;
sqlite3 *db;

View File

@ -27,7 +27,7 @@
#include "seafile-session.h"
#include "http-tx-mgr.h"
#include "seafile-error.h"
#include "seafile-error-impl.h"
#include "utils.h"
#include "diff-simple.h"
@ -130,6 +130,8 @@ http_tx_task_new (HttpTxManager *mgr,
if (worktree)
task->worktree = g_strdup(worktree);
task->error = SYNC_ERROR_ID_NO_ERROR;
return task;
}
@ -141,10 +143,9 @@ http_tx_task_free (HttpTxTask *task)
g_free (task->passwd);
g_free (task->worktree);
g_free (task->email);
g_free (task->repo_name);
if (task->type == HTTP_TASK_TYPE_DOWNLOAD) {
g_hash_table_destroy (task->blk_ref_cnts);
cevent_manager_unregister (seaf->ev_mgr, task->cevent_id);
g_free (task->repo_name);
}
g_free (task);
}
@ -166,32 +167,6 @@ static const char *http_task_rt_state_str[] = {
"finished",
};
static const char *http_task_error_strs[] = {
"Successful",
"Permission denied on server",
"Do not have write permission to the library",
"Do not have permission to sync the library",
"Network error",
"Cannot resolve proxy address",
"Cannot resolve server address",
"Cannot connect to server",
"Failed to establish secure connection",
"Data transfer was interrupted",
"Data transfer timed out",
"Unhandled http redirect from server",
"Server error",
"Bad request",
"Internal data corrupt on the client",
"Not enough memory",
"Failed to write data on the client",
"Storage quota full",
"Files are locked by other application",
"Library deleted on server",
"Library damaged on server",
"File is locked by another user on server",
"Unknown error",
};
/* Http connection and connection pool. */
static Connection *
@ -1100,21 +1075,22 @@ static int
http_error_to_http_task_error (int status)
{
if (status == HTTP_BAD_REQUEST)
return HTTP_TASK_ERR_BAD_REQUEST;
/* This is usually a bug in the client. Set to general error. */
return SYNC_ERROR_ID_GENERAL_ERROR;
else if (status == HTTP_FORBIDDEN)
return HTTP_TASK_ERR_FORBIDDEN;
return SYNC_ERROR_ID_ACCESS_DENIED;
else if (status >= HTTP_INTERNAL_SERVER_ERROR)
return HTTP_TASK_ERR_SERVER;
return SYNC_ERROR_ID_SERVER;
else if (status == HTTP_NOT_FOUND)
return HTTP_TASK_ERR_SERVER;
return SYNC_ERROR_ID_SERVER;
else if (status == HTTP_NO_QUOTA)
return HTTP_TASK_ERR_NO_QUOTA;
return SYNC_ERROR_ID_QUOTA_FULL;
else if (status == HTTP_REPO_DELETED)
return HTTP_TASK_ERR_REPO_DELETED;
return SYNC_ERROR_ID_SERVER_REPO_DELETED;
else if (status == HTTP_REPO_CORRUPTED)
return HTTP_TASK_ERR_REPO_CORRUPTED;
return SYNC_ERROR_ID_SERVER_REPO_CORRUPT;
else
return HTTP_TASK_ERR_UNKNOWN;
return SYNC_ERROR_ID_GENERAL_ERROR;
}
static void
@ -1128,30 +1104,30 @@ curl_error_to_http_task_error (int curl_error)
{
if (curl_error == CURLE_SSL_CACERT ||
curl_error == CURLE_PEER_FAILED_VERIFICATION)
return HTTP_TASK_ERR_SSL;
return SYNC_ERROR_ID_SSL;
switch (curl_error) {
case CURLE_COULDNT_RESOLVE_PROXY:
return HTTP_TASK_ERR_RESOLVE_PROXY;
return SYNC_ERROR_ID_RESOLVE_PROXY;
case CURLE_COULDNT_RESOLVE_HOST:
return HTTP_TASK_ERR_RESOLVE_HOST;
return SYNC_ERROR_ID_RESOLVE_HOST;
case CURLE_COULDNT_CONNECT:
return HTTP_TASK_ERR_CONNECT;
return SYNC_ERROR_ID_CONNECT;
case CURLE_OPERATION_TIMEDOUT:
return HTTP_TASK_ERR_TX_TIMEOUT;
return SYNC_ERROR_ID_TX_TIMEOUT;
case CURLE_SSL_CONNECT_ERROR:
case CURLE_SSL_CERTPROBLEM:
case CURLE_SSL_CACERT_BADFILE:
case CURLE_SSL_ISSUER_ERROR:
return HTTP_TASK_ERR_SSL;
return SYNC_ERROR_ID_SSL;
case CURLE_GOT_NOTHING:
case CURLE_SEND_ERROR:
case CURLE_RECV_ERROR:
return HTTP_TASK_ERR_TX;
return SYNC_ERROR_ID_TX;
case CURLE_SEND_FAIL_REWIND:
return HTTP_TASK_ERR_UNHANDLED_REDIRECT;
return SYNC_ERROR_ID_UNHANDLED_REDIRECT;
default:
return HTTP_TASK_ERR_NET;
return SYNC_ERROR_ID_NETWORK;
}
}
@ -2387,15 +2363,6 @@ clean_tasks_for_repo (HttpTxManager *manager, const char *repo_id)
remove_task_help, (gpointer)repo_id);
}
static void
notify_sync_perm_error (HttpTxTask *task, const char *unsyncable_path)
{
send_file_sync_error_notification (task->repo_id, task->repo_name,
unsyncable_path, SYNC_ERROR_ID_PERM_NOT_SYNCABLE);
}
static int
check_permission (HttpTxTask *task, Connection *conn)
{
@ -2462,9 +2429,9 @@ check_permission (HttpTxTask *task, Connection *conn)
reason_str = json_string_value (reason);
if (g_strcmp0 (reason_str, "no write permission") == 0) {
task->error = HTTP_TASK_ERR_NO_WRITE_PERMISSION;
task->error = SYNC_ERROR_ID_NO_WRITE_PERMISSION;
} else if (g_strcmp0 (reason_str, "unsyncable share permission") == 0) {
task->error = HTTP_TASK_ERR_NO_PERMISSION_TO_SYNC;
task->error = SYNC_ERROR_ID_PERM_NOT_SYNCABLE;
unsyncable_path = json_object_get (rsp_obj, "unsyncable_path");
if (!unsyncable_path) {
@ -2475,9 +2442,11 @@ check_permission (HttpTxTask *task, Connection *conn)
unsyncable_path_str = json_string_value (unsyncable_path);
if (unsyncable_path_str)
notify_sync_perm_error (task, unsyncable_path_str);
seaf_repo_manager_record_sync_error (task->repo_id, task->repo_name,
unsyncable_path_str,
SYNC_ERROR_ID_PERM_NOT_SYNCABLE);
} else {
task->error = HTTP_TASK_ERR_FORBIDDEN;
task->error = SYNC_ERROR_ID_ACCESS_DENIED;
}
ret = -1;
@ -2532,6 +2501,8 @@ http_tx_manager_add_upload (HttpTxManager *manager,
task->use_fileserver_port = use_fileserver_port;
task->repo_name = g_strdup(repo->name);
g_hash_table_insert (manager->priv->upload_tasks,
g_strdup(repo_id),
task);
@ -2739,7 +2710,7 @@ send_commit_object (HttpTxTask *task, Connection *conn)
task->repo_id, task->repo_version,
task->head, (void**)&data, &len) < 0) {
seaf_warning ("Failed to read commit %s.\n", task->head);
task->error = HTTP_TASK_ERR_BAD_LOCAL_DATA;
task->error = SYNC_ERROR_ID_LOCAL_DATA_CORRUPT;
return -1;
}
@ -2970,7 +2941,7 @@ upload_check_id_list_segment (HttpTxTask *task, Connection *conn, const char *ur
array = json_loadb (rsp_content, rsp_size, 0, &jerror);
if (!array) {
seaf_warning ("Invalid JSON response from the server: %s.\n", jerror.text);
task->error = HTTP_TASK_ERR_SERVER;
task->error = SYNC_ERROR_ID_SERVER;
ret = -1;
goto out;
}
@ -3039,7 +3010,7 @@ send_fs_objects (HttpTxTask *task, Connection *conn, GList **send_fs_list)
obj_id, (void **)&data, &len) < 0) {
seaf_warning ("Failed to read fs object %s in repo %s.\n",
obj_id, task->repo_id);
task->error = HTTP_TASK_ERR_BAD_LOCAL_DATA;
task->error = SYNC_ERROR_ID_LOCAL_DATA_CORRUPT;
ret = -1;
goto out;
}
@ -3287,7 +3258,7 @@ send_block_callback (void *ptr, size_t size, size_t nmemb, void *userp)
if (n < 0) {
seaf_warning ("Failed to read block %s in repo %.8s.\n",
data->block_id, task->repo_id);
task->error = HTTP_TASK_ERR_BAD_LOCAL_DATA;
task->error = SYNC_ERROR_ID_LOCAL_DATA_CORRUPT;
return CURL_READFUNC_ABORT;
}
@ -3331,7 +3302,7 @@ send_block (HttpTxTask *task, Connection *conn, const char *block_id, guint32 *p
if (!bmd) {
seaf_warning ("Failed to stat block %s in repo %s.\n",
block_id, task->repo_id);
task->error = HTTP_TASK_ERR_BAD_LOCAL_DATA;
task->error = SYNC_ERROR_ID_LOCAL_DATA_CORRUPT;
return -1;
}
@ -3341,7 +3312,7 @@ send_block (HttpTxTask *task, Connection *conn, const char *block_id, guint32 *p
if (!block) {
seaf_warning ("Failed to open block %s in repo %s.\n",
block_id, task->repo_id);
task->error = HTTP_TASK_ERR_BAD_LOCAL_DATA;
task->error = SYNC_ERROR_ID_LOCAL_DATA_CORRUPT;
g_free (bmd);
return -1;
}
@ -3369,7 +3340,7 @@ send_block (HttpTxTask *task, Connection *conn, const char *block_id, guint32 *p
if (task->state == HTTP_TASK_STATE_CANCELED)
goto out;
if (task->error == HTTP_TASK_OK) {
if (task->error == SYNC_ERROR_ID_NO_ERROR) {
/* Only release connection when it's a network error */
conn->release = TRUE;
handle_curl_errors (task, curl_error);
@ -3428,7 +3399,7 @@ upload_block_thread_func (gpointer data, gpointer user_data)
conn = connection_pool_get_connection (tx_data->cpool);
if (!conn) {
seaf_warning ("Failed to get connection to host %s.\n", http_task->host);
http_task->error = HTTP_TASK_ERR_NOT_ENOUGH_MEMORY;
http_task->error = SYNC_ERROR_ID_NOT_ENOUGH_MEMORY;
ret = -1;
goto out;
}
@ -3464,7 +3435,7 @@ multi_threaded_send_blocks (HttpTxTask *http_task, GList *block_list)
cpool = find_connection_pool (priv, http_task->host);
if (!cpool) {
seaf_warning ("Failed to create connection pool for host %s.\n", http_task->host);
http_task->error = HTTP_TASK_ERR_NOT_ENOUGH_MEMORY;
http_task->error = SYNC_ERROR_ID_NOT_ENOUGH_MEMORY;
return -1;
}
@ -3534,19 +3505,21 @@ notify_permission_error (HttpTxTask *task, const char *error_str)
if (g_regex_match (priv->locked_error_regex, error_str, 0, &match_info)) {
path = g_match_info_fetch (match_info, 1);
send_file_sync_error_notification (task->repo_id, task->repo_name, path,
seaf_repo_manager_record_sync_error (task->repo_id, task->repo_name, path,
SYNC_ERROR_ID_FILE_LOCKED);
g_free (path);
/* Set more accurate error. */
task->error = HTTP_TASK_ERR_FILE_LOCKED_ON_SERVER;
task->error = SYNC_ERROR_ID_FILE_LOCKED;
} else if (g_regex_match (priv->folder_perm_error_regex, error_str, 0, &match_info)) {
path = g_match_info_fetch (match_info, 1);
/* The path returned by server begins with '/'. */
send_file_sync_error_notification (task->repo_id, task->repo_name,
seaf_repo_manager_record_sync_error (task->repo_id, task->repo_name,
(path[0] == '/') ? (path + 1) : path,
SYNC_ERROR_ID_FOLDER_PERM_DENIED);
g_free (path);
task->error = SYNC_ERROR_ID_FOLDER_PERM_DENIED;
}
g_match_info_free (match_info);
@ -3666,7 +3639,7 @@ http_upload_thread (void *vdata)
task->repo_id, "local");
if (!local) {
seaf_warning ("Failed to get branch local of repo %.8s.\n", task->repo_id);
task->error = HTTP_TASK_ERR_BAD_LOCAL_DATA;
task->error = SYNC_ERROR_ID_LOCAL_DATA_CORRUPT;
return NULL;
}
memcpy (task->head, local->commit_id, 40);
@ -3675,14 +3648,14 @@ http_upload_thread (void *vdata)
pool = find_connection_pool (priv, task->host);
if (!pool) {
seaf_warning ("Failed to create connection pool for host %s.\n", task->host);
task->error = HTTP_TASK_ERR_NOT_ENOUGH_MEMORY;
task->error = SYNC_ERROR_ID_NOT_ENOUGH_MEMORY;
goto out;
}
conn = connection_pool_get_connection (pool);
if (!conn) {
seaf_warning ("Failed to get connection to host %s.\n", task->host);
task->error = HTTP_TASK_ERR_NOT_ENOUGH_MEMORY;
task->error = SYNC_ERROR_ID_NOT_ENOUGH_MEMORY;
goto out;
}
@ -3697,7 +3670,7 @@ http_upload_thread (void *vdata)
if (calculate_upload_size_delta_and_active_paths (task, &delta, active_paths) < 0) {
seaf_warning ("Failed to calculate upload size delta for repo %s.\n",
task->repo_id);
task->error = HTTP_TASK_ERR_BAD_LOCAL_DATA;
task->error = SYNC_ERROR_ID_LOCAL_DATA_CORRUPT;
goto out;
}
@ -3734,7 +3707,7 @@ http_upload_thread (void *vdata)
if (!send_fs_list) {
seaf_warning ("Failed to calculate fs object list for repo %.8s.\n",
task->repo_id);
task->error = HTTP_TASK_ERR_BAD_LOCAL_DATA;
task->error = SYNC_ERROR_ID_LOCAL_DATA_CORRUPT;
goto out;
}
@ -3773,7 +3746,7 @@ http_upload_thread (void *vdata)
if (calculate_block_list (task, &block_list) < 0) {
seaf_warning ("Failed to calculate block list for repo %.8s.\n",
task->repo_id);
task->error = HTTP_TASK_ERR_BAD_LOCAL_DATA;
task->error = SYNC_ERROR_ID_LOCAL_DATA_CORRUPT;
goto out;
}
@ -3843,7 +3816,7 @@ http_upload_done (void *vdata)
{
HttpTxTask *task = vdata;
if (task->error != HTTP_TASK_OK)
if (task->error != SYNC_ERROR_ID_NO_ERROR)
transition_state (task, HTTP_TASK_STATE_ERROR, HTTP_TASK_RT_STATE_FINISHED);
else if (task->state == HTTP_TASK_STATE_CANCELED)
transition_state (task, task->state, HTTP_TASK_RT_STATE_FINISHED);
@ -3855,7 +3828,6 @@ http_upload_done (void *vdata)
static void *http_download_thread (void *vdata);
static void http_download_done (void *vdata);
static void notify_conflict (CEvent *event, void *data);
int
http_tx_manager_add_download (HttpTxManager *manager,
@ -3911,9 +3883,6 @@ http_tx_manager_add_download (HttpTxManager *manager,
g_strdup(repo_id),
task);
task->cevent_id = cevent_manager_register (seaf->ev_mgr,
(cevent_handler)notify_conflict,
NULL);
task->repo_name = g_strdup(repo_name);
if (seaf_job_manager_schedule_job (seaf->job_mgr,
@ -3972,7 +3941,7 @@ get_commit_object (HttpTxTask *task, Connection *conn)
if (rc < 0) {
seaf_warning ("Failed to save commit %s in repo %.8s.\n",
task->head, task->repo_id);
task->error = HTTP_TASK_ERR_WRITE_LOCAL_DATA;
task->error = SYNC_ERROR_ID_WRITE_LOCAL_DATA;
ret = -1;
}
@ -4043,7 +4012,7 @@ get_needed_fs_id_list (HttpTxTask *task, Connection *conn, GList **fs_id_list)
array = json_loadb (rsp_content, rsp_size, 0, &jerror);
if (!array) {
seaf_warning ("Invalid JSON response from the server: %s.\n", jerror.text);
task->error = HTTP_TASK_ERR_SERVER;
task->error = SYNC_ERROR_ID_SERVER;
ret = -1;
goto out;
}
@ -4195,7 +4164,7 @@ get_fs_objects (HttpTxTask *task, Connection *conn, GList **fs_list)
if (n + sizeof(ObjectHeader) + size > rsp_size) {
seaf_warning ("Incomplete object package received for repo %.8s.\n",
task->repo_id);
task->error = HTTP_TASK_ERR_SERVER;
task->error = SYNC_ERROR_ID_SERVER;
ret = -1;
goto out;
}
@ -4210,7 +4179,7 @@ get_fs_objects (HttpTxTask *task, Connection *conn, GList **fs_list)
if (rc < 0) {
seaf_warning ("Failed to write fs object %s in repo %.8s.\n",
recv_obj_id, task->repo_id);
task->error = HTTP_TASK_ERR_WRITE_LOCAL_DATA;
task->error = SYNC_ERROR_ID_WRITE_LOCAL_DATA;
ret = -1;
goto out;
}
@ -4271,7 +4240,7 @@ get_block_callback (void *ptr, size_t size, size_t nmemb, void *userp)
if (n < realsize) {
seaf_warning ("Failed to write block %s in repo %.8s.\n",
data->block_id, task->repo_id);
task->error = HTTP_TASK_ERR_WRITE_LOCAL_DATA;
task->error = SYNC_ERROR_ID_WRITE_LOCAL_DATA;
return n;
}
@ -4338,7 +4307,7 @@ get_block (HttpTxTask *task, Connection *conn, const char *block_id)
if (task->state == HTTP_TASK_STATE_CANCELED)
goto error;
if (task->error == HTTP_TASK_OK) {
if (task->error == SYNC_ERROR_ID_NO_ERROR) {
/* Only release the connection when it's a network error. */
conn->release = TRUE;
handle_curl_errors (task, curl_error);
@ -4378,7 +4347,7 @@ get_block (HttpTxTask *task, Connection *conn, const char *block_id)
{
seaf_warning ("Failed to commit block %s in repo %.8s.\n",
block_id, task->repo_id);
task->error = HTTP_TASK_ERR_WRITE_LOCAL_DATA;
task->error = SYNC_ERROR_ID_WRITE_LOCAL_DATA;
ret = -1;
}
@ -4430,7 +4399,7 @@ http_tx_task_download_file_blocks (HttpTxTask *task, const char *file_id)
pool = find_connection_pool (priv, task->host);
if (!pool) {
seaf_warning ("Failed to create connection pool for host %s.\n", task->host);
task->error = HTTP_TASK_ERR_NOT_ENOUGH_MEMORY;
task->error = SYNC_ERROR_ID_NOT_ENOUGH_MEMORY;
seafile_unref (file);
return -1;
}
@ -4438,7 +4407,7 @@ http_tx_task_download_file_blocks (HttpTxTask *task, const char *file_id)
conn = connection_pool_get_connection (pool);
if (!conn) {
seaf_warning ("Failed to get connection to host %s.\n", task->host);
task->error = HTTP_TASK_ERR_NOT_ENOUGH_MEMORY;
task->error = SYNC_ERROR_ID_NOT_ENOUGH_MEMORY;
seafile_unref (file);
return -1;
}
@ -4473,7 +4442,7 @@ update_local_repo (HttpTxTask *task)
task->head);
if (!new_head) {
seaf_warning ("Failed to get commit %s:%s.\n", task->repo_id, task->head);
task->error = HTTP_TASK_ERR_BAD_LOCAL_DATA;
task->error = SYNC_ERROR_ID_LOCAL_DATA_CORRUPT;
return -1;
}
@ -4488,7 +4457,7 @@ update_local_repo (HttpTxTask *task)
repo = seaf_repo_new (new_head->repo_id, NULL, NULL);
if (repo == NULL) {
/* create repo failed */
task->error = HTTP_TASK_ERR_NOT_ENOUGH_MEMORY;
task->error = SYNC_ERROR_ID_NOT_ENOUGH_MEMORY;
ret = -1;
goto out;
}
@ -4507,7 +4476,7 @@ update_local_repo (HttpTxTask *task)
seaf_branch_unref (branch);
} else {
if (!repo) {
task->error = HTTP_TASK_ERR_BAD_LOCAL_DATA;
task->error = SYNC_ERROR_ID_LOCAL_DATA_CORRUPT;
ret = -1;
goto out;
}
@ -4517,7 +4486,7 @@ update_local_repo (HttpTxTask *task)
"master");
if (!branch) {
seaf_warning ("Branch master not found for repo %.8s.\n", task->repo_id);
task->error = HTTP_TASK_ERR_BAD_LOCAL_DATA;
task->error = SYNC_ERROR_ID_LOCAL_DATA_CORRUPT;
ret = -1;
goto out;
}
@ -4550,14 +4519,14 @@ http_download_thread (void *vdata)
pool = find_connection_pool (priv, task->host);
if (!pool) {
seaf_warning ("Failed to create connection pool for host %s.\n", task->host);
task->error = HTTP_TASK_ERR_NOT_ENOUGH_MEMORY;
task->error = SYNC_ERROR_ID_NOT_ENOUGH_MEMORY;
goto out;
}
conn = connection_pool_get_connection (pool);
if (!conn) {
seaf_warning ("Failed to get connection to host %s.\n", task->host);
task->error = HTTP_TASK_ERR_NOT_ENOUGH_MEMORY;
task->error = SYNC_ERROR_ID_NOT_ENOUGH_MEMORY;
goto out;
}
@ -4625,12 +4594,12 @@ http_download_thread (void *vdata)
case FETCH_CHECKOUT_CANCELED:
goto out;
case FETCH_CHECKOUT_FAILED:
task->error = HTTP_TASK_ERR_WRITE_LOCAL_DATA;
task->error = SYNC_ERROR_ID_WRITE_LOCAL_DATA;
goto out;
case FETCH_CHECKOUT_TRANSFER_ERROR:
goto out;
case FETCH_CHECKOUT_LOCKED:
task->error = HTTP_TASK_ERR_FILES_LOCKED;
task->error = SYNC_ERROR_ID_FILE_LOCKED_BY_APP;
goto out;
}
@ -4647,7 +4616,7 @@ http_download_done (void *vdata)
{
HttpTxTask *task = vdata;
if (task->error != HTTP_TASK_OK)
if (task->error != SYNC_ERROR_ID_NO_ERROR)
transition_state (task, HTTP_TASK_STATE_ERROR, HTTP_TASK_RT_STATE_FINISHED);
else if (task->state == HTTP_TASK_STATE_CANCELED)
transition_state (task, task->state, HTTP_TASK_RT_STATE_FINISHED);
@ -4655,49 +4624,6 @@ http_download_done (void *vdata)
transition_state (task, HTTP_TASK_STATE_FINISHED, HTTP_TASK_RT_STATE_FINISHED);
}
typedef struct FileConflictData {
char *repo_id;
char *repo_name;
char *path;
} FileConflictData;
static void
notify_conflict (CEvent *event, void *handler_data)
{
FileConflictData *data = event->data;
json_t *object;
char *str;
object = json_object ();
json_object_set_new (object, "repo_id", json_string(data->repo_id));
json_object_set_new (object, "repo_name", json_string(data->repo_name));
json_object_set_new (object, "path", json_string(data->path));
str = json_dumps (object, 0);
seaf_mq_manager_publish_notification (seaf->mq_mgr,
"sync.conflict",
str);
free (str);
json_decref (object);
g_free (data->repo_id);
g_free (data->repo_name);
g_free (data->path);
g_free (data);
}
void
http_tx_manager_notify_conflict (HttpTxTask *task, const char *path)
{
FileConflictData *data = g_new0 (FileConflictData, 1);
data->repo_id = g_strdup(task->repo_id);
data->repo_name = g_strdup(task->repo_name);
data->path = g_strdup(path);
cevent_manager_add_event (seaf->ev_mgr, task->cevent_id, data);
}
GList*
http_tx_manager_get_upload_tasks (HttpTxManager *manager)
{
@ -4775,28 +4701,3 @@ http_task_rt_state_to_str (int rt_state)
return http_task_rt_state_str[rt_state];
}
const char *
http_task_error_str (int task_errno)
{
if (task_errno < 0 || task_errno >= N_HTTP_TASK_ERROR)
return "unknown error";
return http_task_error_strs[task_errno];
}
gboolean
is_http_task_net_error (char *err_detail)
{
if (err_detail &&
(strcmp (err_detail, http_task_error_strs[HTTP_TASK_ERR_NET]) == 0 ||
strcmp (err_detail, http_task_error_strs[HTTP_TASK_ERR_RESOLVE_PROXY]) == 0 ||
strcmp (err_detail, http_task_error_strs[HTTP_TASK_ERR_RESOLVE_HOST]) == 0 ||
strcmp (err_detail, http_task_error_strs[HTTP_TASK_ERR_CONNECT]) == 0 ||
strcmp (err_detail, http_task_error_strs[HTTP_TASK_ERR_SSL]) == 0 ||
strcmp (err_detail, http_task_error_strs[HTTP_TASK_ERR_TX]) == 0 ||
strcmp (err_detail, http_task_error_strs[HTTP_TASK_ERR_TX_TIMEOUT]) == 0))
return TRUE;
else
return FALSE;
}

View File

@ -34,33 +34,6 @@ enum HttpTaskRuntimeState {
N_HTTP_TASK_RT_STATE,
};
enum HttpTaskError {
HTTP_TASK_OK = 0,
HTTP_TASK_ERR_FORBIDDEN,
HTTP_TASK_ERR_NO_WRITE_PERMISSION,
HTTP_TASK_ERR_NO_PERMISSION_TO_SYNC,
HTTP_TASK_ERR_NET,
HTTP_TASK_ERR_RESOLVE_PROXY,
HTTP_TASK_ERR_RESOLVE_HOST,
HTTP_TASK_ERR_CONNECT,
HTTP_TASK_ERR_SSL,
HTTP_TASK_ERR_TX,
HTTP_TASK_ERR_TX_TIMEOUT,
HTTP_TASK_ERR_UNHANDLED_REDIRECT,
HTTP_TASK_ERR_SERVER,
HTTP_TASK_ERR_BAD_REQUEST,
HTTP_TASK_ERR_BAD_LOCAL_DATA,
HTTP_TASK_ERR_NOT_ENOUGH_MEMORY,
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_FILE_LOCKED_ON_SERVER,
HTTP_TASK_ERR_UNKNOWN,
N_HTTP_TASK_ERROR,
};
struct _SeafileSession;
struct _HttpTxPriv;
@ -77,6 +50,7 @@ struct _HttpTxTask {
char repo_id[37];
int repo_version;
char *repo_name;
char *token;
int protocol_version;
int type;
@ -117,9 +91,6 @@ struct _HttpTxTask {
gint tx_bytes; /* bytes transferred in this second. */
gint last_tx_bytes; /* bytes transferred in the last second. */
uint32_t cevent_id; /* Used by download task to send notification. */
char *repo_name; /* Used by download task in conflict notification. */
};
typedef struct _HttpTxTask HttpTxTask;
@ -312,10 +283,6 @@ http_tx_manager_cancel_task (HttpTxManager *manager,
const char *repo_id,
int task_type);
/* Only useful for download task. */
void
http_tx_manager_notify_conflict (HttpTxTask *task, const char *path);
int
http_tx_task_get_rate (HttpTxTask *task);
@ -325,9 +292,4 @@ http_task_state_to_str (int state);
const char *
http_task_rt_state_to_str (int rt_state);
const char *
http_task_error_str (int task_errno);
#endif
gboolean
is_http_task_net_error (char *err_detail);

View File

@ -55,8 +55,6 @@ struct _SeafRepoManagerPriv {
GHashTable *group_perms; /* repo_id -> folder group perms */
pthread_mutex_t perm_lock;
uint32_t cevent_id; /* Used to notify sync error */
GAsyncQueue *lock_office_job_queue;
};
@ -276,6 +274,7 @@ locked_file_set_remove (LockedFileSet *fset, const char *path, gboolean db_only)
sqlite3_finalize (stmt);
pthread_mutex_unlock (&mgr->priv->db_lock);
if (!db_only)
g_hash_table_remove (fset->locked_files, path);
return 0;
@ -665,61 +664,49 @@ is_repo_id_valid (const char *id)
return is_uuid_valid (id);
}
typedef struct FileErrorAux {
char *repo_id;
char *path;
int err_id;
} FileErrorAux;
/*
* Sync error related. These functions should belong to the sync-mgr module.
* But since we have to store the errors in repo database, we have to put the code here.
*/
static gboolean
get_last_file_sync_error (sqlite3_stmt *stmt, void *data)
{
FileErrorAux *aux = data;
aux->repo_id = g_strdup((const char *)sqlite3_column_text (stmt, 0));
aux->path = g_strdup((const char *)sqlite3_column_text (stmt, 1));
aux->err_id = sqlite3_column_int (stmt, 2);
return FALSE;
}
static void
save_file_sync_error (const char *repo_id, const char *repo_name, const char *path,
int err_id, gboolean *duplicated)
int
seaf_repo_manager_record_sync_error (const char *repo_id,
const char *repo_name,
const char *path,
int error_id)
{
char *sql;
FileErrorAux aux;
int n;
memset (&aux, 0, sizeof(aux));
int ret;
pthread_mutex_lock (&seaf->repo_mgr->priv->db_lock);
sql = "SELECT repo_id, path, err_id FROM FileSyncError "
"ORDER BY id DESC LIMIT 1 OFFSET 0";
n = sqlite_foreach_selected_row (seaf->repo_mgr->priv->db,
sql, get_last_file_sync_error, &aux);
if (n > 0 &&
g_strcmp0(repo_id, aux.repo_id) == 0 &&
g_strcmp0(path, aux.path) == 0 &&
err_id == aux.err_id) {
*duplicated = TRUE;
sql = sqlite3_mprintf ("DELETE FROM FileSyncError WHERE repo_id='%q' AND path='%q'",
repo_id, path);
ret = sqlite_query_exec (seaf->repo_mgr->priv->db, sql);
sqlite3_free (sql);
if (ret < 0)
goto out;
}
/* REPLACE INTO will update the primary key id automatically.
* So new errors are always on top.
*/
if (path != NULL)
sql = sqlite3_mprintf ("INSERT INTO FileSyncError "
"(repo_id, repo_name, path, err_id, timestamp) "
"VALUES ('%q', '%q', '%q', %d, %"G_GINT64_FORMAT")",
repo_id, repo_name, path, err_id, (gint64)time(NULL));
sqlite_query_exec (seaf->repo_mgr->priv->db, sql);
repo_id, repo_name, path, error_id, (gint64)time(NULL));
else
sql = sqlite3_mprintf ("INSERT INTO FileSyncError "
"(repo_id, repo_name, err_id, timestamp) "
"VALUES ('%q', '%q', %d, %"G_GINT64_FORMAT")",
repo_id, repo_name, error_id, (gint64)time(NULL));
ret = sqlite_query_exec (seaf->repo_mgr->priv->db, sql);
sqlite3_free (sql);
out:
pthread_mutex_unlock (&seaf->repo_mgr->priv->db_lock);
g_free (aux.repo_id);
g_free (aux.path);
return;
return ret;
}
static gboolean
@ -771,42 +758,8 @@ seaf_repo_manager_get_file_sync_errors (SeafRepoManager *mgr, int offset, int li
return ret;
}
typedef struct SyncErrorData {
char *repo_id;
char *repo_name;
char *path;
int err_id;
} SyncErrorData;
static void
notify_sync_error (CEvent *event, void *handler_data)
{
SyncErrorData *data = event->data;
json_t *object;
char *str;
object = json_object ();
json_object_set_new (object, "repo_id", json_string(data->repo_id));
json_object_set_new (object, "repo_name", json_string(data->repo_name));
json_object_set_new (object, "path", json_string(data->path));
json_object_set_new (object, "err_id", json_integer(data->err_id));
str = json_dumps (object, 0);
seaf_mq_manager_publish_notification (seaf->mq_mgr,
"sync.error",
str);
free (str);
json_decref (object);
g_free (data->repo_id);
g_free (data->repo_name);
g_free (data->path);
g_free (data);
}
/*
* FIXME: This function should be placed in sync manager.
* Record file-level sync errors and send system notification.
*/
void
send_file_sync_error_notification (const char *repo_id,
@ -821,23 +774,27 @@ send_file_sync_error_notification (const char *repo_id,
repo_name = repo->name;
}
SyncErrorData *data = g_new0 (SyncErrorData, 1);
data->repo_id = g_strdup(repo_id);
data->repo_name = g_strdup(repo_name);
data->path = g_strdup(path);
data->err_id = err_id;
seaf_repo_manager_record_sync_error (repo_id, repo_name, path, err_id);
gboolean duplicated = FALSE;
save_file_sync_error (repo_id, repo_name, path, err_id, &duplicated);
seaf_sync_manager_set_task_error_code (seaf->sync_mgr, repo_id, err_id);
if (!duplicated)
cevent_manager_add_event (seaf->ev_mgr, seaf->repo_mgr->priv->cevent_id, data);
else {
g_free (data->repo_id);
g_free (data->repo_name);
g_free (data->path);
g_free (data);
}
json_t *object;
char *str;
object = json_object ();
json_object_set_new (object, "repo_id", json_string(repo_id));
json_object_set_new (object, "repo_name", json_string(repo_name));
json_object_set_new (object, "path", json_string(path));
json_object_set_new (object, "err_id", json_integer(err_id));
str = json_dumps (object, 0);
seaf_mq_manager_publish_notification (seaf->mq_mgr,
"sync.error",
str);
free (str);
json_decref (object);
}
SeafRepo*
@ -4601,11 +4558,11 @@ checkout_file_http (FileTxData *data,
cleanup_file_blocks_http (http_task, file_id);
if (conflicted) {
http_tx_manager_notify_conflict (http_task, de->name);
send_file_sync_error_notification (repo_id, NULL, de->name, SYNC_ERROR_ID_CONFLICT);
} else if (!http_task->is_clone) {
char *orig_path = NULL;
if (check_path_conflict (de->name, &orig_path))
http_tx_manager_notify_conflict (http_task, orig_path);
send_file_sync_error_notification (repo_id, NULL, orig_path, SYNC_ERROR_ID_CONFLICT);
g_free (orig_path);
}
@ -5687,10 +5644,6 @@ seaf_repo_manager_init (SeafRepoManager *mgr)
return -1;
}
mgr->priv->cevent_id = cevent_manager_register (seaf->ev_mgr,
(cevent_handler)notify_sync_error,
NULL);
/* Load all the repos into memory on the client side. */
load_repos (mgr, mgr->seaf->seaf_dir);
@ -6577,6 +6530,9 @@ open_db (SeafRepoManager *manager, const char *seaf_dir)
"path TEXT, err_id INTEGER, timestamp INTEGER);";
sqlite_query_exec (db, sql);
sql = "CREATE INDEX IF NOT EXISTS FileSyncErrorIndex ON FileSyncError (repo_id, path)";
sqlite_query_exec (db, sql);
return db;
}

View File

@ -400,25 +400,18 @@ seaf_repo_manager_is_path_writable (SeafRepoManager *mgr,
const char *repo_id,
const char *path);
/*
* File Sync Errors.
* FIXME: better to be placed in sync manager.
*/
/* Sync error related. */
#define SYNC_ERROR_ID_FILE_LOCKED_BY_APP 0
#define SYNC_ERROR_ID_FOLDER_LOCKED_BY_APP 1
#define SYNC_ERROR_ID_FILE_LOCKED 2
#define SYNC_ERROR_ID_INVALID_PATH 3
#define SYNC_ERROR_ID_INDEX_ERROR 4
#define SYNC_ERROR_ID_PATH_END_SPACE_PERIOD 5
#define SYNC_ERROR_ID_PATH_INVALID_CHARACTER 6
#define SYNC_ERROR_ID_FOLDER_PERM_DENIED 7
#define SYNC_ERROR_ID_PERM_NOT_SYNCABLE 8
#define SYNC_ERROR_ID_UPDATE_TO_READ_ONLY_REPO 9
int
seaf_repo_manager_record_sync_error (const char *repo_id,
const char *repo_name,
const char *path,
int error_id);
GList *
seaf_repo_manager_get_file_sync_errors (SeafRepoManager *mgr, int offset, int limit);
/* Record sync error and send notification. */
void
send_file_sync_error_notification (const char *repo_id,
const char *repo_name,

View File

@ -222,11 +222,6 @@ register_rpc_service ()
"seafile_get_repo_sync_task",
searpc_signature_object__string());
searpc_server_register_function ("seafile-rpcserver",
seafile_get_repo_sync_info,
"seafile_get_repo_sync_info",
searpc_signature_object__string());
searpc_server_register_function ("seafile-rpcserver",
seafile_find_transfer_task,
"seafile_find_transfer_task",

View File

@ -0,0 +1,18 @@
#ifndef SEAFILE_ERROR_IMPL_H
#define SEAFILE_ERROR_IMPL_H
#include "seafile-error.h"
enum {
SYNC_ERROR_LEVEL_REPO,
SYNC_ERROR_LEVEL_FILE,
SYNC_ERROR_LEVEL_NETWORK,
};
const char *
sync_error_id_to_str (int error);
int
sync_error_level (int error);
#endif

178
daemon/seafile-error.c Normal file
View File

@ -0,0 +1,178 @@
#include "common.h"
#include "seafile-error-impl.h"
typedef struct SyncErrorInfo {
int error_id;
int error_level;
const char *err_str;
} SyncErrorInfo;
static SyncErrorInfo sync_error_info_tbl[] = {
{
SYNC_ERROR_ID_FILE_LOCKED_BY_APP,
SYNC_ERROR_LEVEL_FILE,
"File is locked by another application"
},
{
SYNC_ERROR_ID_FOLDER_LOCKED_BY_APP,
SYNC_ERROR_LEVEL_FILE,
"Folder is locked by another application"
},
{
SYNC_ERROR_ID_FILE_LOCKED,
SYNC_ERROR_LEVEL_FILE,
"File is locked by another user"
},
{
SYNC_ERROR_ID_INVALID_PATH,
SYNC_ERROR_LEVEL_FILE,
"Path is invalid"
},
{
SYNC_ERROR_ID_INDEX_ERROR,
SYNC_ERROR_LEVEL_FILE,
"Error when indexing"
},
{
SYNC_ERROR_ID_PATH_END_SPACE_PERIOD,
SYNC_ERROR_LEVEL_FILE,
"Path ends with space or period character"
},
{
SYNC_ERROR_ID_PATH_INVALID_CHARACTER,
SYNC_ERROR_LEVEL_FILE,
"Path contains invalid characters like '|' or ':'"
},
{
SYNC_ERROR_ID_FOLDER_PERM_DENIED,
SYNC_ERROR_LEVEL_FILE,
"Update to file denied by folder permission setting"
},
{
SYNC_ERROR_ID_PERM_NOT_SYNCABLE,
SYNC_ERROR_LEVEL_FILE,
"No permission to sync this folder"
},
{
SYNC_ERROR_ID_UPDATE_TO_READ_ONLY_REPO,
SYNC_ERROR_LEVEL_FILE,
"Created or updated a file in a non-writable library or folder"
},
{
SYNC_ERROR_ID_ACCESS_DENIED,
SYNC_ERROR_LEVEL_REPO,
"Permission denied on server"
},
{
SYNC_ERROR_ID_NO_WRITE_PERMISSION,
SYNC_ERROR_LEVEL_REPO,
"Do not have write permission to the library"
},
{
SYNC_ERROR_ID_QUOTA_FULL,
SYNC_ERROR_LEVEL_REPO,
"Storage quota full"
},
{
SYNC_ERROR_ID_NETWORK,
SYNC_ERROR_LEVEL_NETWORK,
"Network error",
},
{
SYNC_ERROR_ID_RESOLVE_PROXY,
SYNC_ERROR_LEVEL_NETWORK,
"Cannot resolve proxy address"
},
{
SYNC_ERROR_ID_RESOLVE_HOST,
SYNC_ERROR_LEVEL_NETWORK,
"Cannot resolve server address"
},
{
SYNC_ERROR_ID_CONNECT,
SYNC_ERROR_LEVEL_NETWORK,
"Cannot connect to server"
},
{
SYNC_ERROR_ID_SSL,
SYNC_ERROR_LEVEL_NETWORK,
"Failed to establish secure connection. Please check server SSL certificate"
},
{
SYNC_ERROR_ID_TX,
SYNC_ERROR_LEVEL_NETWORK,
"Data transfer was interrupted. Please check network or firewall"
},
{
SYNC_ERROR_ID_TX_TIMEOUT,
SYNC_ERROR_LEVEL_NETWORK,
"Data transfer timed out. Please check network or firewall"
},
{
SYNC_ERROR_ID_UNHANDLED_REDIRECT,
SYNC_ERROR_LEVEL_NETWORK,
"Unhandled http redirect from server. Please check server cofiguration"
},
{
SYNC_ERROR_ID_SERVER,
SYNC_ERROR_LEVEL_REPO,
"Server error"
},
{
SYNC_ERROR_ID_LOCAL_DATA_CORRUPT,
SYNC_ERROR_LEVEL_REPO,
"Internal data corrupt on the client. Please try to resync the library"
},
{
SYNC_ERROR_ID_WRITE_LOCAL_DATA,
SYNC_ERROR_LEVEL_REPO,
"Failed to write data on the client. Please check disk space or folder permissions"
},
{
SYNC_ERROR_ID_SERVER_REPO_DELETED,
SYNC_ERROR_LEVEL_REPO,
"Library deleted on server"
},
{
SYNC_ERROR_ID_SERVER_REPO_CORRUPT,
SYNC_ERROR_LEVEL_REPO,
"Library damaged on server"
},
{
SYNC_ERROR_ID_NOT_ENOUGH_MEMORY,
SYNC_ERROR_LEVEL_REPO,
"Not enough memory"
},
{
SYNC_ERROR_ID_CONFLICT,
SYNC_ERROR_LEVEL_FILE,
"Concurrent updates to file. File is saved as conflict file"
},
{
SYNC_ERROR_ID_GENERAL_ERROR,
SYNC_ERROR_LEVEL_REPO,
"Unknown error"
},
{
SYNC_ERROR_ID_NO_ERROR,
SYNC_ERROR_LEVEL_REPO,
"No error"
},
};
const char *
sync_error_id_to_str (int error)
{
g_return_val_if_fail ((error >= 0 && error < N_SYNC_ERROR_ID), "Unknown error");
return sync_error_info_tbl[error].err_str;
}
int
sync_error_level (int error)
{
g_return_val_if_fail ((error >= 0 && error < N_SYNC_ERROR_ID), -1);
return sync_error_info_tbl[error].error_level;
}

View File

@ -9,7 +9,7 @@
#include "seafile-session.h"
#include "seafile-config.h"
#include "sync-mgr.h"
#include "seafile-error.h"
#include "seafile-error-impl.h"
#include "mq-mgr.h"
#include "utils.h"
#include "vc-utils.h"
@ -506,6 +506,15 @@ notify_sync (SeafRepo *repo, gboolean is_multipart_upload)
#define IN_ERROR_THRESHOLD 3
static gboolean
is_perm_error (int error)
{
return (error == SYNC_ERROR_ID_ACCESS_DENIED ||
error == SYNC_ERROR_ID_NO_WRITE_PERMISSION ||
error == SYNC_ERROR_ID_PERM_NOT_SYNCABLE ||
error == SYNC_ERROR_ID_FOLDER_PERM_DENIED);
}
static void
update_sync_info_error_state (SyncTask *task, int new_state)
{
@ -515,7 +524,7 @@ update_sync_info_error_state (SyncTask *task, int new_state)
info->err_cnt++;
if (info->err_cnt == IN_ERROR_THRESHOLD)
info->in_error = TRUE;
if (task->error == SYNC_ERROR_ACCESS_DENIED)
if (is_perm_error(task->error))
info->sync_perm_err_cnt++;
} else if (info->err_cnt > 0) {
info->err_cnt = 0;
@ -526,7 +535,7 @@ update_sync_info_error_state (SyncTask *task, int new_state)
static void commit_repo (SyncTask *task);
static inline void
static void
transition_sync_state (SyncTask *task, int new_state)
{
g_return_if_fail (new_state >= 0 && new_state < SYNC_STATE_NUM);
@ -551,6 +560,17 @@ transition_sync_state (SyncTask *task, int new_state)
return;
}
/* If file error levels occured during sync, the whole sync process can still finish
* with DONE state. But we need to notify the user about this error in the interface.
* Such file level errors are set with seaf_sync_manager_set_task_error_code().
*/
if (new_state != SYNC_STATE_ERROR && task->error != SYNC_ERROR_ID_NO_ERROR) {
new_state = SYNC_STATE_ERROR;
seaf_message ("Repo '%s' sync is finished but with error: %s\n",
task->repo->name,
sync_error_id_to_str(task->error));
}
if (!(task->state == SYNC_STATE_DONE && new_state == SYNC_STATE_INIT) &&
!(task->state == SYNC_STATE_INIT && new_state == SYNC_STATE_DONE)) {
seaf_message ("Repo '%s' sync state transition from '%s' to '%s'.\n",
@ -582,49 +602,32 @@ transition_sync_state (SyncTask *task, int new_state)
}
}
static const char *sync_error_str[] = {
"Success",
"relay not connected",
"failed to upgrade old repo",
"Server has been removed",
"You have not login to the server",
"Remote service is not available",
"You do not have permission to access this library",
"The storage space of the repo owner has been used up",
"Access denied to service. Please check your registration on relay.",
"Internal data corrupted.",
"Failed to start upload.",
"Error occurred in upload.",
"Failed to start download.",
"Error occurred in download.",
"No such repo on relay.",
"Repo is damaged on relay.",
"Failed to index files.",
"Conflict in merge.",
"Files changed in local folder, skip merge.",
"Server version is too old.",
"Failed to get sync info from server.",
"Files are locked by other application",
"Unknown error.",
};
void
seaf_sync_manager_set_task_error (SyncTask *task, int error)
static void
set_task_error (SyncTask *task, int error)
{
g_return_if_fail (error >= 0 && error < SYNC_ERROR_NUM);
g_return_if_fail (error >= 0 && error < N_SYNC_ERROR_ID);
const char *err_str = sync_error_id_to_str(error);
int err_level = sync_error_level(error);
if (task->state != SYNC_STATE_ERROR) {
seaf_message ("Repo '%s' sync state transition from %s to '%s': '%s'.\n",
task->repo->name,
sync_state_str[task->state],
sync_state_str[SYNC_STATE_ERROR],
sync_error_str[error]);
err_str);
task->state = SYNC_STATE_ERROR;
task->error = error;
task->info->in_sync = FALSE;
--(task->mgr->n_running_tasks);
update_sync_info_error_state (task, SYNC_STATE_ERROR);
/* For repo-level errors, only need to record in database, but not send notifications.
* File-level errors are recorded and notified in the location they happens, not here.
*/
if (err_level == SYNC_ERROR_LEVEL_REPO)
seaf_repo_manager_record_sync_error (task->repo->id, task->repo->name, NULL, error);
#ifdef WIN32
seaf_sync_manager_add_refresh_path (seaf->sync_mgr, task->repo->worktree);
#endif
@ -632,13 +635,24 @@ seaf_sync_manager_set_task_error (SyncTask *task, int error)
}
}
void
seaf_sync_manager_set_task_error_code (SeafSyncManager *mgr,
const char *repo_id,
int error)
{
SyncInfo *info = g_hash_table_lookup (mgr->sync_infos, repo_id);
if (!info)
return;
info->current_task->error = error;
}
static void
sync_task_free (SyncTask *task)
{
g_free (task->tx_id);
g_free (task->dest_id);
g_free (task->token);
g_free (task->err_detail);
g_free (task);
}
@ -657,7 +671,7 @@ start_upload_if_necessary (SyncTask *task)
repo->use_fileserver_port,
&error) < 0) {
seaf_warning ("Failed to start http upload: %s\n", error->message);
seaf_sync_manager_set_task_error (task, SYNC_ERROR_START_UPLOAD);
set_task_error (task, SYNC_ERROR_ID_NOT_ENOUGH_MEMORY);
return;
}
task->tx_id = g_strdup(repo->id);
@ -685,7 +699,7 @@ start_fetch_if_necessary (SyncTask *task, const char *remote_head)
repo->name,
&error) < 0) {
seaf_warning ("Failed to start http download: %s.\n", error->message);
seaf_sync_manager_set_task_error (task, SYNC_ERROR_START_FETCH);
set_task_error (task, SYNC_ERROR_ID_NOT_ENOUGH_MEMORY);
return;
}
task->tx_id = g_strdup(repo->id);
@ -809,7 +823,7 @@ remove_blocks_done (void *vtask)
static void
on_repo_deleted_on_server (SyncTask *task, SeafRepo *repo)
{
seaf_sync_manager_set_task_error (task, SYNC_ERROR_NOREPO);
set_task_error (task, SYNC_ERROR_ID_SERVER_REPO_DELETED);
seaf_warning ("repo %s(%.8s) not found on server\n",
repo->name, repo->id);
@ -817,9 +831,9 @@ on_repo_deleted_on_server (SyncTask *task, SeafRepo *repo)
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_mq_manager_publish_notification (seaf->mq_mgr, */
/* "repo.deleted_on_relay", */
/* repo->name); */
seaf_repo_manager_del_repo (seaf->repo_mgr, repo);
}
}
@ -836,7 +850,7 @@ update_sync_status_v2 (SyncTask *task)
if (!local) {
seaf_warning ("[sync-mgr] Branch local not found for repo %s(%.8s).\n",
repo->name, repo->id);
seaf_sync_manager_set_task_error (task, SYNC_ERROR_DATA_CORRUPT);
set_task_error (task, SYNC_ERROR_ID_LOCAL_DATA_CORRUPT);
return;
}
@ -845,12 +859,12 @@ update_sync_status_v2 (SyncTask *task)
if (!master) {
seaf_warning ("[sync-mgr] Branch master not found for repo %s(%.8s).\n",
repo->name, repo->id);
seaf_sync_manager_set_task_error (task, SYNC_ERROR_DATA_CORRUPT);
set_task_error (task, SYNC_ERROR_ID_LOCAL_DATA_CORRUPT);
return;
}
if (info->repo_corrupted) {
seaf_sync_manager_set_task_error (task, SYNC_ERROR_REPO_CORRUPT);
set_task_error (task, SYNC_ERROR_ID_SERVER_REPO_CORRUPT);
} else if (info->deleted_on_relay) {
on_repo_deleted_on_server (task, repo);
} else {
@ -883,8 +897,7 @@ check_head_commit_done (HttpHeadCommit *result, void *user_data)
SyncInfo *info = task->info;
if (!result->check_success) {
seaf_sync_manager_set_task_error (task, SYNC_ERROR_GET_SYNC_INFO);
task->err_detail = g_strdup(http_task_error_str(result->error_code));
set_task_error (task, result->error_code);
return;
}
@ -910,7 +923,7 @@ check_head_commit_http (SyncTask *task)
if (ret == 0)
transition_sync_state (task, SYNC_STATE_INIT);
else if (ret < 0)
seaf_sync_manager_set_task_error (task, SYNC_ERROR_GET_SYNC_INFO);
set_task_error (task, SYNC_ERROR_ID_NOT_ENOUGH_MEMORY);
return ret;
}
@ -976,7 +989,7 @@ commit_job_done (void *vres)
}
if (!res->success) {
seaf_sync_manager_set_task_error (res->task, SYNC_ERROR_COMMIT);
set_task_error (res->task, SYNC_ERROR_ID_INDEX_ERROR);
g_free (res);
return;
}
@ -1012,7 +1025,7 @@ commit_repo (SyncTask *task)
commit_job,
commit_job_done,
task) < 0)
seaf_sync_manager_set_task_error (task, SYNC_ERROR_COMMIT);
set_task_error (task, SYNC_ERROR_ID_NOT_ENOUGH_MEMORY);
}
static int
@ -1045,6 +1058,7 @@ create_sync_task_v2 (SeafSyncManager *manager, SeafRepo *repo,
task->token = g_strdup(repo->token);
task->is_manual_sync = is_manual_sync;
task->is_initial_commit = is_initial_commit;
task->error = SYNC_ERROR_ID_NO_ERROR;
repo->last_sync_time = time(NULL);
++(manager->n_running_tasks);
@ -2025,17 +2039,6 @@ auto_sync_pulse (void *vmanager)
return TRUE;
}
inline static void
send_sync_error_notification (SeafRepo *repo, const char *type)
{
GString *buf = g_string_new (NULL);
g_string_append_printf (buf, "%s\t%s", repo->name, repo->id);
seaf_mq_manager_publish_notification (seaf->mq_mgr,
type,
buf->str);
g_string_free (buf, TRUE);
}
static void
on_repo_http_fetched (SeafileSession *seaf,
HttpTxTask *tx_task,
@ -2060,21 +2063,11 @@ on_repo_http_fetched (SeafileSession *seaf,
} else if (tx_task->state == HTTP_TASK_STATE_CANCELED) {
transition_sync_state (task, SYNC_STATE_CANCELED);
} else if (tx_task->state == HTTP_TASK_STATE_ERROR) {
if (tx_task->error == HTTP_TASK_ERR_FORBIDDEN ||
tx_task->error == HTTP_TASK_ERR_NO_WRITE_PERMISSION ||
tx_task->error == HTTP_TASK_ERR_NO_PERMISSION_TO_SYNC) {
seaf_sync_manager_set_task_error (task, SYNC_ERROR_ACCESS_DENIED);
if (!task->repo->access_denied_notified) {
send_sync_error_notification (task->repo, "sync.access_denied");
task->repo->access_denied_notified = 1;
}
} 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) {
if (tx_task->error == SYNC_ERROR_ID_SERVER_REPO_DELETED) {
on_repo_deleted_on_server (task, task->repo);
} else
seaf_sync_manager_set_task_error (task, SYNC_ERROR_FETCH);
task->err_detail = g_strdup(http_task_error_str(tx_task->error));
} else {
set_task_error (task, tx_task->error);
}
}
}
@ -2107,38 +2100,12 @@ on_repo_http_uploaded (SeafileSession *seaf,
} else if (tx_task->state == HTTP_TASK_STATE_CANCELED) {
transition_sync_state (task, SYNC_STATE_CANCELED);
} else if (tx_task->state == HTTP_TASK_STATE_ERROR) {
if (tx_task->error == HTTP_TASK_ERR_FORBIDDEN ||
tx_task->error == HTTP_TASK_ERR_NO_WRITE_PERMISSION ||
tx_task->error == HTTP_TASK_ERR_NO_PERMISSION_TO_SYNC) {
seaf_sync_manager_set_task_error (task, SYNC_ERROR_ACCESS_DENIED);
if (!task->repo->access_denied_notified) {
send_sync_error_notification (task->repo, "sync.access_denied");
task->repo->access_denied_notified = 1;
}
} else if (tx_task->error == HTTP_TASK_ERR_NO_QUOTA) {
seaf_sync_manager_set_task_error (task, SYNC_ERROR_QUOTA_FULL);
/* Only notify "quota full" once. */
if (!task->repo->quota_full_notified) {
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) {
if (tx_task->error == SYNC_ERROR_ID_SERVER_REPO_DELETED) {
on_repo_deleted_on_server (task, task->repo);
} else
seaf_sync_manager_set_task_error (task, SYNC_ERROR_UPLOAD);
task->err_detail = g_strdup(http_task_error_str(tx_task->error));
} else {
set_task_error (task, tx_task->error);
}
}
const char *
sync_error_to_str (int error)
{
if (error < 0 || error >= SYNC_ERROR_NUM) {
seaf_warning ("illegal sync error: %d\n", error);
return NULL;
}
return sync_error_str[error];
}
const char *

View File

@ -50,33 +50,6 @@ enum {
SYNC_STATE_NUM,
};
enum {
SYNC_ERROR_NONE,
SYNC_ERROR_RELAY_OFFLINE,
SYNC_ERROR_UPGRADE_REPO,
SYNC_ERROR_RELAY_REMOVED,
SYNC_ERROR_NOT_LOGIN,
SYNC_ERROR_SERVICE_DOWN,
SYNC_ERROR_ACCESS_DENIED,
SYNC_ERROR_QUOTA_FULL,
SYNC_ERROR_PROC_PERM_ERR,
SYNC_ERROR_DATA_CORRUPT,
SYNC_ERROR_START_UPLOAD,
SYNC_ERROR_UPLOAD,
SYNC_ERROR_START_FETCH,
SYNC_ERROR_FETCH,
SYNC_ERROR_NOREPO,
SYNC_ERROR_REPO_CORRUPT,
SYNC_ERROR_COMMIT,
SYNC_ERROR_MERGE,
SYNC_ERROR_WORKTREE_DIRTY,
SYNC_ERROR_DEPRECATED_SERVER,
SYNC_ERROR_GET_SYNC_INFO, /* for http sync */
SYNC_ERROR_FILES_LOCKED,
SYNC_ERROR_UNKNOWN,
SYNC_ERROR_NUM,
};
struct _SyncTask {
SeafSyncManager *mgr;
SyncInfo *info;
@ -85,7 +58,6 @@ struct _SyncTask {
gboolean is_initial_commit;
int state;
int error;
char *err_detail;
char *tx_id;
char *token;
struct SeafTimer *commit_timer;
@ -166,9 +138,6 @@ seaf_sync_manager_enable_auto_sync (SeafSyncManager *mgr);
int
seaf_sync_manager_is_auto_sync_enabled (SeafSyncManager *mgr);
const char *
sync_error_to_str (int error);
const char *
sync_state_to_str (int state);
@ -209,4 +178,9 @@ void
seaf_sync_manager_refresh_path (SeafSyncManager *mgr, const char *path);
#endif
void
seaf_sync_manager_set_task_error_code (SeafSyncManager *mgr,
const char *repo_id,
int error);
#endif

View File

@ -1,6 +1,8 @@
#ifndef SEAFILE_ERROR_H
#define SEAFILE_ERROR_H
/* Error codes used in RPC. */
#define SEAF_ERR_GENERAL 500
#define SEAF_ERR_BAD_REPO 501
#define SEAF_ERR_BAD_COMMIT 502
@ -19,4 +21,44 @@
#define SEAF_ERR_DIR_MISSING 515
#define SEAF_ERR_PATH_NO_EXIST 516 /* the dir or file pointed by this path not exists */
/* Sync errors. */
#define SYNC_ERROR_ID_FILE_LOCKED_BY_APP 0
#define SYNC_ERROR_ID_FOLDER_LOCKED_BY_APP 1
/* When file is locked on server. Returned in update-branch. */
#define SYNC_ERROR_ID_FILE_LOCKED 2
#define SYNC_ERROR_ID_INVALID_PATH 3
#define SYNC_ERROR_ID_INDEX_ERROR 4
#define SYNC_ERROR_ID_PATH_END_SPACE_PERIOD 5
#define SYNC_ERROR_ID_PATH_INVALID_CHARACTER 6
/* Returned in update-branch */
#define SYNC_ERROR_ID_FOLDER_PERM_DENIED 7
/* When there is no sync permission to library */
#define SYNC_ERROR_ID_PERM_NOT_SYNCABLE 8
/* Local error when updating a file in readonly library. */
#define SYNC_ERROR_ID_UPDATE_TO_READ_ONLY_REPO 9
/* When there is no read access to library. */
#define SYNC_ERROR_ID_ACCESS_DENIED 10
/* When there is no write access to library */
#define SYNC_ERROR_ID_NO_WRITE_PERMISSION 11
#define SYNC_ERROR_ID_QUOTA_FULL 12
#define SYNC_ERROR_ID_NETWORK 13
#define SYNC_ERROR_ID_RESOLVE_PROXY 14
#define SYNC_ERROR_ID_RESOLVE_HOST 15
#define SYNC_ERROR_ID_CONNECT 16
#define SYNC_ERROR_ID_SSL 17
#define SYNC_ERROR_ID_TX 18
#define SYNC_ERROR_ID_TX_TIMEOUT 19
#define SYNC_ERROR_ID_UNHANDLED_REDIRECT 20
#define SYNC_ERROR_ID_SERVER 21
#define SYNC_ERROR_ID_LOCAL_DATA_CORRUPT 22
#define SYNC_ERROR_ID_WRITE_LOCAL_DATA 23
#define SYNC_ERROR_ID_SERVER_REPO_DELETED 24
#define SYNC_ERROR_ID_SERVER_REPO_CORRUPT 25
#define SYNC_ERROR_ID_NOT_ENOUGH_MEMORY 26
#define SYNC_ERROR_ID_CONFLICT 27
#define SYNC_ERROR_ID_GENERAL_ERROR 28
#define SYNC_ERROR_ID_NO_ERROR 29
#define N_SYNC_ERROR_ID 30
#endif

View File

@ -30,15 +30,6 @@ GObject* seafile_get_repo (const gchar* id, GError **error);
GObject *
seafile_get_repo_sync_task (const char *repo_id, GError **error);
/**
* seafile_get_repo_sync_info:
*/
GObject *
seafile_get_repo_sync_info (const char *repo_id, GError **error);
GList*
seafile_get_repo_sinfo (const char *repo_id, GError **error);
/* [seafile_get_config] returns the value of the config entry whose name is
* [key] in config.db
*/

View File

@ -97,28 +97,12 @@ public class Repo : Object {
public bool is_shared { get; set; }
}
public class SyncInfo : Object {
public string repo_id { get; set; }
public string head_commit { get; set; }
public bool deleted_on_relay { get; set; }
public bool bad_local_branch { get; set; }
public bool need_fetch { get; set; }
public bool need_upload { get; set; }
public bool need_merge { get; set; }
// public int last_sync_time { get; set; }
}
public class SyncTask : Object {
public bool is_sync_lan { get; set; }
public bool force_upload { get; set; }
public string dest_id { get; set; }
public string repo_id { get; set; }
public string state { get; set; }
public string error { get; set; }
public string err_detail { get; set; }
public string tx_id { get; set; }
public int error { get; set; }
}
public class SessionInfo : Object {

View File

@ -21,8 +21,6 @@ public class Task : Object {
public string rt_state { get; set; }
public string error_str { get; set; }
public int64 block_total { get; set; }
public int64 block_done { get; set; } // the number of blocks sent or received
@ -47,13 +45,10 @@ public class Task : Object {
public class CloneTask : Object {
public string state { get; set; }
public string error_str { get; set; }
public string err_detail { get; set; }
public int error { get; set; }
public string repo_id { get; set; }
public string peer_id { get; set; }
public string repo_name { get; set; }
public string worktree { get; set; }
public string tx_id { get; set; }
}
} // namespace

View File

@ -139,11 +139,6 @@ class SeafileRpcClient(NamedPipeClient):
pass
find_transfer_task = seafile_find_transfer_task
@searpc_func("object", ["string"])
def seafile_get_checkout_task(repo_id):
pass
get_checkout_task = seafile_get_checkout_task
### sync
@searpc_func("int", ["string", "string"])
def seafile_sync(repo_id, peer_id):
@ -155,16 +150,16 @@ class SeafileRpcClient(NamedPipeClient):
pass
get_repo_sync_task = seafile_get_repo_sync_task
@searpc_func("object", ["string"])
def seafile_get_repo_sync_info():
pass
get_repo_sync_info = seafile_get_repo_sync_info
@searpc_func("int", [])
def seafile_is_auto_sync_enabled():
pass
is_auto_sync_enabled = seafile_is_auto_sync_enabled
@searpc_func("objlist", ["int", "int"])
def seafile_get_file_sync_errors():
pass
get_file_sync_errors = seafile_get_file_sync_errors
###### Property Management #########
@searpc_func("int", ["string", "string"])