mirror of
https://github.com/nextcloud/desktop.git
synced 2024-11-26 06:55:59 +03:00
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:
parent
7fad474863
commit
157e933ae5
4 changed files with 40 additions and 112 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
||||
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 = file->other.modtime;
|
||||
item->_modtime = other->modtime;
|
||||
// same for the size
|
||||
item->_size = file->other.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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue