This commit is contained in:
Olivier Goffart 2014-02-12 16:44:24 +01:00
Родитель 7ae40e13ec a677f97b7f
Коммит 93f31fa9d7
5 изменённых файлов: 74 добавлений и 23 удалений

Просмотреть файл

@ -114,25 +114,28 @@ static int _csync_merge_algorithm_visitor(void *obj, void *data) {
if( tmp ) {
if( tmp->path ) {
/* Find the temporar file in the other tree. */
len = strlen( tmp->path );
h = c_jhash64((uint8_t *) tmp->path, len, 0);
node = c_rbtree_find(tree, &h);
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "PHash of temporary opposite (%s): %" PRIu64 " %s",
tmp->path , h, node ? "found": "not found" );
if (!node) {
/* the renamed file could not be found in the opposite tree. That is because it
* is not longer existing there, maybe because it was renamed or deleted.
* The journal is cleaned up later after propagation.
*/
/* First, check that the file is NOT in our tree (another file with the same name was added) */
node = c_rbtree_find(ctx->current == REMOTE_REPLICA ? ctx->remote.tree : ctx->local.tree, &h);
if (node) {
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Origin found in our tree : %s", tmp->path);
} else {
/* Find the temporar file in the other tree. */
node = c_rbtree_find(tree, &h);
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "PHash of temporary opposite (%s): %" PRIu64 " %s",
tmp->path , h, node ? "found": "not found" );
if (node) {
other = (csync_file_stat_t*)node->data;
} else {
/* the renamed file could not be found in the opposite tree. That is because it
* is not longer existing there, maybe because it was renamed or deleted.
* The journal is cleaned up later after propagation.
*/
}
}
}
if(node) {
other = (csync_file_stat_t*)node->data;
}
if(!other) {
cur->instruction = CSYNC_INSTRUCTION_NEW;
} else if (other->instruction == CSYNC_INSTRUCTION_NONE
@ -159,9 +162,7 @@ static int _csync_merge_algorithm_visitor(void *obj, void *data) {
cur->instruction = CSYNC_INSTRUCTION_NONE;
other->instruction = CSYNC_INSTRUCTION_SYNC;
}
SAFE_FREE(tmp->etag);
SAFE_FREE(tmp);
csync_file_stat_free(tmp);
}
break;

Просмотреть файл

@ -79,6 +79,7 @@ system( "echo \"super new\" >> " . localDir() . 'newdir/myfile.txt' );
#Add some files for the next test.
system( "echo \"un\" > " . localDir() . '1.txt' );
system( "echo \"deux\" > " . localDir() . '2.txt' );
system( "echo \"trois\" > " . localDir() . '3.txt' );
mkdir( localDir() . 'newdir2' );
csync();
@ -105,6 +106,17 @@ my $newdir4Id = remoteFileId( localDir(), 'newdir4' );
assert( $newdirId eq $newdir3Id, "newdir was not MOVE'd to newdir3?" );
assert( $newdir2Id eq $newdir4Id, "newdir2 was not MOVE'd to newdir4?" );
printInfo("Move a file and replace it by a new one");
move( localDir() . '1.txt', localDir() . '1_bis.txt' );
move( localDir() . '3.txt', localDir() . '3_bis.txt' );
system( "echo \"new file un\" > " . localDir() . '1.txt' );
system( "echo \"new file trois\" > " . localDir() . '3.txt' );
csync();
assertLocalAndRemoteDir( '', 0);
cleanup();

Просмотреть файл

@ -100,18 +100,36 @@ void PropagateItemJob::done(SyncFileItem::Status status, const QString &errorStr
}
/**
* For delete or remove, check that we are not removing from a shared directory.
* If we are, try to restore the file
*
* Return true if the problem is handled.
*/
bool PropagateItemJob::checkForProblemsWithShared()
{
QString errorString = QString::fromUtf8(ne_get_error(_propagator->_session));
int httpStatusCode = errorString.mid(0, errorString.indexOf(QChar(' '))).toInt();
if( httpStatusCode == 403 && _propagator->isInSharedDirectory(_item._file )) {
// the file was removed locally from a read only Shared sync
// the file is gone locally and it should be recovered.
SyncFileItem downloadItem(_item);
downloadItem._instruction = CSYNC_INSTRUCTION_SYNC;
downloadItem._dir = SyncFileItem::Down;
_restoreJob.reset(new PropagateDownloadFile(_propagator, downloadItem));
if( _item._type != SyncFileItem::Directory ) {
// the file was removed locally from a read only Shared sync
// the file is gone locally and it should be recovered.
SyncFileItem downloadItem(_item);
downloadItem._instruction = CSYNC_INSTRUCTION_SYNC;
downloadItem._dir = SyncFileItem::Down;
_restoreJob.reset(new PropagateDownloadFile(_propagator, downloadItem));
} else {
// Directories are harder to recover.
// But just re-create the directory, next sync will be able to recover the files
SyncFileItem mkdirItem(_item);
mkdirItem._instruction = CSYNC_INSTRUCTION_SYNC;
mkdirItem._dir = SyncFileItem::Down;
_restoreJob.reset(new PropagateLocalMkdir(_propagator, mkdirItem));
// Also remove the inodes and fileid from the db so no further renames are tried for
// this item.
_propagator->_journal->avoidRenamesOnNextSync(_item._file);
}
connect(_restoreJob.data(), SIGNAL(completed(SyncFileItem)),
this, SLOT(slotRestoreJobCompleted(SyncFileItem)));
_restoreJob->start();

Просмотреть файл

@ -776,6 +776,25 @@ void SyncJournalDb::updateBlacklistEntry( const SyncJournalBlacklistRecord& item
}
void SyncJournalDb::avoidRenamesOnNextSync(const QString& path)
{
QMutexLocker locker(&_mutex);
if( !checkConnect() ) {
return;
}
QSqlQuery query(_db);
query.prepare("UPDATE metadata SET fileid = '', inode = '0' WHERE path LIKE(?||'/%')");
query.bindValue(0, path);
if( !query.exec() ) {
qDebug() << "SQL error in avoidRenamesOnNextSync: "<< query.lastError().text();
} else {
qDebug() << query.executedQuery() << path;
}
}
void SyncJournalDb::commit(const QString& context, bool startTrans)
{
QMutexLocker lock(&_mutex);

Просмотреть файл

@ -64,6 +64,7 @@ public:
UploadInfo getUploadInfo(const QString &file);
void setUploadInfo(const QString &file, const UploadInfo &i);
SyncJournalBlacklistRecord blacklistEntry( const QString& );
void avoidRenamesOnNextSync(const QString &path);
bool postSyncCleanup( const QHash<QString, QString>& items );