From 40c6706acc82e598f72a991cebc50b7a48263302 Mon Sep 17 00:00:00 2001 From: Jiaqiang Xu Date: Sat, 29 Oct 2016 15:07:20 +0800 Subject: [PATCH] Fix SQLite "database is locked" problem. Need to use shared cache mode to open db connections. Also use "unlock_notify" API instead of timed retry. --- common/db-wrapper/db-wrapper.c | 1 + common/db-wrapper/db-wrapper.h | 1 + common/db-wrapper/sqlite-db-ops.c | 26 +++++++++++++------------- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/common/db-wrapper/db-wrapper.c b/common/db-wrapper/db-wrapper.c index e6fb7cc..d434145 100644 --- a/common/db-wrapper/db-wrapper.c +++ b/common/db-wrapper/db-wrapper.c @@ -196,6 +196,7 @@ db_conn_pool_get_connection (DBConnPool *pool, GError **error) if (conn) { conn->is_available = FALSE; conn->pool = pool; + conn->conn_no = size; g_ptr_array_add (pool->connections, conn); } } diff --git a/common/db-wrapper/db-wrapper.h b/common/db-wrapper/db-wrapper.h index 4d3fdc8..8345b53 100644 --- a/common/db-wrapper/db-wrapper.h +++ b/common/db-wrapper/db-wrapper.h @@ -55,6 +55,7 @@ struct DBConnection { DBConnPool *pool; ResultSet *result_set; DBStmt *stmt; + int conn_no; }; typedef struct DBConnection DBConnection; diff --git a/common/db-wrapper/sqlite-db-ops.c b/common/db-wrapper/sqlite-db-ops.c index 070dc80..87b7c55 100644 --- a/common/db-wrapper/sqlite-db-ops.c +++ b/common/db-wrapper/sqlite-db-ops.c @@ -6,8 +6,6 @@ #include #include -#if 0 - /* SQLite thread synchronization rountines. */ typedef struct UnlockNotification { @@ -90,7 +88,7 @@ sqlite3_blocking_exec(sqlite3 *db, const char *sql, int (*callback)(void *, int, return rc; } -#endif +#if 0 #define SQLITE_QUERY_TIMEOUT 3 @@ -101,12 +99,14 @@ sqlite3_blocking_exec(sqlite3 *db, const char *sql, int (*callback)(void *, int, do {\ status = (action);\ if (((status == SQLITE_BUSY) || (status == SQLITE_LOCKED)) && (x++ <= 9))\ - g_usleep(t/(rand() % 10 + 100));\ + g_usleep(t/(rand() % 3 + 10));\ else\ break;\ } while (1);\ } while (0) +#endif /* 0 */ + typedef struct SQLiteDBConnPool { DBConnPool parent; char *db_path; @@ -147,7 +147,7 @@ sqlite_get_db_connection (DBConnPool *vpool, GError **error) const char *errmsg; SQLiteDBConnection *conn; - result = sqlite3_open (pool->db_path, &db); + result = sqlite3_open_v2 (pool->db_path, &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_SHAREDCACHE, NULL); if (result != SQLITE_OK) { errmsg = sqlite3_errmsg(db); g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, @@ -188,7 +188,7 @@ sqlite_db_connection_execute (DBConnection *vconn, const char *sql, GError **err char *errmsg = NULL; int rc; - EXEC_SQLITE(rc, sqlite3_exec (conn->db, sql, NULL, NULL, &errmsg)); + rc = sqlite3_blocking_exec (conn->db, sql, NULL, NULL, &errmsg); if (rc != SQLITE_OK) { g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, "sqlite3_exec failed: %s", @@ -229,7 +229,7 @@ sqlite_execute_query (DBConnection *vconn, const char *sql, GError **error) int rc; SQLiteResultSet *r; - EXEC_SQLITE(rc, sqlite3_prepare_v2(conn->db, sql, -1, &stmt, NULL)); + rc = sqlite3_blocking_prepare_v2 (conn->db, sql, -1, &stmt, NULL); if (rc != SQLITE_OK) { g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, "sqlite3_prepare_v2 failed: %s", sqlite3_errmsg(conn->db)); @@ -250,7 +250,7 @@ sqlite_result_set_next (ResultSet *vr, GError **error) SQLiteResultSet *r = (SQLiteResultSet *)vr; int rc; - EXEC_SQLITE(rc, sqlite3_step(r->stmt)); + rc = sqlite3_blocking_step (r->stmt); if (rc != SQLITE_ROW && rc != SQLITE_DONE) { g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, "sqlite3_step failed: %s", sqlite3_errmsg(r->db)); @@ -295,7 +295,7 @@ sqlite_prepare_statement (DBConnection *vconn, const char *sql, GError **error) int rc; SQLiteDBStmt *ret; - EXEC_SQLITE(rc, sqlite3_prepare_v2 (conn->db, sql, -1, &stmt, NULL)); + rc = sqlite3_blocking_prepare_v2 (conn->db, sql, -1, &stmt, NULL); if (rc != SQLITE_OK) { g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, "sqlite3_prepare_v2 failed: %s", sqlite3_errmsg(conn->db)); @@ -382,7 +382,7 @@ sqlite_db_stmt_execute (DBStmt *vstmt, GError **error) SQLiteDBStmt *stmt = (SQLiteDBStmt *)vstmt; int rc; - EXEC_SQLITE(rc, sqlite3_step(stmt->stmt)); + rc = sqlite3_blocking_step (stmt->stmt); if (rc == SQLITE_DONE) { sqlite3_reset (stmt->stmt); return TRUE; @@ -434,7 +434,7 @@ sqlite_db_begin_transaction (DBConnection *vconn, GError **error) SQLiteDBConnection *conn = (SQLiteDBConnection *)vconn; int rc; - EXEC_SQLITE(rc, sqlite3_exec (conn->db, "BEGIN TRANSACTION;", NULL, NULL, NULL)); + rc = sqlite3_blocking_exec (conn->db, "BEGIN TRANSACTION;", NULL, NULL, NULL); if (rc != SQLITE_OK) { g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, "begin transaction failed: %s", sqlite3_errmsg(conn->db)); @@ -450,7 +450,7 @@ sqlite_db_commit (DBConnection *vconn, GError **error) SQLiteDBConnection *conn = (SQLiteDBConnection *)vconn; int rc; - EXEC_SQLITE(rc, sqlite3_exec (conn->db, "COMMIT TRANSACTION;", NULL, NULL, NULL)); + rc = sqlite3_blocking_exec (conn->db, "COMMIT TRANSACTION;", NULL, NULL, NULL); if (rc != SQLITE_OK) { g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, "commit transaction failed: %s", sqlite3_errmsg(conn->db)); @@ -466,7 +466,7 @@ sqlite_db_rollback (DBConnection *vconn, GError **error) SQLiteDBConnection *conn = (SQLiteDBConnection *)vconn; int rc; - EXEC_SQLITE(rc, sqlite3_exec (conn->db, "ROLLBACK TRANSACTION;", NULL, NULL, NULL)); + rc = sqlite3_blocking_exec (conn->db, "ROLLBACK TRANSACTION;", NULL, NULL, NULL); if (rc != SQLITE_OK) { g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, "rollback transaction failed: %s", sqlite3_errmsg(conn->db));