diff --git a/src/csync.c b/src/csync.c index 85e623901..71b3fdeeb 100644 --- a/src/csync.c +++ b/src/csync.c @@ -235,7 +235,6 @@ int csync_init(CSYNC *ctx) { errbuf); } - /* create/load statedb */ if (! csync_is_statedb_disabled(ctx)) { rc = asprintf(&ctx->statedb.file, "%s/.csync_journal.db", @@ -691,19 +690,11 @@ static void _tree_destructor(void *data) { SAFE_FREE(freedata); } -int csync_destroy(CSYNC *ctx) { +static int _merge_and_write_statedb(CSYNC *ctx) { struct timespec start, finish; - char *lock = NULL; char errbuf[256] = {0}; int jwritten = 0; - - if (ctx == NULL) { - errno = EBADF; - return -1; - } - ctx->error_code = CSYNC_ERR_NONE; - - csync_vio_shutdown(ctx); + int rc = 0; /* if we have a statedb */ if (ctx->statedb.db != NULL) { @@ -714,6 +705,7 @@ int csync_destroy(CSYNC *ctx) { strerror_r(errno, errbuf, sizeof(errbuf)); CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "Unable to merge trees: %s", errbuf); + rc = -1; } else { csync_gettime(&start); /* write the statedb to disk */ @@ -727,10 +719,104 @@ int csync_destroy(CSYNC *ctx) { strerror_r(errno, errbuf, sizeof(errbuf)); CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "Unable to write statedb: %s", errbuf); + rc = -1; } } } - csync_statedb_close(ctx, ctx->statedb.file, jwritten); + if (csync_statedb_close(ctx, ctx->statedb.file, jwritten) < 0) { + CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "ERR: closing of statedb failed."); + rc = -1; + } + } + return rc; +} + +int csync_commit(CSYNC *ctx) { + int rc = 0; + + ctx->error_code = CSYNC_ERR_NONE; + + if (_merge_and_write_statedb(ctx) < 0) { + CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Merge and Write database failed!"); + if (ctx->error_code == CSYNC_ERR_NONE) { + ctx->error_code = CSYNC_ERR_STATEDB_WRITE; + } + rc = 1; /* Set to soft error. */ + /* The other steps happen anyway, what else can we do? */ + } + + /* destroy the rbtrees */ + if (c_rbtree_size(ctx->local.tree) > 0) { + c_rbtree_destroy(ctx->local.tree, _tree_destructor); + } + + if (c_rbtree_size(ctx->remote.tree) > 0) { + c_rbtree_destroy(ctx->remote.tree, _tree_destructor); + } + + /* free memory */ + c_rbtree_free(ctx->local.tree); + c_list_free(ctx->local.list); + c_list_free(ctx->local.id_list); + c_rbtree_free(ctx->remote.tree); + c_list_free(ctx->remote.list); + c_list_free(ctx->remote.id_list); + + /* create/load statedb */ + if (! csync_is_statedb_disabled(ctx)) { + if(!ctx->statedb.file) { + rc = asprintf(&ctx->statedb.file, "%s/.csync_journal.db", + ctx->local.uri); + if (rc < 0) { + ctx->error_code = CSYNC_ERR_MEM; + CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Failed to assemble statedb file name."); + goto out; + } + } + CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Journal: %s", ctx->statedb.file); + + if (csync_statedb_load(ctx, ctx->statedb.file) < 0) { + ctx->error_code = CSYNC_ERR_STATEDB_LOAD; + rc = -1; + goto out; + } + } + + /* Create new trees */ + if (c_rbtree_create(&ctx->local.tree, _key_cmp, _data_cmp) < 0) { + ctx->error_code = CSYNC_ERR_TREE; + rc = -1; + goto out; + } + + if (c_rbtree_create(&ctx->remote.tree, _key_cmp, _data_cmp) < 0) { + ctx->error_code = CSYNC_ERR_TREE; + rc = -1; + goto out; + } + + ctx->status = CSYNC_STATUS_INIT; + out: + return rc; +} + +int csync_destroy(CSYNC *ctx) { + char *lock = NULL; + + if (ctx == NULL) { + errno = EBADF; + return -1; + } + ctx->error_code = CSYNC_ERR_NONE; + + csync_vio_shutdown(ctx); + + if (_merge_and_write_statedb(ctx) < 0) { + CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "destroy: Merge and Write database failed!"); + if (ctx->error_code == CSYNC_ERR_NONE) { + ctx->error_code = CSYNC_ERR_STATEDB_WRITE; + } + /* The other steps happen anyway, what else can we do? */ } /* clear exclude list */ @@ -873,7 +959,6 @@ int csync_set_auth_callback(CSYNC *ctx, csync_auth_callback cb) { ctx->error_code = CSYNC_ERR_UNSPEC; return -1; } - ctx->callbacks.auth_function = cb; return 0; diff --git a/src/csync.h b/src/csync.h index af5c60a2e..66b82e24d 100644 --- a/src/csync.h +++ b/src/csync.h @@ -73,6 +73,7 @@ enum csync_error_codes_e { CSYNC_ERR_LOG, CSYNC_ERR_LOCK, CSYNC_ERR_STATEDB_LOAD, + CSYNC_ERR_STATEDB_WRITE, CSYNC_ERR_MODULE, CSYNC_ERR_TIMESKEW, CSYNC_ERR_FILESYSTEM, @@ -226,6 +227,15 @@ int csync_reconcile(CSYNC *ctx); */ int csync_propagate(CSYNC *ctx); +/** + * @brief Commit the sync results to journal + * + * @param ctx The context to commit. + * + * @return 0 on success, less than 0 if an error occured. + */ +int csync_commit(CSYNC *ctx); + /** * @brief Destroy the csync context * diff --git a/src/csync_misc.c b/src/csync_misc.c index 7d02af645..0deac979d 100644 --- a/src/csync_misc.c +++ b/src/csync_misc.c @@ -162,6 +162,7 @@ CSYNC_ERROR_CODE csync_errno_to_csync_error(CSYNC_ERROR_CODE default_err) CSYNC_ERR_LOG, CSYNC_ERR_LOCK, CSYNC_ERR_STATEDB_LOAD, + CSYNC_ERR_STATEDB_WRITE, CSYNC_ERR_MODULE, CSYNC_ERR_TIMESKEW, CSYNC_ERR_FILESYSTEM,