From 686755f474bcacd1a765a486c9274ba59516d4b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=AC=A2=E4=B9=90=E9=A9=AC?= <38058090+SkywalkerSpace@users.noreply.github.com> Date: Mon, 4 Jan 2021 11:18:30 +0800 Subject: [PATCH 1/5] fix 8.0 sql (#436) --- scripts/upgrade/sql/8.0.0/mysql/seafevents.sql | 4 ++++ scripts/upgrade/sql/8.0.0/mysql/seahub.sql | 5 ----- scripts/upgrade/sql/8.0.0/sqlite3/seafevents.sql | 9 +++++++++ scripts/upgrade/sql/8.0.0/sqlite3/seahub.sql | 10 ---------- 4 files changed, 13 insertions(+), 15 deletions(-) create mode 100644 scripts/upgrade/sql/8.0.0/mysql/seafevents.sql create mode 100644 scripts/upgrade/sql/8.0.0/sqlite3/seafevents.sql diff --git a/scripts/upgrade/sql/8.0.0/mysql/seafevents.sql b/scripts/upgrade/sql/8.0.0/mysql/seafevents.sql new file mode 100644 index 0000000..93a851b --- /dev/null +++ b/scripts/upgrade/sql/8.0.0/mysql/seafevents.sql @@ -0,0 +1,4 @@ +ALTER TABLE `VirusFile` ADD COLUMN IF NOT EXISTS `has_ignored` TINYINT(1) NOT NULL DEFAULT 0; +ALTER TABLE `VirusFile` CHANGE `has_handle` `has_deleted` TINYINT(1); +ALTER TABLE `VirusFile` ADD INDEX IF NOT EXISTS `has_deleted` (`has_deleted`); +ALTER TABLE `VirusFile` ADD INDEX IF NOT EXISTS `has_ignored` (`has_ignored`); diff --git a/scripts/upgrade/sql/8.0.0/mysql/seahub.sql b/scripts/upgrade/sql/8.0.0/mysql/seahub.sql index e4a2fc9..7ab51b3 100644 --- a/scripts/upgrade/sql/8.0.0/mysql/seahub.sql +++ b/scripts/upgrade/sql/8.0.0/mysql/seahub.sql @@ -37,8 +37,3 @@ CREATE TABLE IF NOT EXISTS `ocm_share_received` ( KEY `ocm_share_received_repo_id_9e77a1b9` (`repo_id`), KEY `ocm_share_received_provider_id_60c873e0` (`provider_id`) ) ENGINE = InnoDB DEFAULT CHARSET=utf8; - -ALTER TABLE `VirusFile` ADD COLUMN IF NOT EXISTS `has_ignored` TINYINT(1) NOT NULL DEFAULT 0; -ALTER TABLE `VirusFile` CHANGE `has_handle` `has_deleted` TINYINT(1); -ALTER TABLE `VirusFile` ADD INDEX IF NOT EXISTS `has_deleted` (`has_deleted`); -ALTER TABLE `VirusFile` ADD INDEX IF NOT EXISTS `has_ignored` (`has_ignored`); diff --git a/scripts/upgrade/sql/8.0.0/sqlite3/seafevents.sql b/scripts/upgrade/sql/8.0.0/sqlite3/seafevents.sql new file mode 100644 index 0000000..2bc1695 --- /dev/null +++ b/scripts/upgrade/sql/8.0.0/sqlite3/seafevents.sql @@ -0,0 +1,9 @@ +DROP TABLE IF EXISTS "VirusFile_old"; +ALTER TABLE "VirusFile" RENAME TO "VirusFile_old"; +CREATE TABLE IF NOT EXISTS "VirusFile" ("vid" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "repo_id" varchar(36) NOT NULL, "commit_id" varchar(40) NOT NULL, "file_path" text NOT NULL, "has_deleted" tinyint(1) NOT NULL, "has_ignored" TINYINT(1) NOT NULL DEFAULT 0); +INSERT INTO "VirusFile" ("vid", "repo_id", "commit_id", "file_path", "has_deleted") SELECT "vid", "repo_id", "commit_id", "file_path", "has_handle" FROM "VirusFile_old"; +DROP TABLE "VirusFile_old"; + +CREATE INDEX IF NOT EXISTS "VirusFile_repo_id_yewnci4gd" ON "VirusFile" ("repo_id"); +CREATE INDEX IF NOT EXISTS "VirusFile_has_deleted_834ndyts" ON "VirusFile" ("has_deleted"); +CREATE INDEX IF NOT EXISTS "VirusFile_has_ignored_d84tvuwg" ON "VirusFile" ("has_ignored"); diff --git a/scripts/upgrade/sql/8.0.0/sqlite3/seahub.sql b/scripts/upgrade/sql/8.0.0/sqlite3/seahub.sql index 65b9175..cc0ee70 100644 --- a/scripts/upgrade/sql/8.0.0/sqlite3/seahub.sql +++ b/scripts/upgrade/sql/8.0.0/sqlite3/seahub.sql @@ -10,13 +10,3 @@ CREATE INDEX IF NOT EXISTS "ocm_share_received_to_user_0921d09a" ON "ocm_share_r CREATE INDEX IF NOT EXISTS "ocm_share_received_from_server_url_10527b80" ON "ocm_share_received" ("from_server_url"); CREATE INDEX IF NOT EXISTS "ocm_share_received_repo_id_9e77a1b9" ON "ocm_share_received" ("repo_id"); CREATE INDEX IF NOT EXISTS "ocm_share_received_provider_id_60c873e0" ON "ocm_share_received" ("provider_id"); - -DROP TABLE IF EXISTS "VirusFile_old"; -ALTER TABLE "VirusFile" RENAME TO "VirusFile_old"; -CREATE TABLE IF NOT EXISTS "VirusFile" ("vid" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "repo_id" varchar(36) NOT NULL, "commit_id" varchar(40) NOT NULL, "file_path" text NOT NULL, "has_deleted" tinyint(1) NOT NULL, "has_ignored" TINYINT(1) NOT NULL DEFAULT 0); -INSERT INTO "VirusFile" ("vid", "repo_id", "commit_id", "file_path", "has_deleted") SELECT "vid", "repo_id", "commit_id", "file_path", "has_handle" FROM "VirusFile_old"; -DROP TABLE "VirusFile_old"; - -CREATE INDEX IF NOT EXISTS "VirusFile_repo_id_yewnci4gd" ON "VirusFile" ("repo_id"); -CREATE INDEX IF NOT EXISTS "VirusFile_has_deleted_834ndyts" ON "VirusFile" ("has_deleted"); -CREATE INDEX IF NOT EXISTS "VirusFile_has_ignored_d84tvuwg" ON "VirusFile" ("has_ignored"); From a9d134715259133f13ad7424a4fd9256412e45e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=AC=A2=E4=B9=90=E9=A9=AC?= <38058090+SkywalkerSpace@users.noreply.github.com> Date: Mon, 4 Jan 2021 15:04:22 +0800 Subject: [PATCH 2/5] sql 8.0 repo_auto_delete (#438) --- scripts/upgrade/sql/8.0.0/mysql/seahub.sql | 8 ++++++++ scripts/upgrade/sql/8.0.0/sqlite3/seahub.sql | 2 ++ 2 files changed, 10 insertions(+) diff --git a/scripts/upgrade/sql/8.0.0/mysql/seahub.sql b/scripts/upgrade/sql/8.0.0/mysql/seahub.sql index 7ab51b3..7ba03b0 100644 --- a/scripts/upgrade/sql/8.0.0/mysql/seahub.sql +++ b/scripts/upgrade/sql/8.0.0/mysql/seahub.sql @@ -37,3 +37,11 @@ CREATE TABLE IF NOT EXISTS `ocm_share_received` ( KEY `ocm_share_received_repo_id_9e77a1b9` (`repo_id`), KEY `ocm_share_received_provider_id_60c873e0` (`provider_id`) ) ENGINE = InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE IF NOT EXISTS `repo_auto_delete` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `repo_id` varchar(36) NOT NULL, + `days` int(11) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `repo_id` (`repo_id`) +) ENGINE = InnoDB DEFAULT CHARSET=utf8; diff --git a/scripts/upgrade/sql/8.0.0/sqlite3/seahub.sql b/scripts/upgrade/sql/8.0.0/sqlite3/seahub.sql index cc0ee70..ea14647 100644 --- a/scripts/upgrade/sql/8.0.0/sqlite3/seahub.sql +++ b/scripts/upgrade/sql/8.0.0/sqlite3/seahub.sql @@ -10,3 +10,5 @@ CREATE INDEX IF NOT EXISTS "ocm_share_received_to_user_0921d09a" ON "ocm_share_r CREATE INDEX IF NOT EXISTS "ocm_share_received_from_server_url_10527b80" ON "ocm_share_received" ("from_server_url"); CREATE INDEX IF NOT EXISTS "ocm_share_received_repo_id_9e77a1b9" ON "ocm_share_received" ("repo_id"); CREATE INDEX IF NOT EXISTS "ocm_share_received_provider_id_60c873e0" ON "ocm_share_received" ("provider_id"); + +CREATE TABLE IF NOT EXISTS "repo_auto_delete" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "repo_id" varchar(36) NOT NULL UNIQUE, "days" integer NOT NULL); From f94baf09c3322732276617105f3f4f24b446b12e Mon Sep 17 00:00:00 2001 From: feiniks <36756310+feiniks@users.noreply.github.com> Date: Tue, 5 Jan 2021 15:14:02 +0800 Subject: [PATCH 3/5] Improve fs-id-list API (#431) (#441) * Improve fs-id-list API * Del unused log * Del invalid parameter log * Don't return json error --- server/http-server.c | 317 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 317 insertions(+) diff --git a/server/http-server.c b/server/http-server.c index 88ab9c9..21fe812 100644 --- a/server/http-server.c +++ b/server/http-server.c @@ -54,6 +54,9 @@ #define PERM_EXPIRE_TIME 7200 /* 2 hours */ #define VIRINFO_EXPIRE_TIME 7200 /* 2 hours */ +#define FS_ID_LIST_MAX_WORKERS 3 +#define FS_ID_LIST_TOKEN_LEN 36 + struct _HttpServer { evbase_t *evbase; evhtp_t *evhtp; @@ -69,6 +72,11 @@ struct _HttpServer { pthread_mutex_t vir_repo_info_cache_lock; event_t *reap_timer; + + GThreadPool *compute_fs_obj_id_pool; + + GHashTable *fs_obj_ids; + pthread_mutex_t fs_obj_ids_lock; }; typedef struct _HttpServer HttpServer; @@ -115,6 +123,9 @@ const char *GET_HEAD_COMMITS_MULTI_REGEX = "^/repo/head-commits-multi"; const char *COMMIT_OPER_REGEX = "^/repo/[\\da-z]{8}-[\\da-z]{4}-[\\da-z]{4}-[\\da-z]{4}-[\\da-z]{12}/commit/[\\da-z]{40}"; const char *PUT_COMMIT_INFO_REGEX = "^/repo/[\\da-z]{8}-[\\da-z]{4}-[\\da-z]{4}-[\\da-z]{4}-[\\da-z]{12}/commit/[\\da-z]{40}"; const char *GET_FS_OBJ_ID_REGEX = "^/repo/[\\da-z]{8}-[\\da-z]{4}-[\\da-z]{4}-[\\da-z]{4}-[\\da-z]{12}/fs-id-list/.*"; +const char *START_FS_OBJ_ID_REGEX = "^/repo/[\\da-z]{8}-[\\da-z]{4}-[\\da-z]{4}-[\\da-z]{4}-[\\da-z]{12}/start-fs-id-list/.*"; +const char *QUERY_FS_OBJ_ID_REGEX = "^/repo/[\\da-z]{8}-[\\da-z]{4}-[\\da-z]{4}-[\\da-z]{4}-[\\da-z]{12}/query-fs-id-list/.*"; +const char *RETRIEVE_FS_OBJ_ID_REGEX = "^/repo/[\\da-z]{8}-[\\da-z]{4}-[\\da-z]{4}-[\\da-z]{4}-[\\da-z]{12}/retrieve-fs-id-list/.*"; const char *BLOCK_OPER_REGEX = "^/repo/[\\da-z]{8}-[\\da-z]{4}-[\\da-z]{4}-[\\da-z]{4}-[\\da-z]{12}/block/[\\da-z]{40}"; const char *POST_CHECK_FS_REGEX = "^/repo/[\\da-z]{8}-[\\da-z]{4}-[\\da-z]{4}-[\\da-z]{4}-[\\da-z]{12}/check-fs"; const char *POST_CHECK_BLOCK_REGEX = "^/repo/[\\da-z]{8}-[\\da-z]{4}-[\\da-z]{4}-[\\da-z]{4}-[\\da-z]{12}/check-blocks"; @@ -1531,6 +1542,293 @@ out: seaf_repo_unref (repo); } +typedef struct ComputeObjTask { + HttpServer *htp_server; + char *token; + char *repo_id; + char *client_head; + char *server_head; + gboolean dir_only; +} ComputeObjTask; + +typedef struct CalObjResult { + GList *list; + gboolean done; +} CalObjResult; + +static void +free_compute_obj_task(ComputeObjTask *task) +{ + if (!task) + return; + + if (task->token) + g_free(task->token); + if (task->repo_id) + g_free(task->repo_id); + if (task->client_head) + g_free(task->client_head); + if (task->server_head) + g_free(task->server_head); + g_free(task); +} + +static void +free_obj_cal_result (gpointer data) +{ + CalObjResult *result = (CalObjResult *)data; + if (!result) + return; + + if (result->list) + g_list_free (result->list); + + g_free(result); +} + +static void +compute_fs_obj_id (gpointer ptask, gpointer ppara) +{ + SeafRepo *repo = NULL; + ComputeObjTask *task = ptask; + const char *client_head = task->client_head; + const char *server_head = task->server_head; + char *repo_id = task->repo_id; + gboolean dir_only = task->dir_only; + HttpServer *htp_server = task->htp_server; + CalObjResult *result = NULL; + + pthread_mutex_lock (&htp_server->fs_obj_ids_lock); + result = g_hash_table_lookup (htp_server->fs_obj_ids, task->token); + pthread_mutex_unlock (&htp_server->fs_obj_ids_lock); + if (!result) { + goto out; + } + + repo = seaf_repo_manager_get_repo (seaf->repo_mgr, repo_id); + if (!repo) { + seaf_warning ("Failed to find repo %.8s.\n", repo_id); + goto out; + } + + if (calculate_send_object_list (repo, server_head, client_head, dir_only, &result->list) < 0) { + pthread_mutex_lock (&htp_server->fs_obj_ids_lock); + g_hash_table_remove (htp_server->fs_obj_ids, task->token); + pthread_mutex_unlock (&htp_server->fs_obj_ids_lock); + goto out; + } + + result->done = TRUE; +out: + seaf_repo_unref (repo); + free_compute_obj_task(task); +} + +static void +start_fs_obj_id_cb (evhtp_request_t *req, void *arg) +{ + HttpServer *htp_server = arg; + char **parts; + char *repo_id; + gboolean dir_only = FALSE; + json_t *obj; + + const char *server_head = evhtp_kv_find (req->uri->query, "server-head"); + if (server_head == NULL || !is_object_id_valid (server_head)) { + char *error = "Invalid server-head parameter.\n"; + evbuffer_add (req->buffer_out, error, strlen (error)); + evhtp_send_reply (req, EVHTP_RES_BADREQ); + return; + } + + const char *client_head = evhtp_kv_find (req->uri->query, "client-head"); + if (client_head && !is_object_id_valid (client_head)) { + char *error = "Invalid client-head parameter.\n"; + evbuffer_add (req->buffer_out, error, strlen (error)); + evhtp_send_reply (req, EVHTP_RES_BADREQ); + return; + } + + const char *dir_only_arg = evhtp_kv_find (req->uri->query, "dir-only"); + if (dir_only_arg) + dir_only = TRUE; + + parts = g_strsplit (req->uri->path->full + 1, "/", 0); + repo_id = parts[1]; + + int 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 uuid[37]; + char *new_token; + gen_uuid_inplace (uuid); + new_token = g_strndup(uuid, FS_ID_LIST_TOKEN_LEN); + + CalObjResult *result = g_new0(CalObjResult, 1); + if (!result) { + evhtp_send_reply (req, EVHTP_RES_SERVERR); + goto out; + } + result->done = FALSE; + + ComputeObjTask *task = g_new0 (ComputeObjTask, 1); + if (!task) { + evhtp_send_reply (req, EVHTP_RES_SERVERR); + goto out; + } + + task->token = new_token; + task->dir_only = dir_only; + task->htp_server = htp_server; + task->repo_id = g_strdup(repo_id); + task->client_head = g_strdup(client_head); + task->server_head = g_strdup(server_head); + + pthread_mutex_lock (&htp_server->fs_obj_ids_lock); + g_hash_table_insert (htp_server->fs_obj_ids, g_strdup(task->token), result); + pthread_mutex_unlock (&htp_server->fs_obj_ids_lock); + g_thread_pool_push (htp_server->compute_fs_obj_id_pool, task, NULL); + obj = json_object (); + json_object_set_new (obj, "token", json_string (new_token)); + + char *json_str = json_dumps (obj, JSON_COMPACT); + evbuffer_add (req->buffer_out, json_str, strlen(json_str)); + evhtp_send_reply (req, EVHTP_RES_OK); + + g_free (json_str); + json_decref (obj); +out: + g_strfreev (parts); +} + +static void +query_fs_obj_id_cb (evhtp_request_t *req, void *arg) +{ + json_t *obj; + const char *token = NULL; + CalObjResult *result = NULL; + char **parts; + char *repo_id = NULL; + HttpServer *htp_server = (HttpServer *)arg; + + parts = g_strsplit (req->uri->path->full + 1, "/", 0); + repo_id = parts[1]; + + int 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; + } + + token = evhtp_kv_find (req->uri->query, "token"); + if (!token || strlen(token)!=FS_ID_LIST_TOKEN_LEN) { + evhtp_send_reply (req, EVHTP_RES_BADREQ); + goto out; + } + + obj = json_object (); + + pthread_mutex_lock (&htp_server->fs_obj_ids_lock); + result = g_hash_table_lookup (htp_server->fs_obj_ids, token); + if (!result) { + pthread_mutex_unlock (&htp_server->fs_obj_ids_lock); + evhtp_send_reply (req, EVHTP_RES_NOTFOUND); + goto out; + } else { + if (!result->done) { + json_object_set_new (obj, "success", json_false()); + } else { + json_object_set_new (obj, "success", json_true()); + } + } + pthread_mutex_unlock (&htp_server->fs_obj_ids_lock); + + json_object_set_new (obj, "token", json_string (token)); + + char *json_str = json_dumps (obj, JSON_COMPACT); + evbuffer_add (req->buffer_out, json_str, strlen(json_str)); + evhtp_send_reply (req, EVHTP_RES_OK); + + g_free (json_str); + +out: + if (obj) + json_decref (obj); + g_strfreev (parts); + return; +} + +static void +retrieve_fs_obj_id_cb (evhtp_request_t *req, void *arg) +{ + char **parts; + const char *token = NULL; + char *repo_id = NULL; + GList *list = NULL; + CalObjResult *result = NULL; + HttpServer *htp_server = (HttpServer *)arg; + + parts = g_strsplit (req->uri->path->full + 1, "/", 0); + repo_id = parts[1]; + + int 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; + } + + token = evhtp_kv_find (req->uri->query, "token"); + if (!token || strlen(token)!=FS_ID_LIST_TOKEN_LEN) { + evhtp_send_reply (req, EVHTP_RES_BADREQ); + goto out; + } + + pthread_mutex_lock (&htp_server->fs_obj_ids_lock); + result = g_hash_table_lookup (htp_server->fs_obj_ids, token); + if (!result) { + pthread_mutex_unlock (&htp_server->fs_obj_ids_lock); + evhtp_send_reply (req, EVHTP_RES_NOTFOUND); + + return; + } + if (!result->done) { + pthread_mutex_unlock (&htp_server->fs_obj_ids_lock); + + char *error = "The cauculation task is not completed.\n"; + evbuffer_add (req->buffer_out, error, strlen(error)); + evhtp_send_reply (req, EVHTP_RES_BADREQ); + return; + } + list = result->list; + pthread_mutex_unlock (&htp_server->fs_obj_ids_lock); + + GList *ptr; + json_t *obj_array = json_array (); + + for (ptr = list; ptr; ptr = ptr->next) { + json_array_append_new (obj_array, json_string (ptr->data)); + g_free (ptr->data); + } + + pthread_mutex_lock (&htp_server->fs_obj_ids_lock); + g_hash_table_remove (htp_server->fs_obj_ids, token); + pthread_mutex_unlock (&htp_server->fs_obj_ids_lock); + + char *obj_list = json_dumps (obj_array, JSON_COMPACT); + evbuffer_add (req->buffer_out, obj_list, strlen (obj_list)); + evhtp_send_reply (req, EVHTP_RES_OK); + + g_free (obj_list); + json_decref (obj_array); + +out: + g_strfreev (parts); + return; +} + static void get_block_cb (evhtp_request_t *req, void *arg) { @@ -2346,6 +2644,18 @@ http_request_init (HttpServerStruct *server) GET_FS_OBJ_ID_REGEX, get_fs_obj_id_cb, priv); + evhtp_set_regex_cb (priv->evhtp, + START_FS_OBJ_ID_REGEX, start_fs_obj_id_cb, + priv); + + evhtp_set_regex_cb (priv->evhtp, + QUERY_FS_OBJ_ID_REGEX, query_fs_obj_id_cb, + priv); + + evhtp_set_regex_cb (priv->evhtp, + RETRIEVE_FS_OBJ_ID_REGEX, retrieve_fs_obj_id_cb, + priv); + evhtp_set_regex_cb (priv->evhtp, BLOCK_OPER_REGEX, block_oper_cb, priv); @@ -2530,6 +2840,13 @@ seaf_http_server_new (struct _SeafileSession *session) server->http_temp_dir = g_build_filename (session->seaf_dir, "httptemp", NULL); + priv->compute_fs_obj_id_pool = g_thread_pool_new (compute_fs_obj_id, NULL, + FS_ID_LIST_MAX_WORKERS, FALSE, NULL); + + priv->fs_obj_ids = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, free_obj_cal_result); + pthread_mutex_init (&priv->fs_obj_ids_lock, NULL); + server->seaf_session = session; server->priv = priv; From 44a2ce41d10e9e72b43634cffef7f0564399165c Mon Sep 17 00:00:00 2001 From: feiniks <36756310+feiniks@users.noreply.github.com> Date: Thu, 21 Jan 2021 11:44:07 +0800 Subject: [PATCH 4/5] Add ccnet config for fuse (#443) --- fuse/seafile-session.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fuse/seafile-session.c b/fuse/seafile-session.c index c627347..7a6815f 100644 --- a/fuse/seafile-session.c +++ b/fuse/seafile-session.c @@ -90,6 +90,7 @@ seafile_session_new(const char *central_config_dir, session->ccnet_dir = abs_ccnet_dir; session->tmp_file_dir = tmp_file_dir; session->config = config; + session->ccnet_config = ccnet_config; session->excluded_users = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); From 814b796038e229fb5c2842878b6b9faa97e8f1d2 Mon Sep 17 00:00:00 2001 From: feiniks <36756310+feiniks@users.noreply.github.com> Date: Mon, 1 Feb 2021 16:02:47 +0800 Subject: [PATCH 5/5] Close connection when failed to query mysql (#446) * Close connection when failed to query mysql (#318) * Close connection when failed to query mysql * Close connection when failed to handle transaction * Fix ci error --- common/seaf-db.c | 46 +++++++++++++++++++++++++++++++++------------- 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/common/seaf-db.c b/common/seaf-db.c index 59bba91..d4d7bb7 100644 --- a/common/seaf-db.c +++ b/common/seaf-db.c @@ -35,11 +35,12 @@ struct SeafDBRow { struct SeafDBTrans { DBConnection *conn; + gboolean need_close; }; typedef struct DBOperations { DBConnection* (*get_connection)(SeafDB *db); - void (*release_connection)(DBConnection *conn); + void (*release_connection)(DBConnection *conn, gboolean need_close); int (*execute_sql_no_stmt)(DBConnection *conn, const char *sql); int (*execute_sql)(DBConnection *conn, const char *sql, int n, va_list args); @@ -138,7 +139,7 @@ out: } static void -mysql_conn_pool_release_connection (DBConnection *conn) +mysql_conn_pool_release_connection (DBConnection *conn, gboolean need_close) { if (!conn) return; @@ -148,6 +149,14 @@ mysql_conn_pool_release_connection (DBConnection *conn) return; } + if (need_close) { + pthread_mutex_lock (&conn->pool->lock); + g_ptr_array_remove (conn->pool->connections, conn); + pthread_mutex_unlock (&conn->pool->lock); + mysql_db_release_connection (conn); + return; + } + pthread_mutex_lock (&conn->pool->lock); conn->is_available = TRUE; pthread_mutex_unlock (&conn->pool->lock); @@ -227,7 +236,7 @@ sqlite_db_new (const char *db_path); static DBConnection * sqlite_db_get_connection (SeafDB *db); static void -sqlite_db_release_connection (DBConnection *vconn); +sqlite_db_release_connection (DBConnection *vconn, gboolean need_close); static int sqlite_db_execute_sql_no_stmt (DBConnection *vconn, const char *sql); static int @@ -284,7 +293,7 @@ seaf_db_query (SeafDB *db, const char *sql) int ret; ret = db_ops.execute_sql_no_stmt (conn, sql); - db_ops.release_connection (conn); + db_ops.release_connection (conn, ret < 0); return ret; } @@ -358,7 +367,7 @@ seaf_db_statement_query (SeafDB *db, const char *sql, int n, ...) ret = db_ops.execute_sql (conn, sql, n, args); va_end (args); - db_ops.release_connection (conn); + db_ops.release_connection (conn, ret < 0); return ret; } @@ -380,7 +389,7 @@ seaf_db_statement_exists (SeafDB *db, const char *sql, gboolean *db_err, int n, n_rows = db_ops.query_foreach_row (conn, sql, NULL, NULL, n, args); va_end (args); - db_ops.release_connection(conn); + db_ops.release_connection(conn, n_rows < 0); if (n_rows < 0) { *db_err = TRUE; @@ -408,7 +417,7 @@ seaf_db_statement_foreach_row (SeafDB *db, const char *sql, ret = db_ops.query_foreach_row (conn, sql, callback, data, n, args); va_end (args); - db_ops.release_connection (conn); + db_ops.release_connection (conn, ret < 0); return ret; } @@ -439,7 +448,7 @@ seaf_db_statement_get_int (SeafDB *db, const char *sql, int n, ...) rc = db_ops.query_foreach_row (conn, sql, get_int_cb, &ret, n, args); va_end (args); - db_ops.release_connection (conn); + db_ops.release_connection (conn, rc < 0); if (rc < 0) return -1; @@ -473,7 +482,7 @@ seaf_db_statement_get_int64 (SeafDB *db, const char *sql, int n, ...) rc = db_ops.query_foreach_row (conn, sql, get_int64_cb, &ret, n, args); va_end(args); - db_ops.release_connection (conn); + db_ops.release_connection (conn, rc < 0); if (rc < 0) return -1; @@ -507,7 +516,7 @@ seaf_db_statement_get_string (SeafDB *db, const char *sql, int n, ...) rc = db_ops.query_foreach_row (conn, sql, get_string_cb, &ret, n, args); va_end(args); - db_ops.release_connection (conn); + db_ops.release_connection (conn, rc < 0); if (rc < 0) return NULL; @@ -527,7 +536,7 @@ seaf_db_begin_transaction (SeafDB *db) } if (db_ops.execute_sql_no_stmt (conn, "BEGIN") < 0) { - db_ops.release_connection (conn); + db_ops.release_connection (conn, TRUE); return trans; } @@ -540,7 +549,7 @@ seaf_db_begin_transaction (SeafDB *db) void seaf_db_trans_close (SeafDBTrans *trans) { - db_ops.release_connection (trans->conn); + db_ops.release_connection (trans->conn, trans->need_close); g_free (trans); } @@ -550,6 +559,7 @@ seaf_db_commit (SeafDBTrans *trans) DBConnection *conn = trans->conn; if (db_ops.execute_sql_no_stmt (conn, "COMMIT") < 0) { + trans->need_close = TRUE; return -1; } @@ -562,6 +572,7 @@ seaf_db_rollback (SeafDBTrans *trans) DBConnection *conn = trans->conn; if (db_ops.execute_sql_no_stmt (conn, "ROLLBACK") < 0) { + trans->need_close = TRUE; return -1; } @@ -578,6 +589,9 @@ seaf_db_trans_query (SeafDBTrans *trans, const char *sql, int n, ...) ret = db_ops.execute_sql (trans->conn, sql, n, args); va_end (args); + if (ret < 0) + trans->need_close = TRUE; + return ret; } @@ -595,6 +609,7 @@ seaf_db_trans_check_for_existence (SeafDBTrans *trans, va_end (args); if (n_rows < 0) { + trans->need_close = TRUE; *db_err = TRUE; return FALSE; } else { @@ -615,6 +630,9 @@ seaf_db_trans_foreach_selected_row (SeafDBTrans *trans, const char *sql, ret = db_ops.query_foreach_row (trans->conn, sql, callback, data, n, args); va_end (args); + if (ret < 0) + trans->need_close = TRUE; + return ret; } @@ -679,6 +697,8 @@ mysql_db_new (const char *host, return (SeafDB *)db; } +typedef char my_bool; + static DBConnection * mysql_db_get_connection (SeafDB *vdb) { @@ -1200,7 +1220,7 @@ sqlite_db_get_connection (SeafDB *vdb) } static void -sqlite_db_release_connection (DBConnection *vconn) +sqlite_db_release_connection (DBConnection *vconn, gboolean need_close) { if (!vconn) return;