Replace TREE_WALK_FILE with csync_file_stat_t

Just expose csync_file_stat_t since we don't need an abstraction layer
anymore. Also pass the nodes of both trees directly to the visitor
function.

Issue #1817
This commit is contained in:
Jocelyn Turcotte 2017-08-17 14:39:23 +02:00 committed by Roeland Jago Douma
parent 7fad474863
commit 157e933ae5
No known key found for this signature in database
GPG key ID: F941078878347C0C
4 changed files with 40 additions and 112 deletions

View file

@ -279,9 +279,8 @@ static int _csync_treewalk_visitor(void *obj, void *data) {
int rc = 0; int rc = 0;
csync_file_stat_t *cur = NULL; csync_file_stat_t *cur = NULL;
CSYNC *ctx = NULL; CSYNC *ctx = NULL;
c_rbtree_visit_func *visitor = NULL; csync_treewalk_visit_func *visitor = NULL;
_csync_treewalk_context *twctx = NULL; _csync_treewalk_context *twctx = NULL;
TREE_WALK_FILE trav;
c_rbtree_t *other_tree = NULL; c_rbtree_t *other_tree = NULL;
c_rbnode_t *other_node = NULL; c_rbnode_t *other_node = NULL;
@ -334,6 +333,8 @@ static int _csync_treewalk_visitor(void *obj, void *data) {
SAFE_FREE(renamed_path); SAFE_FREE(renamed_path);
} }
csync_file_stat_t *other = other_node ? (csync_file_stat_t*)other_node->data : NULL;
if (obj == NULL || data == NULL) { if (obj == NULL || data == NULL) {
ctx->status_code = CSYNC_STATUS_PARAM_ERROR; ctx->status_code = CSYNC_STATUS_PARAM_ERROR;
return -1; return -1;
@ -351,45 +352,9 @@ static int _csync_treewalk_visitor(void *obj, void *data) {
return 0; return 0;
} }
visitor = (c_rbtree_visit_func*)(twctx->user_visitor); visitor = (csync_treewalk_visit_func*)(twctx->user_visitor);
if (visitor != NULL) { if (visitor != NULL) {
trav.path = cur->path; rc = (*visitor)(cur, other, twctx->userdata);
trav.size = cur->size;
trav.modtime = cur->modtime;
trav.type = cur->type;
trav.instruction = cur->instruction;
trav.rename_path = cur->rename_path;
trav.etag = cur->etag;
trav.file_id = cur->file_id;
trav.remotePerm = cur->remotePerm;
trav.directDownloadUrl = cur->directDownloadUrl.data();
trav.directDownloadCookies = cur->directDownloadCookies.data();
trav.inode = cur->inode;
trav.error_status = cur->error_status;
trav.has_ignored_files = cur->has_ignored_files;
trav.checksumHeader = cur->checksumHeader;
if( other_node ) {
csync_file_stat_t *other_stat = (csync_file_stat_t*)other_node->data;
trav.other.etag = other_stat->etag;
trav.other.file_id = other_stat->file_id;
trav.other.instruction = other_stat->instruction;
trav.other.modtime = other_stat->modtime;
trav.other.size = other_stat->size;
} else {
trav.other.etag = 0;
trav.other.file_id = 0;
trav.other.instruction = CSYNC_INSTRUCTION_NONE;
trav.other.modtime = 0;
trav.other.size = 0;
}
rc = (*visitor)(&trav, twctx->userdata);
cur->instruction = trav.instruction;
if (trav.etag != cur->etag) { // FIXME It would be nice to have this documented
cur->etag = trav.etag;
}
return rc; return rc;
} }

View file

@ -195,47 +195,6 @@ struct csync_file_stat_s {
{ } { }
}; };
/**
* CSync File Traversal structure.
*
* This structure is passed to the visitor function for every file
* which is seen.
*
*/
struct csync_tree_walk_file_s {
const char *path;
int64_t size;
int64_t inode;
time_t modtime;
mode_t mode;
enum csync_ftw_type_e type;
enum csync_instructions_e instruction;
/* For directories: Does it have children that were ignored (hidden or ignore pattern) */
int has_ignored_files;
const char *rename_path;
const char *etag;
const char *file_id;
const char *remotePerm;
char *directDownloadUrl;
char *directDownloadCookies;
const char *checksumHeader;
struct {
int64_t size;
time_t modtime;
const char *etag;
const char *file_id;
enum csync_instructions_e instruction;
} other;
CSYNC_STATUS error_status;
};
typedef struct csync_tree_walk_file_s TREE_WALK_FILE;
/** /**
* csync handle * csync handle
*/ */
@ -402,7 +361,7 @@ CSYNC_STATUS OCSYNC_EXPORT csync_get_status(CSYNC *ctx);
/* Used for special modes or debugging */ /* Used for special modes or debugging */
int OCSYNC_EXPORT csync_set_status(CSYNC *ctx, int status); int OCSYNC_EXPORT csync_set_status(CSYNC *ctx, int status);
typedef int csync_treewalk_visit_func(TREE_WALK_FILE* ,void*); typedef int csync_treewalk_visit_func(csync_file_stat_t *cur, csync_file_stat_t *other, void*);
/** /**
* @brief Walk the local file tree and call a visitor function for each file. * @brief Walk the local file tree and call a visitor function for each file.

View file

@ -334,14 +334,14 @@ void SyncEngine::deleteStaleErrorBlacklistEntries(const SyncFileItemVector &sync
_journal->deleteStaleErrorBlacklistEntries(blacklist_file_paths); _journal->deleteStaleErrorBlacklistEntries(blacklist_file_paths);
} }
int SyncEngine::treewalkLocal(TREE_WALK_FILE *file, void *data) int SyncEngine::treewalkLocal(csync_file_stat_t *file, csync_file_stat_t *other, void *data)
{ {
return static_cast<SyncEngine *>(data)->treewalkFile(file, false); return static_cast<SyncEngine *>(data)->treewalkFile(file, other, false);
} }
int SyncEngine::treewalkRemote(TREE_WALK_FILE *file, void *data) int SyncEngine::treewalkRemote(csync_file_stat_t *file, csync_file_stat_t *other, void *data)
{ {
return static_cast<SyncEngine *>(data)->treewalkFile(file, true); return static_cast<SyncEngine *>(data)->treewalkFile(file, other, true);
} }
/** /**
@ -354,7 +354,7 @@ int SyncEngine::treewalkRemote(TREE_WALK_FILE *file, void *data)
* *
* See doc/dev/sync-algorithm.md for an overview. * See doc/dev/sync-algorithm.md for an overview.
*/ */
int SyncEngine::treewalkFile(TREE_WALK_FILE *file, bool remote) int SyncEngine::treewalkFile(csync_file_stat_t *file, csync_file_stat_t *other, bool remote)
{ {
if (!file) if (!file)
return -1; return -1;
@ -407,17 +407,17 @@ int SyncEngine::treewalkFile(TREE_WALK_FILE *file, bool remote)
} }
} }
if (file->file_id && file->file_id[0]) { if (!file->file_id.isEmpty()) {
item->_fileId = file->file_id; item->_fileId = file->file_id;
} }
if (file->directDownloadUrl) { if (!file->directDownloadUrl.isEmpty()) {
item->_directDownloadUrl = QString::fromUtf8(file->directDownloadUrl); item->_directDownloadUrl = QString::fromUtf8(file->directDownloadUrl);
} }
if (file->directDownloadCookies) { if (!file->directDownloadCookies.isEmpty()) {
item->_directDownloadCookies = QString::fromUtf8(file->directDownloadCookies); item->_directDownloadCookies = QString::fromUtf8(file->directDownloadCookies);
} }
if (file->remotePerm && file->remotePerm[0]) { if (!file->remotePerm.isEmpty()) {
item->_remotePerm = QByteArray(file->remotePerm); item->_remotePerm = file->remotePerm;
if (remote) if (remote)
_remotePerms[item->_file] = item->_remotePerm; _remotePerms[item->_file] = item->_remotePerm;
} }
@ -438,12 +438,12 @@ int SyncEngine::treewalkFile(TREE_WALK_FILE *file, bool remote)
} }
// Sometimes the discovery computes checksums for local files // Sometimes the discovery computes checksums for local files
if (!remote && file->checksumHeader) { if (!remote && !file->checksumHeader.isEmpty()) {
item->_checksumHeader = QByteArray(file->checksumHeader); item->_checksumHeader = file->checksumHeader;
} }
// For conflicts, store the remote checksum there // For conflicts, store the remote checksum there
if (remote && item->_instruction == CSYNC_INSTRUCTION_CONFLICT && file->checksumHeader) { if (remote && item->_instruction == CSYNC_INSTRUCTION_CONFLICT && !file->checksumHeader.isEmpty()) {
item->_checksumHeader = QByteArray(file->checksumHeader); item->_checksumHeader = file->checksumHeader;
} }
// record the seen files to be able to clean the journal later // record the seen files to be able to clean the journal later
@ -533,7 +533,7 @@ int SyncEngine::treewalkFile(TREE_WALK_FILE *file, bool remote)
bool isDirectory = file->type == CSYNC_FTW_TYPE_DIR; bool isDirectory = file->type == CSYNC_FTW_TYPE_DIR;
if (file->etag && file->etag[0]) { if (!file->etag.isEmpty()) {
item->_etag = file->etag; item->_etag = file->etag;
} }
@ -562,7 +562,7 @@ int SyncEngine::treewalkFile(TREE_WALK_FILE *file, bool remote)
switch (file->instruction) { switch (file->instruction) {
case CSYNC_INSTRUCTION_NONE: { case CSYNC_INSTRUCTION_NONE: {
// Any files that are instruction NONE? // Any files that are instruction NONE?
if (!isDirectory && file->other.instruction == CSYNC_INSTRUCTION_NONE) { if (!isDirectory && (!other || other->instruction == CSYNC_INSTRUCTION_NONE)) {
_hasNoneFiles = true; _hasNoneFiles = true;
} }
// No syncing or update to be done. // No syncing or update to be done.
@ -592,11 +592,13 @@ int SyncEngine::treewalkFile(TREE_WALK_FILE *file, bool remote)
if (remote) { if (remote) {
QString filePath = _localPath + item->_file; QString filePath = _localPath + item->_file;
// Even if the mtime is different on the server, we always want to keep the mtime from if (other) {
// the file system in the DB, this is to avoid spurious upload on the next sync // Even if the mtime is different on the server, we always want to keep the mtime from
item->_modtime = file->other.modtime; // the file system in the DB, this is to avoid spurious upload on the next sync
// same for the size item->_modtime = other->modtime;
item->_size = file->other.size; // same for the size
item->_size = other->size;
}
// If the 'W' remote permission changed, update the local filesystem // If the 'W' remote permission changed, update the local filesystem
SyncJournalFileRecord prev = _journal->getFileRecord(item->_file); SyncJournalFileRecord prev = _journal->getFileRecord(item->_file);
@ -638,7 +640,7 @@ int SyncEngine::treewalkFile(TREE_WALK_FILE *file, bool remote)
// This counts as a NONE for detecting if all the files on the server were changed // This counts as a NONE for detecting if all the files on the server were changed
_hasNoneFiles = true; _hasNoneFiles = true;
} else if (!isDirectory) { } else if (!isDirectory) {
auto difftime = std::difftime(file->modtime, file->other.modtime); auto difftime = std::difftime(file->modtime, other ? other->modtime : 0);
if (difftime < -3600 * 2) { if (difftime < -3600 * 2) {
// We are going back on time // We are going back on time
// We only increment if the difference is more than two hours to avoid clock skew // We only increment if the difference is more than two hours to avoid clock skew
@ -672,11 +674,13 @@ int SyncEngine::treewalkFile(TREE_WALK_FILE *file, bool remote)
_needsUpdate = true; _needsUpdate = true;
item->log._other_etag = file->other.etag; if (other) {
item->log._other_fileId = file->other.file_id; item->log._other_etag = other->etag;
item->log._other_instruction = file->other.instruction; item->log._other_fileId = other->file_id;
item->log._other_modtime = file->other.modtime; item->log._other_instruction = other->instruction;
item->log._other_size = file->other.size; item->log._other_modtime = other->modtime;
item->log._other_size = other->size;
}
_syncItemMap.insert(key, item); _syncItemMap.insert(key, item);

View file

@ -170,9 +170,9 @@ private:
QString journalDbFilePath() const; QString journalDbFilePath() const;
static int treewalkLocal(TREE_WALK_FILE *, void *); static int treewalkLocal(csync_file_stat_t *file, csync_file_stat_t *other, void *);
static int treewalkRemote(TREE_WALK_FILE *, void *); static int treewalkRemote(csync_file_stat_t *file, csync_file_stat_t *other, void *);
int treewalkFile(TREE_WALK_FILE *, bool); int treewalkFile(csync_file_stat_t *file, csync_file_stat_t *other, bool);
bool checkErrorBlacklisting(SyncFileItem &item); bool checkErrorBlacklisting(SyncFileItem &item);
// Cleans up unnecessary downloadinfo entries in the journal as well // Cleans up unnecessary downloadinfo entries in the journal as well