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;
csync_file_stat_t *cur = NULL;
CSYNC *ctx = NULL;
c_rbtree_visit_func *visitor = NULL;
csync_treewalk_visit_func *visitor = NULL;
_csync_treewalk_context *twctx = NULL;
TREE_WALK_FILE trav;
c_rbtree_t *other_tree = NULL;
c_rbnode_t *other_node = NULL;
@ -334,6 +333,8 @@ static int _csync_treewalk_visitor(void *obj, void *data) {
SAFE_FREE(renamed_path);
}
csync_file_stat_t *other = other_node ? (csync_file_stat_t*)other_node->data : NULL;
if (obj == NULL || data == NULL) {
ctx->status_code = CSYNC_STATUS_PARAM_ERROR;
return -1;
@ -351,45 +352,9 @@ static int _csync_treewalk_visitor(void *obj, void *data) {
return 0;
}
visitor = (c_rbtree_visit_func*)(twctx->user_visitor);
visitor = (csync_treewalk_visit_func*)(twctx->user_visitor);
if (visitor != NULL) {
trav.path = cur->path;
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;
}
rc = (*visitor)(cur, other, twctx->userdata);
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
*/
@ -402,7 +361,7 @@ CSYNC_STATUS OCSYNC_EXPORT csync_get_status(CSYNC *ctx);
/* Used for special modes or debugging */
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.

View file

@ -334,14 +334,14 @@ void SyncEngine::deleteStaleErrorBlacklistEntries(const SyncFileItemVector &sync
_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.
*/
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)
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;
}
if (file->directDownloadUrl) {
if (!file->directDownloadUrl.isEmpty()) {
item->_directDownloadUrl = QString::fromUtf8(file->directDownloadUrl);
}
if (file->directDownloadCookies) {
if (!file->directDownloadCookies.isEmpty()) {
item->_directDownloadCookies = QString::fromUtf8(file->directDownloadCookies);
}
if (file->remotePerm && file->remotePerm[0]) {
item->_remotePerm = QByteArray(file->remotePerm);
if (!file->remotePerm.isEmpty()) {
item->_remotePerm = file->remotePerm;
if (remote)
_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
if (!remote && file->checksumHeader) {
item->_checksumHeader = QByteArray(file->checksumHeader);
if (!remote && !file->checksumHeader.isEmpty()) {
item->_checksumHeader = file->checksumHeader;
}
// For conflicts, store the remote checksum there
if (remote && item->_instruction == CSYNC_INSTRUCTION_CONFLICT && file->checksumHeader) {
item->_checksumHeader = QByteArray(file->checksumHeader);
if (remote && item->_instruction == CSYNC_INSTRUCTION_CONFLICT && !file->checksumHeader.isEmpty()) {
item->_checksumHeader = file->checksumHeader;
}
// 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;
if (file->etag && file->etag[0]) {
if (!file->etag.isEmpty()) {
item->_etag = file->etag;
}
@ -562,7 +562,7 @@ int SyncEngine::treewalkFile(TREE_WALK_FILE *file, bool remote)
switch (file->instruction) {
case CSYNC_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;
}
// No syncing or update to be done.
@ -592,11 +592,13 @@ int SyncEngine::treewalkFile(TREE_WALK_FILE *file, bool remote)
if (remote) {
QString filePath = _localPath + item->_file;
// Even if the mtime is different on the server, we always want to keep the mtime from
// the file system in the DB, this is to avoid spurious upload on the next sync
item->_modtime = file->other.modtime;
// same for the size
item->_size = file->other.size;
if (other) {
// Even if the mtime is different on the server, we always want to keep the mtime from
// the file system in the DB, this is to avoid spurious upload on the next sync
item->_modtime = other->modtime;
// same for the size
item->_size = other->size;
}
// If the 'W' remote permission changed, update the local filesystem
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
_hasNoneFiles = true;
} 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) {
// We are going back on time
// 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;
item->log._other_etag = file->other.etag;
item->log._other_fileId = file->other.file_id;
item->log._other_instruction = file->other.instruction;
item->log._other_modtime = file->other.modtime;
item->log._other_size = file->other.size;
if (other) {
item->log._other_etag = other->etag;
item->log._other_fileId = other->file_id;
item->log._other_instruction = other->instruction;
item->log._other_modtime = other->modtime;
item->log._other_size = other->size;
}
_syncItemMap.insert(key, item);

View file

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