Implement the reconciler.

This commit is contained in:
Andreas Schneider 2008-05-15 13:50:34 +02:00
parent 49543390e2
commit 4489fbfa2b
5 changed files with 221 additions and 2 deletions

View File

@ -160,10 +160,15 @@ int main(int argc, char **argv) {
printf("Version: %s\n", csync_version());
if (arguments.update) {
csync_update(csync);
if (csync_update(csync) < 0) {
goto err;
}
}
if (arguments.reconcile) {
if (csync_reconcile(csync) < 0) {
goto err;
}
}
if (arguments.propagate) {
@ -176,5 +181,10 @@ int main(int argc, char **argv) {
csync_destroy(csync);
return 0;
err:
perror("csync");
csync_destroy(csync);
return 1;
}

View File

@ -41,6 +41,7 @@ set(csync_SRCS
csync_exclude.c
csync_journal.c
csync_lock.c
csync_reconcile.c
csync_time.c
csync_util.c
csync_update.c

View File

@ -38,6 +38,7 @@
#include "csync_util.h"
#include "csync_update.h"
#include "csync_reconcile.h"
#include "vio/csync_vio.h"
@ -48,7 +49,7 @@ static int key_cmp(const void *key, const void *data) {
uint64_t a;
csync_file_stat_t *b;
a = POINTER_TO_INT(key);
a = (uint64_t) key;
b = (csync_file_stat_t *) data;
if (a < b->phash) {
@ -334,6 +335,52 @@ int csync_update(CSYNC *ctx) {
return 0;
}
int csync_reconcile(CSYNC *ctx) {
int rc = -1;
time_t start, finish;
if (ctx == NULL) {
errno = EBADF;
return -1;
}
/* Reconciliation for local replica */
time(&start);
ctx->current = LOCAL_REPLICA;
ctx->replica = ctx->local.type;
rc = csync_reconcile_updates(ctx);
time(&finish);
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG,
"Reconciliation for local replica took %.2f seconds",
difftime(finish, start));
if (rc < 0) {
return -1;
}
/* Reconciliation for local replica */
time(&start);
ctx->current = REMOTE_REPLCIA;
ctx->replica = ctx->remote.type;
rc = csync_reconcile_updates(ctx);
time(&finish);
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG,
"Reconciliation for local replica took %.2f seconds",
difftime(finish, start));
if (rc < 0) {
return -1;
}
ctx->status |= CSYNC_RECONCILE;
return 0;
}
static void tree_destructor(void *data) {
csync_file_stat_t *freedata = NULL;

133
src/csync_reconcile.c Normal file
View File

@ -0,0 +1,133 @@
/*
* libcsync -- a library to sync a directory with another
*
* Copyright (c) 2008 by Andreas Schneider <mail@cynapses.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* vim: ts=2 sw=2 et cindent
*/
#include "csync_private.h"
#include "csync_reconcile.h"
#include "csync_util.h"
#define CSYNC_LOG_CATEGORY_NAME "csync.reconciler"
#include "csync_log.h"
static int csync_merge_algorithm_visitor(void *obj, void *data) {
csync_file_stat_t *cur = NULL;
csync_file_stat_t *other = NULL;
CSYNC *ctx = NULL;
c_rbtree_t *tree = NULL;
c_rbnode_t *node = NULL;
cur = (csync_file_stat_t *) obj;
ctx = (CSYNC *) data;
/* we need the opposite tree! */
switch (ctx->current) {
case LOCAL_REPLICA:
tree = ctx->remote.tree;
break;
case REMOTE_REPLCIA:
tree = ctx->local.tree;
break;
default:
break;
}
node = c_rbtree_find(tree, (void *) cur->phash);
/* file only found on current replica */
if (node == NULL) {
switch(cur->instruction) {
/* file has been modified */
case CSYNC_INSTRUCTION_EVAL:
cur->instruction = CSYNC_INSTRUCTION_NEW;
break;
/* file has been removed on the opposite replica */
case CSYNC_INSTRUCTION_NONE:
cur->instruction = CSYNC_INSTRUCTION_REMOVE;
break;
case CSYNC_INSTRUCTION_RENAME:
cur->instruction = CSYNC_INSTRUCTION_NEW;
break;
default:
break;
}
} else {
/*
* file found on the other replica
*/
other = (csync_file_stat_t *) node->data;
switch (cur->instruction) {
/* file on current replica is new */
case CSYNC_INSTRUCTION_NEW:
/* file on current replica has been modified */
case CSYNC_INSTRUCTION_EVAL:
switch (other->instruction) {
/* file on other replica is new too */
case CSYNC_INSTRUCTION_NEW:
if (cur->modtime > other->modtime) {
cur->instruction = CSYNC_INSTRUCTION_SYNC;
}
cur->instruction = CSYNC_INSTRUCTION_NONE;
break;
/* file on other replica has changed too */
case CSYNC_INSTRUCTION_EVAL:
/* file on current replica is newer */
if (cur->modtime > other->modtime) {
cur->instruction = CSYNC_INSTRUCTION_SYNC;
}
/* file on opposite replica is newer */
cur->instruction = CSYNC_INSTRUCTION_REMOVE;
break;
/* file on the other replica has not been modified */
case CSYNC_INSTRUCTION_NONE:
cur->instruction = CSYNC_INSTRUCTION_SYNC;
break;
default:
break;
}
default:
break;
}
}
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "file: %s, instruction: %s", cur->path, csync_instruction_str(cur->instruction));
return 0;
}
int csync_reconcile_updates(CSYNC *ctx) {
int rc = -1;
c_rbtree_t *tree = NULL;
switch (ctx->current) {
case LOCAL_REPLICA:
tree = ctx->local.tree;
break;
case REMOTE_REPLCIA:
tree = ctx->remote.tree;
break;
default:
break;
}
rc = c_rbtree_walk(tree, (void *) ctx, csync_merge_algorithm_visitor);
return 0;
}

28
src/csync_reconcile.h Normal file
View File

@ -0,0 +1,28 @@
/*
* libcsync -- a library to sync a directory with another
*
* Copyright (c) 2008 by Andreas Schneider <mail@cynapses.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* vim: ft=c.doxygen ts=2 sw=2 et cindent
*/
#ifndef _CSYNC_RECONCILE_H
#define _CSYNC_RECONCILE_H
int csync_reconcile_updates(CSYNC *ctx);
#endif /* _CSYNC_RECONCILE_H */