From 183f16c386636fcab18fdc8bc07cf1acd3155dbb Mon Sep 17 00:00:00 2001 From: Andreas Schneider <mail@cynapses.org> Date: Wed, 18 Jun 2008 13:16:45 +0200 Subject: [PATCH] Add a function to merge the trees. This is needed to be able to write a complete journal. --- src/csync.c | 26 ++++++---- src/csync_util.c | 123 +++++++++++++++++++++++++++++++++++++++++++++++ src/csync_util.h | 2 + 3 files changed, 141 insertions(+), 10 deletions(-) diff --git a/src/csync.c b/src/csync.c index 715def171..c5947ccd1 100644 --- a/src/csync.c +++ b/src/csync.c @@ -460,17 +460,23 @@ int csync_destroy(CSYNC *ctx) { if (ctx->journal.db != NULL) { /* and we have successfully synchronized */ if (ctx->status >= CSYNC_STATUS_DONE) { - clock_gettime(CLOCK_REALTIME, &start); - /* write the journal to disk */ - if (csync_journal_write(ctx) == 0) { - jwritten = 1; - clock_gettime(CLOCK_REALTIME, &finish); - CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, - "Writing the journal to disk took %.2f seconds", - c_secdiff(finish, start)); - } else { - CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "Unable to write journal: %s", + /* merge trees */ + if (csync_merge_file_trees(ctx) < 0) { + CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "Unable to merge trees: %s", strerror(errno)); + } else { + clock_gettime(CLOCK_REALTIME, &start); + /* write the journal to disk */ + if (csync_journal_write(ctx) == 0) { + jwritten = 1; + clock_gettime(CLOCK_REALTIME, &finish); + CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, + "Writing the journal of %llu files to disk took %.2f seconds", + c_rbtree_size(ctx->local.tree), c_secdiff(finish, start)); + } else { + CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "Unable to write journal: %s", + strerror(errno)); + } } } csync_journal_close(ctx, ctx->journal.file, jwritten); diff --git a/src/csync_util.c b/src/csync_util.c index 841c0bc17..ee71252f6 100644 --- a/src/csync_util.c +++ b/src/csync_util.c @@ -20,7 +20,14 @@ * vim: ts=2 sw=2 et cindent */ +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include <stdio.h> + #include "csync_util.h" +#include "vio/csync_vio.h" #define CSYNC_LOG_CATEGORY_NAME "csync.util" #include "csync_log.h" @@ -91,3 +98,119 @@ void csync_memstat_check(void) { m.size * 4, m.resident * 4, m.shared * 4); } +static int _merge_file_trees_visitor(void *obj, void *data) { + csync_file_stat_t *fs = NULL; + csync_vio_file_stat_t *vst = NULL; + + CSYNC *ctx = NULL; + c_rbnode_t *node = NULL; + + char *uri = NULL; + int rc = -1; + + fs = (csync_file_stat_t *) obj; + ctx = (CSYNC *) data; + + /* search for UPDATED file */ + if (fs->instruction != CSYNC_INSTRUCTION_UPDATED) { + rc = 0; + goto out; + } + + /* check if the file is new or has been synced */ + node = c_rbtree_find(ctx->local.tree, (void *) fs->phash); + if (node == NULL) { + csync_file_stat_t *new = NULL; + + new = c_malloc(sizeof(csync_file_stat_t) + fs->pathlen + 1); + if (new == NULL) { + rc = -1; + goto out; + } + new = memcpy(new, fs, sizeof(csync_file_stat_t) + fs->pathlen + 1); + + if (c_rbtree_insert(ctx->local.tree, new) < 0) { + SAFE_FREE(new); + rc = -1; + goto out; + } + + node = c_rbtree_find(ctx->local.tree, (void *) fs->phash); + if (node == NULL) { + rc = -1; + goto out; + } + } + fs = c_rbtree_node_data(node); + + switch (ctx->current) { + case LOCAL_REPLICA: + if (asprintf(&uri, "%s/%s", ctx->local.uri, fs->path) < 0) { + rc =-1; + goto out; + } + break; + case REMOTE_REPLCIA: + if (asprintf(&uri, "%s/%s", ctx->remote.uri, fs->path) < 0) { + rc = -1; + goto out; + } + break; + default: + break; + } + + /* get file stat of the file on local replica */ + vst = csync_vio_file_stat_new(); + if (csync_vio_stat(ctx, uri, vst) < 0) { + rc = -1; + goto out; + } + + /* update file stat */ + fs->inode = vst->inode; + fs->modtime = vst->mtime; + + CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "file: %s, instruction: UPDATED", uri); + + rc = 0; +out: + csync_vio_file_stat_destroy(vst); + SAFE_FREE(uri); + + return rc; +} + +/* + * merge the local tree with the new files from remote and update the + * inode numbers + */ +int csync_merge_file_trees(CSYNC *ctx) { + int rc = -1; + + /* walk over remote tree, stat on local system */ + ctx->current = LOCAL_REPLICA; + ctx->replica = ctx->local.type; + + rc = c_rbtree_walk(ctx->remote.tree, ctx, _merge_file_trees_visitor); + if (rc < 0) { + goto out; + } + +#if 0 + /* We don't have to merge the remote tree atm. */ + + /* walk over local tree, stat on remote system */ + ctx->current = REMOTE_REPLICA; + ctx->replica = ctx->remote.type; + + rc = c_rbtree_walk(ctx->local.tree, ctx, _merge_file_trees_visitor); + if (rc < 0) { + goto out; + } +#endif + +out: + return rc; +} + diff --git a/src/csync_util.h b/src/csync_util.h index cbbd9a462..cff1ef777 100644 --- a/src/csync_util.h +++ b/src/csync_util.h @@ -29,4 +29,6 @@ const char *csync_instruction_str(enum csync_instructions_e instr); void csync_memstat_check(void); +int csync_merge_file_trees(CSYNC *ctx); + #endif /* _CSYNC_UTIL_H */