mirror of
https://github.com/nextcloud/desktop.git
synced 2024-11-29 20:28:57 +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;
|
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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue