CSync: Close/Reopen DB between update and reconcile

update and reconcile happen in different threads. This code is safer.
(Even though depending on sqlite3 version it should work anyway)
This commit is contained in:
Markus Goetz 2014-10-22 15:41:29 +02:00
parent 9330d2e1e8
commit 47ad4e3fe8
3 changed files with 49 additions and 44 deletions

View file

@ -228,9 +228,10 @@ int csync_update(CSYNC *ctx) {
rc = csync_ftw(ctx, ctx->local.uri, csync_walker, MAX_DEPTH);
if (rc < 0) {
if(ctx->status_code == CSYNC_STATUS_OK)
if(ctx->status_code == CSYNC_STATUS_OK) {
ctx->status_code = csync_errno_to_status(errno, CSYNC_STATUS_UPDATE_ERROR);
return -1;
}
goto out;
}
csync_gettime(&finish);
@ -247,20 +248,14 @@ int csync_update(CSYNC *ctx) {
rc = csync_ftw(ctx, ctx->remote.uri, csync_walker, MAX_DEPTH);
if (rc < 0) {
if(ctx->status_code == CSYNC_STATUS_OK)
if(ctx->status_code == CSYNC_STATUS_OK) {
ctx->status_code = csync_errno_to_status(errno, CSYNC_STATUS_UPDATE_ERROR);
return -1;
}
goto out;
}
csync_gettime(&finish);
/* Finalize the sql precompiled statements after the update run since
* it runs in its own thread. Precompiled statements shoult not be shared
* across thread borders according to
* http://www.sqlite.org/cvstrac/wiki?p=MultiThreading
*/
csync_statedb_finalize_statements(ctx);
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG,
"Update detection for remote replica took %.2f seconds "
"walking %zu files.",
@ -269,7 +264,11 @@ int csync_update(CSYNC *ctx) {
ctx->status |= CSYNC_STATUS_UPDATE;
return 0;
rc = 0;
out:
csync_statedb_close(ctx);
return rc;
}
int csync_reconcile(CSYNC *ctx) {
@ -285,6 +284,12 @@ int csync_reconcile(CSYNC *ctx) {
/* Reconciliation for local replica */
csync_gettime(&start);
if (csync_statedb_load(ctx, ctx->statedb.file, &ctx->statedb.db) < 0) {
ctx->status_code = CSYNC_STATUS_STATEDB_LOAD_ERROR;
rc = -1;
return rc;
}
ctx->current = LOCAL_REPLICA;
ctx->replica = ctx->local.type;
@ -300,7 +305,7 @@ int csync_reconcile(CSYNC *ctx) {
if (!CSYNC_STATUS_IS_OK(ctx->status_code)) {
ctx->status_code = csync_errno_to_status( errno, CSYNC_STATUS_RECONCILE_ERROR );
}
return -1;
goto out;
}
/* Reconciliation for remote replica */
@ -321,11 +326,15 @@ int csync_reconcile(CSYNC *ctx) {
if (!CSYNC_STATUS_IS_OK(ctx->status_code)) {
ctx->status_code = csync_errno_to_status(errno, CSYNC_STATUS_RECONCILE_ERROR );
}
return -1;
goto out;
}
ctx->status |= CSYNC_STATUS_RECONCILE;
rc = 0;
out:
csync_statedb_close(ctx);
return 0;
}

View file

@ -129,6 +129,11 @@ int csync_statedb_load(CSYNC *ctx, const char *statedb, sqlite3 **pdb) {
return -1;
}
if (ctx->statedb.db) {
CSYNC_LOG(CSYNC_LOG_PRIORITY_NOTICE, "ERR: DB already open");
return -1;
}
ctx->statedb.lastReturnValue = SQLITE_OK;
/* Openthe database */
@ -178,6 +183,8 @@ int csync_statedb_load(CSYNC *ctx, const char *statedb, sqlite3 **pdb) {
#endif
*pdb = db;
CSYNC_LOG(CSYNC_LOG_PRIORITY_NOTICE, "Success");
return 0;
out:
sqlite3_close(db);
@ -191,9 +198,26 @@ int csync_statedb_close(CSYNC *ctx) {
return -1;
}
csync_statedb_finalize_statements(ctx);
/* deallocate query resources */
if( ctx->statedb.by_fileid_stmt ) {
sqlite3_finalize(ctx->statedb.by_fileid_stmt);
ctx->statedb.by_fileid_stmt = NULL;
}
if( ctx->statedb.by_hash_stmt ) {
sqlite3_finalize(ctx->statedb.by_hash_stmt);
ctx->statedb.by_hash_stmt = NULL;
}
if( ctx->statedb.by_inode_stmt) {
sqlite3_finalize(ctx->statedb.by_inode_stmt);
ctx->statedb.by_inode_stmt = NULL;
}
sqlite3_close(ctx->statedb.db);
ctx->statedb.lastReturnValue = SQLITE_OK;
int sr = sqlite3_close(ctx->statedb.db);
CSYNC_LOG(CSYNC_LOG_PRIORITY_NOTICE, "sqlite3_close=%d", sr);
ctx->statedb.db = 0;
return rc;
}
@ -302,28 +326,6 @@ csync_file_stat_t *csync_statedb_get_stat_by_hash(CSYNC *ctx,
return st;
}
void csync_statedb_finalize_statements(CSYNC *ctx) {
if( !ctx ) {
return;
}
/* deallocate query resources */
if( ctx->statedb.by_fileid_stmt ) {
sqlite3_finalize(ctx->statedb.by_fileid_stmt);
ctx->statedb.by_fileid_stmt = NULL;
}
if( ctx->statedb.by_hash_stmt ) {
sqlite3_finalize(ctx->statedb.by_hash_stmt);
ctx->statedb.by_hash_stmt = NULL;
}
if( ctx->statedb.by_inode_stmt) {
sqlite3_finalize(ctx->statedb.by_inode_stmt);
ctx->statedb.by_inode_stmt = NULL;
}
ctx->statedb.lastReturnValue = SQLITE_OK;
}
csync_file_stat_t *csync_statedb_get_stat_by_file_id(CSYNC *ctx,
const char *file_id ) {
csync_file_stat_t *st = NULL;

View file

@ -98,12 +98,6 @@ int csync_statedb_get_below_path(CSYNC *ctx, const char *path);
*/
c_strlist_t *csync_statedb_query(sqlite3 *db, const char *statement);
/**
* @brief csync_statedb_finalize_statements - Clear prepared statements
* @param ctx The csync context
*/
void csync_statedb_finalize_statements(CSYNC *ctx);
#ifdef __cplusplus
}
#endif