Use remote rename if local rename is detected.

This commit is contained in:
Klaas Freitag 2012-08-02 16:58:54 +03:00
parent 28d28ecac6
commit 253605758e
3 changed files with 98 additions and 2 deletions

View File

@ -159,6 +159,7 @@ struct csync_file_stat_s {
mode_t mode; /* u32 */
int nlink; /* u32 */
int type; /* u32 */
char *destpath; /* for renames */
enum csync_instructions_e instruction; /* u32 */
char path[1]; /* u8 */
}

View File

@ -550,6 +550,68 @@ static int _csync_new_file(CSYNC *ctx, csync_file_stat_t *st) {
return rc;
}
static int _csync_rename_file(CSYNC *ctx, csync_file_stat_t *st) {
int rc = 0;
char errbuf[256] = {0};
char *suri = NULL;
char *duri = NULL;
switch (ctx->current) {
case REMOTE_REPLCIA:
if( !(st->path && st->destpath) ) {
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "Rename failed: src or dest path empty");
rc = -1;
}
if (asprintf(&suri, "%s/%s", ctx->remote.uri, st->path) < 0) {
rc = -1;
}
if (asprintf(&duri, "%s/%s", ctx->remote.uri, st->destpath) < 0) {
rc = -1;
}
break;
case LOCAL_REPLICA:
/* No renaming supported by updater */
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "RENAME is only supported on local filesystem.");
rc = -1;
break;
default:
break;
}
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Renaming %s => %s", suri, duri);
if (rc > -1 && csync_vio_rename(ctx, suri, duri) < 0) {
switch (errno) {
default:
strerror_r(errno, errbuf, sizeof(errbuf));
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR,
"dir: %s, command: rename, error: %s",
suri,
errbuf);
rc = -1;
break;
}
goto out;
}
/* set instruction for the statedb merger */
if( rc > -1 ) {
st->instruction = CSYNC_INSTRUCTION_RENAME;
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "RENAME file: %s", suri);
}
out:
SAFE_FREE(suri);
SAFE_FREE(duri);
SAFE_FREE(st->destpath);
/* set instruction for the statedb merger */
if (rc != 0) {
st->instruction = CSYNC_INSTRUCTION_NONE;
}
return rc;
}
static int _csync_sync_file(CSYNC *ctx, csync_file_stat_t *st) {
int rc = -1;
@ -947,7 +1009,13 @@ static int _csync_propagation_file_visitor(void *obj, void *data) {
goto err;
}
break;
case CSYNC_INSTRUCTION_SYNC:
case CSYNC_INSTRUCTION_RENAME:
if (_csync_rename_file(ctx, st) < 0) {
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE,"FAIL RENAME: %s",st->path);
goto err;
}
break;
case CSYNC_INSTRUCTION_SYNC:
if (_csync_sync_file(ctx, st) < 0) {
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE,"FAIL SYNC: %s",st->path);
goto err;

View File

@ -23,6 +23,8 @@
#include "csync_private.h"
#include "csync_reconcile.h"
#include "csync_util.h"
#include "csync_statedb.h"
#include "c_jhash.h"
#define CSYNC_LOG_CATEGORY_NAME "csync.reconciler"
#include "csync_log.h"
@ -43,6 +45,10 @@
static int _csync_merge_algorithm_visitor(void *obj, void *data) {
csync_file_stat_t *cur = NULL;
csync_file_stat_t *other = NULL;
csync_file_stat_t *tmp = NULL;
uint64_t h = 0;
int len = 0;
CSYNC *ctx = NULL;
c_rbtree_t *tree = NULL;
c_rbnode_t *node = NULL;
@ -75,7 +81,28 @@ static int _csync_merge_algorithm_visitor(void *obj, void *data) {
cur->instruction = CSYNC_INSTRUCTION_REMOVE;
break;
case CSYNC_INSTRUCTION_RENAME:
cur->instruction = CSYNC_INSTRUCTION_NEW;
/* use the old name to find the "other" node */
tmp = csync_statedb_get_stat_by_inode(ctx, cur->inode);
/* Find the opposite node. */
if( tmp ) {
/* We need to calculate the phash again because of the phash being stored as int in db. */
if( tmp->path ) {
len = strlen( tmp->path );
h = c_jhash64((uint8_t *) tmp->path, len, 0);
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE,"PHash of temporar opposite: %llu", h);
node = c_rbtree_find(tree, &h);
}
if(node) {
other = (csync_file_stat_t*)node->data;
other->instruction = CSYNC_INSTRUCTION_RENAME;
other->destpath = c_strdup( cur->path );
cur->instruction = CSYNC_INSTRUCTION_NONE;
}
if( ! other ) {
cur->instruction = CSYNC_INSTRUCTION_NEW;
}
}
break;
default:
break;