From d66c2b5faecc689c52df23d7dbc44c894b92febc Mon Sep 17 00:00:00 2001 From: Jocelyn Turcotte Date: Wed, 23 Aug 2017 19:16:12 +0200 Subject: [PATCH] Replace the custom rbtree by a std::map --- src/csync/csync.cpp | 183 +---- src/csync/csync_private.h | 28 +- src/csync/csync_reconcile.cpp | 110 +-- src/csync/csync_rename.cpp | 36 +- src/csync/csync_rename.h | 6 +- src/csync/csync_statedb.cpp | 9 +- src/csync/csync_update.cpp | 11 +- src/csync/std/CMakeLists.txt | 1 - src/csync/std/c_lib.h | 1 - src/csync/std/c_rbtree.c | 743 ------------------ src/csync/std/c_rbtree.h | 318 -------- src/libsync/discoveryphase.cpp | 17 +- src/libsync/discoveryphase.h | 8 +- src/libsync/syncengine.cpp | 11 +- test/csync/CMakeLists.txt | 1 - .../csync_tests/check_csync_statedb_query.cpp | 15 +- test/csync/csync_tests/check_csync_update.cpp | 10 +- test/csync/std_tests/check_std_c_rbtree.c | 366 --------- 18 files changed, 153 insertions(+), 1721 deletions(-) delete mode 100644 src/csync/std/c_rbtree.c delete mode 100644 src/csync/std/c_rbtree.h delete mode 100644 test/csync/std_tests/check_std_c_rbtree.c diff --git a/src/csync/csync.cpp b/src/csync/csync.cpp index b37e2bdcd..ac096ae2b 100644 --- a/src/csync/csync.cpp +++ b/src/csync/csync.cpp @@ -51,36 +51,6 @@ #include "csync_rename.h" #include "c_jhash.h" -static int _key_cmp(const void *key, const void *data) { - uint64_t a; - csync_file_stat_t *b; - - a = *(uint64_t *) (key); - b = (csync_file_stat_t *) data; - - if (a < b->phash) { - return -1; - } else if (a > b->phash) { - return 1; - } - - return 0; -} - -static int _data_cmp(const void *key, const void *data) { - csync_file_stat_t *a, *b; - - a = (csync_file_stat_t *) key; - b = (csync_file_stat_t *) data; - - if (a->phash < b->phash) { - return -1; - } else if (a->phash > b->phash) { - return 1; - } - - return 0; -} csync_s::csync_s(const char *localUri, const char *db_file) { size_t len = 0; @@ -91,9 +61,6 @@ csync_s::csync_s(const char *localUri, const char *db_file) { local.uri = c_strndup(localUri, len); - c_rbtree_create(&local.tree, _key_cmp, _data_cmp); - c_rbtree_create(&remote.tree, _key_cmp, _data_cmp); - statedb.file = c_strdup(db_file); } @@ -137,7 +104,7 @@ int csync_update(CSYNC *ctx) { CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Update detection for local replica took %.2f seconds walking %zu files.", - c_secdiff(finish, start), c_rbtree_size(ctx->local.tree)); + c_secdiff(finish, start), ctx->local.files.size()); csync_memstat_check(); /* update detection for remote replica */ @@ -157,7 +124,7 @@ int csync_update(CSYNC *ctx) { CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Update detection for remote replica took %.2f seconds " "walking %zu files.", - c_secdiff(finish, start), c_rbtree_size(ctx->remote.tree)); + c_secdiff(finish, start), ctx->remote.files.size()); csync_memstat_check(); ctx->status |= CSYNC_STATUS_UPDATE; @@ -195,7 +162,7 @@ int csync_reconcile(CSYNC *ctx) { CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Reconciliation for local replica took %.2f seconds visiting %zu files.", - c_secdiff(finish, start), c_rbtree_size(ctx->local.tree)); + c_secdiff(finish, start), ctx->local.files.size()); if (rc < 0) { if (!CSYNC_STATUS_IS_OK(ctx->status_code)) { @@ -215,7 +182,7 @@ int csync_reconcile(CSYNC *ctx) { CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Reconciliation for remote replica took %.2f seconds visiting %zu files.", - c_secdiff(finish, start), c_rbtree_size(ctx->remote.tree)); + c_secdiff(finish, start), ctx->remote.files.size()); if (rc < 0) { if (!CSYNC_STATUS_IS_OK(ctx->status_code)) { @@ -236,17 +203,11 @@ out: /* * local visitor which calls the user visitor with repacked stat info. */ -static int _csync_treewalk_visitor(void *obj, void *data) { +static int _csync_treewalk_visitor(csync_file_stat_t *cur, CSYNC * ctx) { int rc = 0; - csync_file_stat_t *cur = NULL; - CSYNC *ctx = NULL; csync_treewalk_visit_func *visitor = NULL; _csync_treewalk_context *twctx = NULL; - c_rbtree_t *other_tree = NULL; - c_rbnode_t *other_node = NULL; - - cur = (csync_file_stat_t *) obj; - ctx = (CSYNC *) data; + csync_s::FileMap *other_tree = nullptr; if (ctx == NULL) { return -1; @@ -255,51 +216,33 @@ static int _csync_treewalk_visitor(void *obj, void *data) { /* we need the opposite tree! */ switch (ctx->current) { case LOCAL_REPLICA: - other_tree = ctx->remote.tree; + other_tree = &ctx->remote.files; break; case REMOTE_REPLICA: - other_tree = ctx->local.tree; + other_tree = &ctx->local.files; break; default: break; } - other_node = c_rbtree_find(other_tree, &cur->phash); + csync_s::FileMap::const_iterator other_file_it = other_tree->find(cur->path); - if (!other_node) { + if (other_file_it == other_tree->cend()) { /* Check the renamed path as well. */ - int len; - uint64_t h = 0; - char *renamed_path = csync_rename_adjust_path(ctx, cur->path); - - if (!c_streq(renamed_path, cur->path)) { - len = strlen( renamed_path ); - h = c_jhash64((uint8_t *) renamed_path, len, 0); - other_node = c_rbtree_find(other_tree, &h); - } - SAFE_FREE(renamed_path); + QByteArray renamed_path = csync_rename_adjust_path(ctx, cur->path); + if (renamed_path != cur->path) + other_file_it = other_tree->find(renamed_path); } - if (!other_node) { + if (other_file_it == other_tree->cend()) { /* Check the source path as well. */ - int len; - uint64_t h = 0; - char *renamed_path = csync_rename_adjust_path_source(ctx, cur->path); - - if (!c_streq(renamed_path, cur->path)) { - len = strlen( renamed_path ); - h = c_jhash64((uint8_t *) renamed_path, len, 0); - other_node = c_rbtree_find(other_tree, &h); - } - SAFE_FREE(renamed_path); + QByteArray renamed_path = csync_rename_adjust_path_source(ctx, cur->path); + if (renamed_path != cur->path) + other_file_it = other_tree->find(renamed_path); } - csync_file_stat_t *other = other_node ? (csync_file_stat_t*)other_node->data : NULL; + csync_file_stat_t *other = (other_file_it != other_tree->cend()) ? other_file_it->second.get() : NULL; - if (obj == NULL || data == NULL) { - ctx->status_code = CSYNC_STATUS_PARAM_ERROR; - return -1; - } ctx->status_code = CSYNC_STATUS_OK; twctx = (_csync_treewalk_context*) ctx->callbacks.userdata; @@ -331,28 +274,24 @@ static int _csync_treewalk_visitor(void *obj, void *data) { * which calls the local _csync_treewalk_visitor in this module. * The user visitor is called from there. */ -static int _csync_walk_tree(CSYNC *ctx, c_rbtree_t *tree, csync_treewalk_visit_func *visitor, int filter) +static int _csync_walk_tree(CSYNC *ctx, csync_s::FileMap *tree, csync_treewalk_visit_func *visitor, int filter) { _csync_treewalk_context tw_ctx; - int rc = -1; + int rc = 0; - if (ctx == NULL) { - errno = EBADF; - return rc; - } - - if (visitor == NULL || tree == NULL) { - ctx->status_code = CSYNC_STATUS_PARAM_ERROR; - return rc; - } - tw_ctx.userdata = ctx->callbacks.userdata; tw_ctx.user_visitor = visitor; tw_ctx.instruction_filter = filter; ctx->callbacks.userdata = &tw_ctx; - rc = c_rbtree_walk(tree, (void*) ctx, _csync_treewalk_visitor); + for (auto &pair : *tree) { + if (_csync_treewalk_visitor(pair.second.get(), ctx) < 0) { + rc = -1; + break; + } + } + if( rc < 0 ) { if( ctx->status_code == CSYNC_STATUS_OK ) ctx->status_code = csync_errno_to_status(errno, CSYNC_STATUS_TREE_ERROR); @@ -367,18 +306,9 @@ static int _csync_walk_tree(CSYNC *ctx, c_rbtree_t *tree, csync_treewalk_visit_f */ int csync_walk_remote_tree(CSYNC *ctx, csync_treewalk_visit_func *visitor, int filter) { - c_rbtree_t *tree = NULL; - int rc = -1; - - if(ctx != NULL) { - ctx->status_code = CSYNC_STATUS_OK; - ctx->current = REMOTE_REPLICA; - tree = ctx->remote.tree; - } - - /* all error handling in the called function */ - rc = _csync_walk_tree(ctx, tree, visitor, filter); - return rc; + ctx->status_code = CSYNC_STATUS_OK; + ctx->current = REMOTE_REPLICA; + return _csync_walk_tree(ctx, &ctx->remote.files, visitor, filter); } /* @@ -386,25 +316,9 @@ int csync_walk_remote_tree(CSYNC *ctx, csync_treewalk_visit_func *visitor, int */ int csync_walk_local_tree(CSYNC *ctx, csync_treewalk_visit_func *visitor, int filter) { - c_rbtree_t *tree = NULL; - int rc = -1; - - if (ctx != NULL) { - ctx->status_code = CSYNC_STATUS_OK; - ctx->current = LOCAL_REPLICA; - tree = ctx->local.tree; - } - - /* all error handling in the called function */ - rc = _csync_walk_tree(ctx, tree, visitor, filter); - return rc; -} - -static void _tree_destructor(void *data) { - csync_file_stat_t *freedata = NULL; - - freedata = (csync_file_stat_t *) data; - delete freedata; + ctx->status_code = CSYNC_STATUS_OK; + ctx->current = LOCAL_REPLICA; + return _csync_walk_tree(ctx, &ctx->local.files, visitor, filter); } int csync_s::reinitialize() { @@ -419,26 +333,12 @@ int csync_s::reinitialize() { } statedb.db = NULL; - /* destroy the rbtrees */ - if (c_rbtree_size(local.tree) > 0) { - c_rbtree_destroy(local.tree, _tree_destructor); - } - - if (c_rbtree_size(remote.tree) > 0) { - c_rbtree_destroy(remote.tree, _tree_destructor); - } - - /* free memory */ - c_rbtree_free(local.tree); - c_rbtree_free(remote.tree); - remote.read_from_db = 0; read_remote_from_db = true; db_is_empty = false; - /* Create new trees */ - c_rbtree_create(&local.tree, _key_cmp, _data_cmp); - c_rbtree_create(&remote.tree, _key_cmp, _data_cmp); + local.files.clear(); + remote.files.clear(); status = CSYNC_STATUS_INIT; SAFE_FREE(error_string); @@ -454,19 +354,6 @@ csync_s::~csync_s() { } statedb.db = NULL; - /* destroy the rbtrees */ - if (c_rbtree_size(local.tree) > 0) { - c_rbtree_destroy(local.tree, _tree_destructor); - } - - if (c_rbtree_size(remote.tree) > 0) { - c_rbtree_destroy(remote.tree, _tree_destructor); - } - - /* free memory */ - c_rbtree_free(local.tree); - c_rbtree_free(remote.tree); - SAFE_FREE(statedb.file); SAFE_FREE(local.uri); SAFE_FREE(error_string); diff --git a/src/csync/csync_private.h b/src/csync/csync_private.h index 605e1b252..53383db89 100644 --- a/src/csync/csync_private.h +++ b/src/csync/csync_private.h @@ -36,6 +36,7 @@ #include #include #include +#include #include "config_csync.h" #include "std/c_lib.h" @@ -69,6 +70,14 @@ enum csync_replica_e { * @brief csync public structure */ struct OCSYNC_EXPORT csync_s { + class FileMap : public std::map> { + public: + csync_file_stat_t *findFile(const QByteArray &key) const { + auto it = find(key); + return it != end() ? it->second.get() : nullptr; + } + }; + struct { csync_auth_callback auth_function = nullptr; void *userdata = nullptr; @@ -76,8 +85,8 @@ struct OCSYNC_EXPORT csync_s { void *update_callback_userdata = nullptr; /* hooks for checking the white list (uses the update_callback_userdata) */ - int (*checkSelectiveSyncBlackListHook)(void*, const char*) = nullptr; - int (*checkSelectiveSyncNewFolderHook)(void*, const char* /* path */, const char* /* remotePerm */) = nullptr; + int (*checkSelectiveSyncBlackListHook)(void*, const QByteArray &) = nullptr; + int (*checkSelectiveSyncNewFolderHook)(void*, const QByteArray &/* path */, const QByteArray &/* remotePerm */) = nullptr; csync_vio_opendir_hook remote_opendir_hook = nullptr; @@ -105,17 +114,17 @@ struct OCSYNC_EXPORT csync_s { } statedb; struct { - std::map folder_renamed_to; // map from->to - std::map folder_renamed_from; // map to->from + std::map folder_renamed_to; // map from->to + std::map folder_renamed_from; // map to->from } renames; struct { char *uri = nullptr; - c_rbtree_t *tree = nullptr; + FileMap files; } local; struct { - c_rbtree_t *tree = nullptr; + FileMap files; bool read_from_db = false; QByteArray root_perms; /* Permission of the root folder. (Since the root folder is not in the db tree, we need to keep a separate entry.) */ } remote; @@ -151,6 +160,13 @@ struct OCSYNC_EXPORT csync_s { csync_s(const char *localUri, const char *db_file); ~csync_s(); int reinitialize(); + + // For some reason MSVC references the copy constructor and/or the assignment operator + // if a class is exported. This is a problem since unique_ptr isn't copyable. + // Explicitly disable them to fix the issue. + // https://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/e39ab33d-1aaf-4125-b6de-50410d9ced1d + csync_s(const csync_s &) = delete; + csync_s &operator=(const csync_s &) = delete; }; /* diff --git a/src/csync/csync_reconcile.cpp b/src/csync/csync_reconcile.cpp index 760c5ca46..ee7eee7a1 100644 --- a/src/csync/csync_reconcile.cpp +++ b/src/csync/csync_reconcile.cpp @@ -37,33 +37,28 @@ /* Check if a file is ignored because one parent is ignored. * return the node of the ignored directoy if it's the case, or NULL if it is not ignored */ -static c_rbnode_t *_csync_check_ignored(c_rbtree_t *tree, const char *path, int pathlen) { - uint64_t h = 0; - c_rbnode_t *node = NULL; - +static csync_file_stat_t *_csync_check_ignored(csync_s::FileMap *tree, const QByteArray &path) { /* compute the size of the parent directory */ - int parentlen = pathlen - 1; - while (parentlen > 0 && path[parentlen] != '/') { + int parentlen = path.size() - 1; + while (parentlen > 0 && path.at(parentlen) != '/') { parentlen--; } if (parentlen <= 0) { - return NULL; + return nullptr; } - - h = c_jhash64((uint8_t *) path, parentlen, 0); - node = c_rbtree_find(tree, &h); - if (node) { - csync_file_stat_t *n = (csync_file_stat_t*)node->data; - if (n->instruction == CSYNC_INSTRUCTION_IGNORE) { + QByteArray parentPath = path.left(parentlen); + csync_file_stat_t *fs = tree->findFile(parentPath); + if (fs) { + if (fs->instruction == CSYNC_INSTRUCTION_IGNORE) { /* Yes, we are ignored */ - return node; + return fs; } else { /* Not ignored */ - return NULL; + return nullptr; } } else { /* Try if the parent itself is ignored */ - return _csync_check_ignored(tree, path, parentlen); + return _csync_check_ignored(tree, parentPath); } } @@ -83,7 +78,7 @@ static bool _csync_is_collision_safe_hash(const char *checksum_header) /** * The main function in the reconcile pass. * - * It's called for each entry in the local and remote rbtrees by + * It's called for each entry in the local and remote files by * csync_reconcile() * * Before the reconcile phase the trees already know about changes @@ -107,52 +102,37 @@ static bool _csync_is_collision_safe_hash(const char *checksum_header) * (timestamp is newer), it is not overwritten. If both files, on the * source and the destination, have been changed, the newer file wins. */ -static int _csync_merge_algorithm_visitor(void *obj, void *data) { - csync_file_stat_t *cur = NULL; - csync_file_stat_t *other = NULL; +static int _csync_merge_algorithm_visitor(csync_file_stat_t *cur, CSYNC * ctx) { std::unique_ptr tmp; - uint64_t h = 0; - int len = 0; - CSYNC *ctx = NULL; - c_rbtree_t *tree = NULL; - c_rbnode_t *node = NULL; - - cur = (csync_file_stat_t *) obj; - ctx = (CSYNC *) data; + csync_s::FileMap *other_tree = nullptr; /* we need the opposite tree! */ switch (ctx->current) { case LOCAL_REPLICA: - tree = ctx->remote.tree; + other_tree = &ctx->remote.files; break; case REMOTE_REPLICA: - tree = ctx->local.tree; + other_tree = &ctx->local.files; break; default: break; } - node = c_rbtree_find(tree, &cur->phash); + csync_file_stat_t *other = other_tree->findFile(cur->path);; - if (!node) { + if (!other) { /* Check the renamed path as well. */ - char *renamed_path = csync_rename_adjust_path(ctx, cur->path); - if (renamed_path != cur->path) { - len = strlen( renamed_path ); - h = c_jhash64((uint8_t *) renamed_path, len, 0); - node = c_rbtree_find(tree, &h); - } - SAFE_FREE(renamed_path); + other = other_tree->findFile(csync_rename_adjust_path(ctx, cur->path)); } - if (!node) { + if (!other) { /* Check if it is ignored */ - node = _csync_check_ignored(tree, cur->path, cur->path.size()); + other = _csync_check_ignored(other_tree, cur->path); /* If it is ignored, other->instruction will be IGNORE so this one will also be ignored */ } /* file only found on current replica */ - if (node == NULL) { + if (!other) { switch(cur->instruction) { /* file has been modified */ case CSYNC_INSTRUCTION_EVAL: @@ -187,26 +167,20 @@ static int _csync_merge_algorithm_visitor(void *obj, void *data) { } if( tmp ) { - len = strlen( tmp->path ); - if( len > 0 ) { - h = c_jhash64((uint8_t *) tmp->path.constData(), len, 0); + if( !tmp->path.isEmpty() ) { /* 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_s::FileMap *our_tree = ctx->current == REMOTE_REPLICA ? &ctx->remote.files : &ctx->local.files; + if (our_tree->findFile(tmp->path)) { CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Origin found in our tree : %s", tmp->path.constData()); } 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.constData() , 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. - */ - } + /* Find the temporar file in the other tree. + * If 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. + */ + other = other_tree->findFile(tmp->path); + CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Temporary opposite (%s) %s", + tmp->path.constData() , other ? "found": "not found" ); } } @@ -250,7 +224,6 @@ static int _csync_merge_algorithm_visitor(void *obj, void *data) { /* * file found on the other replica */ - other = (csync_file_stat_t *) node->data; switch (cur->instruction) { case CSYNC_INSTRUCTION_UPDATE_METADATA: @@ -395,25 +368,26 @@ static int _csync_merge_algorithm_visitor(void *obj, void *data) { } int csync_reconcile_updates(CSYNC *ctx) { - int rc; - c_rbtree_t *tree = NULL; + csync_s::FileMap *tree = nullptr; switch (ctx->current) { case LOCAL_REPLICA: - tree = ctx->local.tree; + tree = &ctx->local.files; break; case REMOTE_REPLICA: - tree = ctx->remote.tree; + tree = &ctx->remote.files; break; default: break; } - rc = c_rbtree_walk(tree, (void *) ctx, _csync_merge_algorithm_visitor); - if( rc < 0 ) { - ctx->status_code = CSYNC_STATUS_RECONCILE_ERROR; + for (auto &pair : *tree) { + if (_csync_merge_algorithm_visitor(pair.second.get(), ctx) < 0) { + ctx->status_code = CSYNC_STATUS_RECONCILE_ERROR; + return -1; + } } - return rc; + return 0; } /* vim: set ts=8 sw=2 et cindent: */ diff --git a/src/csync/csync_rename.cpp b/src/csync/csync_rename.cpp index 5196020ee..ef825a606 100644 --- a/src/csync/csync_rename.cpp +++ b/src/csync/csync_rename.cpp @@ -21,45 +21,43 @@ #include "csync_private.h" #include "csync_rename.h" -#include -#include #include -static std::string _parentDir(const std::string &path) { +static QByteArray _parentDir(const QByteArray &path) { int len = path.length(); - while(len > 0 && path[len-1]!='/') len--; - while(len > 0 && path[len-1]=='/') len--; - return path.substr(0, len); + while(len > 0 && path.at(len-1)!='/') len--; + while(len > 0 && path.at(len-1)=='/') len--; + return path.left(len); } -void csync_rename_record(CSYNC* ctx, const char* from, const char* to) +void csync_rename_record(CSYNC* ctx, const QByteArray &from, const QByteArray &to) { ctx->renames.folder_renamed_to[from] = to; ctx->renames.folder_renamed_from[to] = from; } -char* csync_rename_adjust_path(CSYNC* ctx, const char* path) +QByteArray csync_rename_adjust_path(CSYNC* ctx, const QByteArray &path) { - for (std::string p = _parentDir(path); !p.empty(); p = _parentDir(p)) { - std::map< std::string, std::string >::iterator it = ctx->renames.folder_renamed_to.find(p); + for (QByteArray p = _parentDir(path); !p.isEmpty(); p = _parentDir(p)) { + std::map< QByteArray, QByteArray >::iterator it = ctx->renames.folder_renamed_to.find(p); if (it != ctx->renames.folder_renamed_to.end()) { - std::string rep = it->second + (path + p.length()); - return c_strdup(rep.c_str()); + QByteArray rep = it->second + path.mid(p.length()); + return rep; } } - return c_strdup(path); + return path; } -char* csync_rename_adjust_path_source(CSYNC* ctx, const char* path) +QByteArray csync_rename_adjust_path_source(CSYNC* ctx, const QByteArray &path) { - for (std::string p = _parentDir(path); !p.empty(); p = _parentDir(p)) { - std::map< std::string, std::string >::iterator it = ctx->renames.folder_renamed_from.find(p); + for (QByteArray p = _parentDir(path); !p.isEmpty(); p = _parentDir(p)) { + std::map< QByteArray, QByteArray >::iterator it = ctx->renames.folder_renamed_from.find(p); if (it != ctx->renames.folder_renamed_from.end()) { - std::string rep = it->second + (path + p.length()); - return c_strdup(rep.c_str()); + QByteArray rep = it->second + path.mid(p.length()); + return rep; } } - return c_strdup(path); + return path; } bool csync_rename_count(CSYNC *ctx) { diff --git a/src/csync/csync_rename.h b/src/csync/csync_rename.h index 509b78afc..194f4256c 100644 --- a/src/csync/csync_rename.h +++ b/src/csync/csync_rename.h @@ -23,9 +23,9 @@ #include "csync.h" /* Return the final destination path of a given patch in case of renames */ -char OCSYNC_EXPORT *csync_rename_adjust_path(CSYNC *ctx, const char *path); +QByteArray OCSYNC_EXPORT csync_rename_adjust_path(CSYNC *ctx, const QByteArray &path); /* Return the source of a given path in case of renames */ -char OCSYNC_EXPORT *csync_rename_adjust_path_source(CSYNC *ctx, const char *path); -void OCSYNC_EXPORT csync_rename_record(CSYNC *ctx, const char *from, const char *to); +QByteArray OCSYNC_EXPORT csync_rename_adjust_path_source(CSYNC *ctx, const QByteArray &path); +void OCSYNC_EXPORT csync_rename_record(CSYNC *ctx, const QByteArray &from, const QByteArray &to); /* Return the amount of renamed item recorded */ bool OCSYNC_EXPORT csync_rename_count(CSYNC *ctx); diff --git a/src/csync/csync_statedb.cpp b/src/csync/csync_statedb.cpp index 4d2598f79..ca5b61537 100644 --- a/src/csync/csync_statedb.cpp +++ b/src/csync/csync_statedb.cpp @@ -486,18 +486,15 @@ int csync_statedb_get_below_path( CSYNC *ctx, const char *path ) { } /* store into result list. */ - if (c_rbtree_insert(ctx->remote.tree, (void *) st.release()) < 0) { - st.reset(); - ctx->status_code = CSYNC_STATUS_TREE_ERROR; - break; - } + QByteArray path = st->path; + ctx->remote.files[path] = std::move(st); cnt++; } } while( rc == SQLITE_ROW ); ctx->statedb.lastReturnValue = rc; if( rc != SQLITE_DONE ) { - ctx->status_code = CSYNC_STATUS_TREE_ERROR; + ctx->status_code = CSYNC_STATUS_STATEDB_LOAD_ERROR; } else { CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "%" PRId64 " entries read below path %s from db.", cnt, path); } diff --git a/src/csync/csync_update.cpp b/src/csync/csync_update.cpp index 91afc8eb6..f63757242 100644 --- a/src/csync/csync_update.cpp +++ b/src/csync/csync_update.cpp @@ -383,18 +383,13 @@ out: CSYNC_LOG(CSYNC_LOG_PRIORITY_INFO, "file: %s, instruction: %s <<=", fs->path.constData(), csync_instruction_str(fs->instruction)); + QByteArray path = fs->path; switch (ctx->current) { case LOCAL_REPLICA: - if (c_rbtree_insert(ctx->local.tree, (void *) fs.release()) < 0) { - ctx->status_code = CSYNC_STATUS_TREE_ERROR; - return -1; - } + ctx->local.files[path] = std::move(fs); break; case REMOTE_REPLICA: - if (c_rbtree_insert(ctx->remote.tree, (void *) fs.release()) < 0) { - ctx->status_code = CSYNC_STATUS_TREE_ERROR; - return -1; - } + ctx->remote.files[path] = std::move(fs); break; default: break; diff --git a/src/csync/std/CMakeLists.txt b/src/csync/std/CMakeLists.txt index ef7a25bd3..fddd02e99 100644 --- a/src/csync/std/CMakeLists.txt +++ b/src/csync/std/CMakeLists.txt @@ -17,7 +17,6 @@ set(CSTDLIB_LINK_LIBRARIES set(cstdlib_SRCS c_alloc.c c_path.c - c_rbtree.c c_string.c c_time.c c_utf8.cpp diff --git a/src/csync/std/c_lib.h b/src/csync/std/c_lib.h index b9c1ea8d3..43f352ff4 100644 --- a/src/csync/std/c_lib.h +++ b/src/csync/std/c_lib.h @@ -24,7 +24,6 @@ #include "c_macro.h" #include "c_alloc.h" #include "c_path.h" -#include "c_rbtree.h" #include "c_string.h" #include "c_time.h" #include "c_private.h" diff --git a/src/csync/std/c_rbtree.c b/src/csync/std/c_rbtree.c deleted file mode 100644 index 9a38fd0a6..000000000 --- a/src/csync/std/c_rbtree.c +++ /dev/null @@ -1,743 +0,0 @@ -/* - * cynapses libc functions - * - * Copyright (c) 2003-2004 by Andrew Suffield - * Copyright (c) 2008-2013 by Andreas Schneider - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* - * This code was originally released under GPL but Andrew Suffield agreed to - * change it to LGPL. - */ - -/* - * static function don't have NULL pointer checks, segfaults are intended. - */ - -#include -#include -#include - -#include "c_alloc.h" -#include "c_rbtree.h" - -#define NIL &_sentinel /* all leafs are sentinels */ -static c_rbnode_t _sentinel = {NULL, NIL, NIL, NULL, NULL, BLACK}; - -void c_rbtree_create(c_rbtree_t **rbtree, c_rbtree_compare_func *key_compare, c_rbtree_compare_func *data_compare) { - assert(rbtree); - assert(key_compare); - assert(data_compare); - - c_rbtree_t *tree = NULL; - - tree = c_malloc(sizeof(*tree)); - tree->root = NIL; - tree->key_compare = key_compare; - tree->data_compare = data_compare; - tree->size = 0; - - *rbtree = tree; -} - -static c_rbnode_t *_rbtree_subtree_dup(const c_rbnode_t *node, c_rbtree_t *new_tree, c_rbnode_t *new_parent) { - c_rbnode_t *new_node = NULL; - - new_node = (c_rbnode_t*) c_malloc(sizeof(c_rbnode_t)); - - new_node->tree = new_tree; - new_node->data = node->data; - new_node->color = node->color; - new_node->parent = new_parent; - - if (node->left == NIL) { - new_node->left = NIL; - } else { - new_node->left = _rbtree_subtree_dup(node->left, new_tree, new_node); - } - - if (node->right == NIL) { - new_node->right = NIL; - } else { - new_node->right = _rbtree_subtree_dup(node->right, new_tree, new_node); - } - - return new_node; -} - -c_rbtree_t *c_rbtree_dup(const c_rbtree_t *tree) { - c_rbtree_t *new_tree = NULL; - - new_tree = (c_rbtree_t*) c_malloc(sizeof(c_rbtree_t)); - - new_tree->key_compare = tree->key_compare; - new_tree->data_compare = tree->data_compare; - new_tree->size = tree->size; - new_tree->root = _rbtree_subtree_dup(tree->root, new_tree, NULL); - - return new_tree; -} - -static int _rbtree_subtree_free(c_rbnode_t *node) { - assert(node); - - if (node->left != NIL) { - if (_rbtree_subtree_free(node->left) < 0) { - /* TODO: set errno? ECANCELED? */ - return -1; - } - } - - if (node->right != NIL) { - if (_rbtree_subtree_free(node->right) < 0) { - /* TODO: set errno? ECANCELED? */ - return -1; - } - } - - SAFE_FREE(node); - - return 0; -} - -int c_rbtree_free(c_rbtree_t *tree) { - if (tree == NULL) { - errno = EINVAL; - return -1; - } - - if (tree->root != NIL) { - _rbtree_subtree_free(tree->root); - } - - SAFE_FREE(tree); - - return 0; -} - -static int _rbtree_subtree_walk(c_rbnode_t *node, void *data, c_rbtree_visit_func *visitor) { - assert(node); - assert(data); - assert(visitor); - - if (node == NIL) { - return 0; - } - - if (_rbtree_subtree_walk(node->left, data, visitor) < 0) { - return -1; - } - - if ((*visitor)(node->data, data) < 0) { - return -1; - } - - if (_rbtree_subtree_walk(node->right, data, visitor) < 0) { - return -1; - } - - return 0; -} - -int c_rbtree_walk(c_rbtree_t *tree, void *data, c_rbtree_visit_func *visitor) { - if (tree == NULL || data == NULL || visitor == NULL) { - errno = EINVAL; - return -1; - } - - if (_rbtree_subtree_walk(tree->root, data, visitor) < 0) { - return -1; - } - - return 0; -} - -static c_rbnode_t *_rbtree_subtree_head(c_rbnode_t *node) { - assert(node); - - if (node == NIL) { - return node; - } - - while (node->left != NIL) { - node = node->left; - } - - return node; -} - -static c_rbnode_t *_rbtree_subtree_tail(c_rbnode_t *node) { - assert(node); - - if (node == NIL) { - return node; - } - - while (node->right != NIL) { - node = node->right; - } - - return node; -} - -c_rbnode_t *c_rbtree_head(c_rbtree_t *tree) { - c_rbnode_t *node = NULL; - - if (tree == NULL) { - errno = EINVAL; - return NULL; - } - - node = _rbtree_subtree_head(tree->root); - - return node != NIL ? node : NULL; -} - -c_rbnode_t *c_rbtree_tail(c_rbtree_t *tree) { - c_rbnode_t *node = NULL; - - if (tree == NULL) { - errno = EINVAL; - return NULL; - } - - node = _rbtree_subtree_tail(tree->root); - - return node != NIL ? node : NULL; -} - -c_rbnode_t *c_rbtree_node_next(c_rbnode_t *node) { - c_rbnode_t *parent = NULL; - - if (node == NULL) { - errno = EINVAL; - return NULL; - } - - if (node->right != NIL) { - c_rbnode_t *next = NULL; - next = _rbtree_subtree_head(node->right); - - return next != NIL ? next : NULL; - } - - parent = node->parent; - while (parent && node == parent->right) { - node = parent; - parent = node->parent; - } - - return parent != NULL ? parent : NULL; -} - -c_rbnode_t *c_rbtree_node_prev(c_rbnode_t *node) { - c_rbnode_t *parent = NULL; - - if (node == NULL) { - return NULL; - } - - if (node->left != NIL) { - c_rbnode_t *prev = NULL; - prev = _rbtree_subtree_tail(node->left); - return prev != NIL ? prev : NULL; - } - - parent = node->parent; - while (parent && node == parent->left) { - node = parent; - parent = node->parent; - } - - return parent != NULL ? parent : NULL; -} - -c_rbnode_t *c_rbtree_find(c_rbtree_t *tree, const void *key) { - int cmp = 0; - c_rbnode_t *node = NULL; - - if (tree == NULL) { - errno = EINVAL; - return NULL; - } - node = tree->root; - - while (node != NIL) { - cmp = tree->key_compare(key, node->data); - if (cmp == 0) { - return node; - } - - if (cmp < 0) { - node = node->left; - } else { - node = node->right; - } - } - - return NULL; -} - -static void _rbtree_subtree_left_rotate(c_rbnode_t *x) { - c_rbnode_t *y = NULL; - - assert(x); - - y = x->right; - - /* establish x-right link */ - x->right = y->left; - - if (y->left != NIL) { - y->left->parent = x; - } - - /* establish y->parent link */ - if (y != NIL) { - y->parent = x->parent; - } - - if (x->parent) { - if (x == x->parent->left) { - x->parent->left = y; - } else { - x->parent->right = y; - } - } else { - x->tree->root = y; - } - - /* link x and y */ - y->left = x; - if (x != NIL) { - x->parent = y; - } -} - -/* rotat node x to the right */ -static void _rbtree_subtree_right_rotate(c_rbnode_t *x) { - c_rbnode_t *y = NULL; - - assert(x); - - y = x->left; - - /* establish x->left link */ - x->left = y->right; - - if (y->right != NIL) { - y->right->parent = x; - } - - /* establish y->parent link */ - if (y != NIL) { - y->parent = x->parent; - } - - if (x->parent) { - if (x == x->parent->right) { - x->parent->right = y; - } else { - x->parent->left = y; - } - } else { - x->tree->root = y; - } - - /* link x and y */ - y->right = x; - if (x != NIL) { - x->parent = y; - } -} - -int c_rbtree_insert(c_rbtree_t *tree, void *data) { - int cmp = 0; - c_rbnode_t *current = NULL; - c_rbnode_t *parent = NULL; - c_rbnode_t *x = NULL; - - if (tree == NULL) { - errno = EINVAL; - return -1; - } - - /* First we do a classic binary tree insert */ - current = tree->root; - parent = NULL; - - while (current != NIL) { - cmp = tree->data_compare(data, current->data); - parent = current; - if (cmp == 0) { - return 1; - } else if (cmp < 0) { - current = current->left; - } else { - current = current->right; - } - } - - x = (c_rbnode_t *) c_malloc(sizeof(c_rbnode_t)); - - x->tree = tree; - x->data = data; - x->parent = parent; - x->left = NIL; - x->right = NIL; - x->color = RED; - - if (parent) { - /* Note that cmp still contains the comparison of data with - * parent->data, from the last pass through the loop above - */ - if (cmp < 0) { - parent->left = x; - } else { - parent->right = x; - } - } else { - tree->root = x; - } - - /* Insert fixup - check red-black properties */ - while (x != tree->root && x->parent->color == RED) { - /* we have a violation */ - if (x->parent == x->parent->parent->left) { - c_rbnode_t *y = NULL; - - y = x->parent->parent->right; - if (y->color == RED) { - x->parent->color = BLACK; - y->color = BLACK; - x->parent->parent->color = RED; - x = x->parent->parent; - } else { - /* uncle is back */ - if (x == x->parent->right) { - /* make x a left child */ - x = x->parent; - _rbtree_subtree_left_rotate(x); - } - x->parent->color = BLACK; - x->parent->parent->color = RED; - _rbtree_subtree_right_rotate(x->parent->parent); - } - } else { - c_rbnode_t *y = NULL; - - y = x->parent->parent->left; - if (y->color == RED) { - x->parent->color = BLACK; - y->color = BLACK; - x->parent->parent->color = RED; - x = x->parent->parent; - } else { - /* uncle is back */ - if (x == x->parent->left) { - x = x->parent; - _rbtree_subtree_right_rotate(x); - } - x->parent->color = BLACK; - x->parent->parent->color = RED; - _rbtree_subtree_left_rotate(x->parent->parent); - } - } - } /* end while */ - tree->root->color = BLACK; - - tree->size++; - - return 0; -} - -int c_rbtree_node_delete(c_rbnode_t *node) { - c_rbtree_t *tree; - c_rbnode_t *y; - c_rbnode_t *x; - - if (node == NULL || node == NIL) { - errno = EINVAL; - return -1; - } - - tree = node->tree; - - if (node->left == NIL || node->right == NIL) { - /* y has a NIL node as a child */ - y = node; - } else { - /* find tree successor with a NIL node as a child */ - y = node; - while(y->left != NIL) { - y = y->left; - } - } - - /* x is y's only child */ - if (y->left != NIL) { - x = y->left; - } else { - x = y->right; - } - - /* remove y from the parent chain */ - x->parent = y->parent; - - if (y->parent) { - if (y == y->parent->left) { - y->parent->left = x; - } else { - y->parent->right = x; - } - } else { - y->tree->root = x; - } - - /* If y is not the node we're deleting, splice it in place of that - * node - * - * The traditional code would call for us to simply copy y->data, but - * that would invalidate the wrong pointer - there might be external - * references to this node, and we must preserve its address. - */ - if (y != node) { - /* Update y */ - y->parent = node->parent; - y->left = node->left; - y->right = node->right; - - /* Update the children and the parent */ - if (y->left != NIL) { - y->left->parent = y; - } - if (y->right != NIL) { - y->right->parent = y; - } - if (y->parent != NULL) { - if (node == y->parent->left) { - y->parent->left = y; - } else { - y->parent->right = y; - } - } else { - y->tree->root = y; - } - } - - if (y->color == BLACK) { - while (x != y->tree->root && x->color == BLACK) { - if (x == x->parent->left) { - c_rbnode_t *w = NULL; - - w = x->parent->right; - - if (w->color == RED) { - w->color = BLACK; - x->parent->color = RED; - _rbtree_subtree_left_rotate(x->parent); - w = x->parent->right; - } - - if (w->left->color == BLACK && w->right->color == BLACK) { - w->color = RED; - x = x->parent; - } else { - if (w->right->color == BLACK) { - w->left->color = BLACK; - w->color = RED; - _rbtree_subtree_right_rotate(w); - w = x->parent->right; - } - w->color = x->parent->color; - x->parent->color = BLACK; - w->right->color = BLACK; - _rbtree_subtree_left_rotate(x->parent); - x = y->tree->root; - } - } else { - c_rbnode_t *w = NULL; - - w = x->parent->left; - if (w->color == RED) { - w->color = BLACK; - x->parent->color = RED; - _rbtree_subtree_right_rotate(x->parent); - w = x->parent->left; - } - - if (w->right->color == BLACK && w->left->color == BLACK) { - w->color = RED; - x = x->parent; - } else { - if (w->left->color == BLACK) { - w->right->color = BLACK; - w->color = RED; - _rbtree_subtree_left_rotate(w); - w = x->parent->left; - } - w->color = x->parent->color; - x->parent->color = BLACK; - w->left->color = BLACK; - _rbtree_subtree_right_rotate(x->parent); - x = y->tree->root; - } - } - } - x->color = BLACK; - } /* end if: y->color == BLACK */ - - /* node has now been spliced out of the tree */ - SAFE_FREE(y); - tree->size--; - - return 0; -} - -static int _rbtree_subtree_check_black_height(c_rbnode_t *node) { - int left = 0; - int right = 0; - - assert(node); - - if (node == NIL) { - return 0; - } - - left = _rbtree_subtree_check_black_height(node->left); - right = _rbtree_subtree_check_black_height(node->right); - if (left != right) { - return -1; - } - - return left + (node->color == BLACK); -} - -int c_rbtree_check_sanity(c_rbtree_t *tree) { - c_rbnode_t *node = NULL; - c_rbnode_t *prev = NULL; - c_rbnode_t *next = NULL; - c_rbnode_t *tail = NULL; - size_t size = 0; - - if (tree == NULL) { - errno = EINVAL; - return -1; - } - - if (! tree->key_compare || ! tree->data_compare) { - errno = EINVAL; - return -2; - } - - /* Iterate the tree */ - tail = c_rbtree_tail(tree); - for (node = c_rbtree_head(tree); node; node = next) { - if (node->tree != tree) { - return -4; - } - - /* We should never see a nil while iterating */ - if (node == NIL) { - return -5; - } - - /* node == tree-root iff node->parent == NIL */ - if (node == tree->root) { - if (node->parent != NULL) { - return -6; - } - } else { - if (node->parent == NULL) { - return -7; - } - } - - /* Invertability of the iterate functions */ - if (prev != c_rbtree_node_prev(node)) { - return -8; - } - - /* Check the iteration sequence */ - if (prev) { - if (tree->data_compare(prev->data, node->data) > 0) { - return -9; - } - - /* And the other way around, to make sure data_compare is stable */ - if (tree->data_compare(node->data, prev->data) < 0) { - return -10; - } - } - - /* The binary tree property */ - if (node->left != NIL) { - if (tree->data_compare(node->left->data, node->data) > 0) { - return -11; - } - - if (tree->data_compare(node->data, node->left->data) < 0) { - return -11; - } - } - - if (node->right != NIL) { - if (tree->data_compare(node->data, node->right->data) > 0) { - return -12; - } - - if (tree->data_compare(node->right->data, node->data) < 0) { - return -13; - } - } - - /* Red-black tree property 3: red nodes have black children */ - if (node->color == RED) { - if (node->left->color == RED) { - return -14; - } - if (node->right->color == RED) { - return -15; - } - } - - /* next == NULL if node == tail */ - next = c_rbtree_node_next(node); - if (next) { - if (node == tail) { - return -16; - } - } else { - if (node != tail) { - return -17; - } - } - - prev = node; - size++; - } /* end for loop */ - - if (size != tree->size) { - return -18; - } - - if (_rbtree_subtree_check_black_height(tree->root) < 0) { - return -19; - } - - return 0; -} diff --git a/src/csync/std/c_rbtree.h b/src/csync/std/c_rbtree.h deleted file mode 100644 index 69b4c0d73..000000000 --- a/src/csync/std/c_rbtree.h +++ /dev/null @@ -1,318 +0,0 @@ -/* - * cynapses libc functions - * - * Copyright (c) 2003-2004 by Andrew Suffield - * Copyright (c) 2008-2013 by Andreas Schneider - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/** - * @file c_rbtree.h - * - * @brief Interface of the cynapses libc red-black tree implementation - * - * A red-black tree is a type of self-balancing binary search tree. It is - * complex, but has good worst-case running time for its operations and is - * efficient in practice: it can search, insert, and delete in O(log n) - * time, where n is the number of elements in the tree. - * - * In red-black trees, the leaf nodes are not relevant and do not contain - * data. Therefore we use a sentinal node to save memory. All references - * from internal nodes to leaf nodes instead point to the sentinel node. - * - * In a red-black tree each node has a color attribute, the value of which - * is either red or black. In addition to the ordinary requirements imposed - * on binary search trees, the following additional requirements of any - * valid red-black tree apply: - * - * 1. A node is either red or black. - * 2. The root is black. - * 3. All leaves are black, even when the parent is black - * (The leaves are the null children.) - * 4. Both children of every red node are black. - * 5. Every simple path from a node to a descendant leaf contains the same - * number of black nodes, either counting or not counting the null black - * nodes. (Counting or not counting the null black nodes does not affect - * the structure as long as the choice is used consistently.). - * - * These constraints enforce a critical property of red-black trees: that the - * longest path from the root to a leaf is no more than twice as long as the - * shortest path from the root to a leaf in that tree. The result is that the - * tree is roughly balanced. Since operations such as inserting, deleting, and - * finding values requires worst-case time proportional to the height of the - * tree, this theoretical upper bound on the height allows red-black trees to - * be efficient in the worst-case, unlike ordinary binary search trees. - * - * http://en.wikipedia.org/wiki/Red-black_tree - * - * @defgroup cynRBTreeInternals cynapses libc red-black tree functions - * @ingroup cynLibraryAPI - * - * @{ - */ -#ifndef _C_RBTREE_H -#define _C_RBTREE_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* Forward declarations */ -struct c_rbtree_s; typedef struct c_rbtree_s c_rbtree_t; -struct c_rbnode_s; typedef struct c_rbnode_s c_rbnode_t; - -/** - * Define the two colors for the red-black tree - */ -enum xrbcolor_e { BLACK = 0, RED }; typedef enum xrbcolor_e xrbcolor_t; - -/** - * @brief Callback function to compare a key with the data from a - * red-black tree node. - * - * @param key key as a generic pointer - * @param data data as a generic pointer - * - * @return It returns an integer less than, equal to, or greater than zero - * depending on the key or data you use. The function is similar - * to strcmp(). - */ -typedef int c_rbtree_compare_func(const void *key, const void *data); - -/** - * @brief Visit function for the c_rbtree_walk() function. - * - * This function will be called by c_rbtree_walk() for every node. It is up to - * the developer what the function does. The fist parameter is a node object - * the second can be of any kind. - * - * @param obj The node data that will be passed by c_rbtree_walk(). - * @param data Generic data pointer. - * - * @return 0 on success, < 0 on error. You should set errno. - * - */ -typedef int c_rbtree_visit_func(void *, void *); - -/** - * Structure that represents a red-black tree - */ -struct c_rbtree_s { - c_rbnode_t *root; - c_rbtree_compare_func *key_compare; - c_rbtree_compare_func *data_compare; - size_t size; -}; - -/** - * Structure that represents a node of a red-black tree - */ -struct c_rbnode_s { - c_rbtree_t *tree; - c_rbnode_t *left; - c_rbnode_t *right; - c_rbnode_t *parent; - void *data; - xrbcolor_t color; -}; - -/** - * @brief Create the red-black tree - * - * @param rbtree The pointer to assign the allocated memory. - * - * @param key_compare Callback function to compare a key with the data - * inside a reb-black tree node. - * - * @param data_compare Callback function to compare a key as data with thee - * data inside a red-black tree node. - */ -void c_rbtree_create(c_rbtree_t **rbtree, c_rbtree_compare_func *key_compare, c_rbtree_compare_func *data_compare); - -/** - * @brief Duplicate a red-black tree. - * - * @param tree Tree to duplicate. - * - * @return Pointer to a new allocated duplicated rbtree. NULL if an error - * occurred. - */ -c_rbtree_t *c_rbtree_dup(const c_rbtree_t *tree); - -/** - * @brief Free the structure of a red-black tree. - * - * You should call c_rbtree_destroy() before you call this function. - * - * @param tree The tree to free. - * - * @return 0 on success, less than 0 if an error occurred. - */ -int c_rbtree_free(c_rbtree_t *tree); - -/** - * @brief Destroy the content and the nodes of an red-black tree. - * - * This is far from the most efficient way to walk a tree, but it is - * the *safest* way to destroy a tree - the destructor can do almost - * anything (as long as it does not create an infinite loop) to the - * tree structure without risk. - * - * If for some strange reason you need a faster destructor (think - * twice - speed and memory deallocation don't mix well) then consider - * stashing an llist of dataects and destroying that instead, and just - * using c_rbtree_free() on your tree. - * - * @param T The tree to destroy. - * @param DESTRUCTOR The destructor to call on a node to destroy. - */ -#define c_rbtree_destroy(T, DESTRUCTOR) \ - do { \ - if (T) { \ - c_rbnode_t *_c_rbtree_temp; \ - while ((_c_rbtree_temp = c_rbtree_head(T))) { \ - (DESTRUCTOR)(_c_rbtree_temp->data); \ - if (_c_rbtree_temp == c_rbtree_head(T)) { \ - c_rbtree_node_delete(_c_rbtree_temp); \ - } \ - } \ - } \ - SAFE_FREE(T); \ - } while (0); - -/** - * @brief Inserts a node into a red black tree. - * - * @param tree The red black tree to insert the node. - * @param data The data to insert into the tree. - * - * @return 0 on success, 1 if a duplicate has been found and < 0 if an error - * occurred with errno set. - * EINVAL if a null pointer has been passed as the tree. - * ENOMEM if there is no memory left. - */ -int c_rbtree_insert(c_rbtree_t *tree, void *data); - -/** - * @brief Find a node in a red-black tree. - * - * c_rbtree_find() is searching for the given key in a red-black tree and - * returns the node if the key has been found. - * - * @param tree The tree to search. - * @param key The key to search for. - * - * @return If the key was found the node will be returned. On error NULL - * will be returned. - */ -c_rbnode_t *c_rbtree_find(c_rbtree_t *tree, const void *key); - -/** - * @brief Get the head of the red-black tree. - * - * @param tree The tree to get the head for. - * - * @return The head node. NULL if an error occurred. - */ -c_rbnode_t *c_rbtree_head(c_rbtree_t *tree); - -/** - * @brief Get the tail of the red-black tree. - * - * @param tree The tree to get the tail for. - * - * @return The tail node. NULL if an error occurred. - */ -c_rbnode_t *c_rbtree_tail(c_rbtree_t *tree); - -/** - * @brief Get the size of the red-black tree. - * - * @param T The tree to get the size from. - * - * @return The size of the red-black tree. - */ -#define c_rbtree_size(T) (T) == NULL ? 0 : ((T)->size) - -/** - * @brief Walk over a red-black tree. - * - * Walk over a red-black tree calling a visitor function for each node found. - * - * @param tree Tree to walk. - * @param data Data which should be passed to the visitor function. - * @param visitor Visitor function. This will be called for each node passed. - * - * @return 0 on sucess, less than 0 if an error occurred. - */ -int c_rbtree_walk(c_rbtree_t *tree, void *data, c_rbtree_visit_func *visitor); - -/** - * @brief Delete a node in a red-black tree. - * - * @param node Node which should be deleted. - * - * @return 0 on success, -1 if an error occurred. - */ -int c_rbtree_node_delete(c_rbnode_t *node); - -/** - * @brief Get the next node. - * - * @param node The node of which you want the next node. - * - * @return The next node, NULL if an error occurred. - */ -c_rbnode_t *c_rbtree_node_next(c_rbnode_t *node); - -/** - * @brief Get the previous node. - * - * @param node The node of which you want the previous node. - * - * @return The previous node, NULL if an error occurred. - */ -c_rbnode_t *c_rbtree_node_prev(c_rbnode_t *node); - -/** - * @brief Get the data of a node. - * - * @param N The node to get the data from. - * - * @return The data, NULL if an error occurred. - */ -#define c_rbtree_node_data(N) ((N) ? ((N)->data) : NULL) - -/** - * @brief Perform a sanity check for a red-black tree. - * - * This is mostly for testing purposes. - * - * @param tree The tree to check. - * - * @return 0 on success, less than 0 if an error occurred. - */ -int c_rbtree_check_sanity(c_rbtree_t *tree); - -/** - * }@ - */ - -#ifdef __cplusplus -} -#endif - -#endif /* _C_RBTREE_H */ diff --git a/src/libsync/discoveryphase.cpp b/src/libsync/discoveryphase.cpp index db846e691..9ebcd7fa8 100644 --- a/src/libsync/discoveryphase.cpp +++ b/src/libsync/discoveryphase.cpp @@ -59,7 +59,7 @@ static bool findPathInList(const QStringList &list, const QString &path) return pathSlash.startsWith(*it); } -bool DiscoveryJob::isInSelectiveSyncBlackList(const char *path) const +bool DiscoveryJob::isInSelectiveSyncBlackList(const QByteArray &path) const { if (_selectiveSyncBlackList.isEmpty()) { // If there is no black list, everything is allowed @@ -73,24 +73,23 @@ bool DiscoveryJob::isInSelectiveSyncBlackList(const char *path) const // Also try to adjust the path if there was renames if (csync_rename_count(_csync_ctx)) { - QScopedPointer adjusted( - csync_rename_adjust_path_source(_csync_ctx, path)); - if (strcmp(adjusted.data(), path) != 0) { - return findPathInList(_selectiveSyncBlackList, QString::fromUtf8(adjusted.data())); + QByteArray adjusted = csync_rename_adjust_path_source(_csync_ctx, path); + if (adjusted != path) { + return findPathInList(_selectiveSyncBlackList, QString::fromUtf8(adjusted)); } } return false; } -int DiscoveryJob::isInSelectiveSyncBlackListCallback(void *data, const char *path) +int DiscoveryJob::isInSelectiveSyncBlackListCallback(void *data, const QByteArray &path) { return static_cast(data)->isInSelectiveSyncBlackList(path); } -bool DiscoveryJob::checkSelectiveSyncNewFolder(const QString &path, const char *remotePerm) +bool DiscoveryJob::checkSelectiveSyncNewFolder(const QString &path, const QByteArray &remotePerm) { - if (_syncOptions._confirmExternalStorage && std::strchr(remotePerm, 'M')) { + if (_syncOptions._confirmExternalStorage && remotePerm.contains('M')) { // 'M' in the permission means external storage. /* Note: DiscoverySingleDirectoryJob::directoryListingIteratedSlot make sure that only the @@ -145,7 +144,7 @@ bool DiscoveryJob::checkSelectiveSyncNewFolder(const QString &path, const char * } } -int DiscoveryJob::checkSelectiveSyncNewFolderCallback(void *data, const char *path, const char *remotePerm) +int DiscoveryJob::checkSelectiveSyncNewFolderCallback(void *data, const QByteArray &path, const QByteArray &remotePerm) { return static_cast(data)->checkSelectiveSyncNewFolder(QString::fromUtf8(path), remotePerm); } diff --git a/src/libsync/discoveryphase.h b/src/libsync/discoveryphase.h index 4a09c3462..c3d44405b 100644 --- a/src/libsync/discoveryphase.h +++ b/src/libsync/discoveryphase.h @@ -210,10 +210,10 @@ class DiscoveryJob : public QObject * return true if the given path should be ignored, * false if the path should be synced */ - bool isInSelectiveSyncBlackList(const char *path) const; - static int isInSelectiveSyncBlackListCallback(void *, const char *); - bool checkSelectiveSyncNewFolder(const QString &path, const char *remotePerm); - static int checkSelectiveSyncNewFolderCallback(void *data, const char *path, const char *remotePerm); + bool isInSelectiveSyncBlackList(const QByteArray &path) const; + static int isInSelectiveSyncBlackListCallback(void *, const QByteArray &); + bool checkSelectiveSyncNewFolder(const QString &path, const QByteArray &remotePerm); + static int checkSelectiveSyncNewFolderCallback(void *data, const QByteArray &path, const QByteArray &remotePerm); // Just for progress static void update_job_update_callback(bool local, diff --git a/src/libsync/syncengine.cpp b/src/libsync/syncengine.cpp index a6599751e..ebb745f70 100644 --- a/src/libsync/syncengine.cpp +++ b/src/libsync/syncengine.cpp @@ -128,9 +128,6 @@ QString SyncEngine::csyncErrorToString(CSYNC_STATUS err) case CSYNC_STATUS_NO_MODULE: errStr = tr("

The %1 plugin for csync could not be loaded.
Please verify the installation!

").arg(qApp->applicationName()); break; - case CSYNC_STATUS_TREE_ERROR: - errStr = tr("CSync got an error while processing internal trees."); - break; case CSYNC_STATUS_PARAM_ERROR: errStr = tr("CSync fatal parameter error."); break; @@ -347,7 +344,7 @@ int SyncEngine::treewalkRemote(csync_file_stat_t *file, csync_file_stat_t *other * Called on each entry in the local and remote trees by * csync_walk_local_tree()/csync_walk_remote_tree(). * - * It merges the two csync rbtrees into a single map of SyncFileItems. + * It merges the two csync file trees into a single map of SyncFileItems. * * See doc/dev/sync-algorithm.md for an overview. */ @@ -359,7 +356,7 @@ int SyncEngine::treewalkFile(csync_file_stat_t *file, csync_file_stat_t *other, QTextCodec::ConverterState utf8State; static QTextCodec *codec = QTextCodec::codecForName("UTF-8"); ASSERT(codec); - QString fileUtf8 = codec->toUnicode(file->path, qstrlen(file->path), &utf8State); + QString fileUtf8 = codec->toUnicode(file->path, file->path.size(), &utf8State); QString renameTarget; QString key = fileUtf8; @@ -368,7 +365,7 @@ int SyncEngine::treewalkFile(csync_file_stat_t *file, csync_file_stat_t *other, qCWarning(lcEngine) << "File ignored because of invalid utf-8 sequence: " << file->path; instruction = CSYNC_INSTRUCTION_IGNORE; } else { - renameTarget = codec->toUnicode(file->rename_path, qstrlen(file->rename_path), &utf8State); + renameTarget = codec->toUnicode(file->rename_path, file->rename_path.size(), &utf8State); if (utf8State.invalidChars > 0 || utf8State.remainingChars > 0) { qCWarning(lcEngine) << "File ignored because of invalid utf-8 sequence in the rename_path: " << file->path << file->rename_path; instruction = CSYNC_INSTRUCTION_IGNORE; @@ -937,7 +934,7 @@ void SyncEngine::slotDiscoveryJobFinished(int discoveryResult) _backInTimeFiles = 0; bool walkOk = true; _remotePerms.clear(); - _remotePerms.reserve(c_rbtree_size(_csync_ctx->remote.tree)); + _remotePerms.reserve(_csync_ctx->remote.files.size()); _seenFiles.clear(); _temporarilyUnavailablePaths.clear(); _renamedFolders.clear(); diff --git a/test/csync/CMakeLists.txt b/test/csync/CMakeLists.txt index a735f8a0b..237c52e27 100644 --- a/test/csync/CMakeLists.txt +++ b/test/csync/CMakeLists.txt @@ -23,7 +23,6 @@ set(TEST_TARGET_LIBRARIES ${TORTURE_LIBRARY}) add_cmocka_test(check_std_c_alloc std_tests/check_std_c_alloc.c ${TEST_TARGET_LIBRARIES}) add_cmocka_test(check_std_c_jhash std_tests/check_std_c_jhash.c ${TEST_TARGET_LIBRARIES}) add_cmocka_test(check_std_c_path std_tests/check_std_c_path.c ${TEST_TARGET_LIBRARIES}) -add_cmocka_test(check_std_c_rbtree std_tests/check_std_c_rbtree.c ${TEST_TARGET_LIBRARIES}) add_cmocka_test(check_std_c_str std_tests/check_std_c_str.c ${TEST_TARGET_LIBRARIES}) add_cmocka_test(check_std_c_time std_tests/check_std_c_time.c ${TEST_TARGET_LIBRARIES}) diff --git a/test/csync/csync_tests/check_csync_statedb_query.cpp b/test/csync/csync_tests/check_csync_statedb_query.cpp index d507c7108..208e2c524 100644 --- a/test/csync/csync_tests/check_csync_statedb_query.cpp +++ b/test/csync/csync_tests/check_csync_statedb_query.cpp @@ -146,19 +146,18 @@ static void check_csync_statedb_drop_tables(void **state) static void check_csync_statedb_insert_metadata(void **state) { CSYNC *csync = (CSYNC*)*state; - csync_file_stat_t *st; + std::unique_ptr st; int i, rc = 0; // rc = csync_statedb_create_tables(csync->statedb.db); assert_int_equal(rc, 0); for (i = 0; i < 100; i++) { - st = new csync_file_stat_t; + st.reset(new csync_file_stat_t); st->path = QString("file_%1").arg(i).toUtf8(); st->phash = i; - rc = c_rbtree_insert(csync->local.tree, (void *) st); - assert_int_equal(rc, 0); + csync->local.files[st->path] = std::move(st); } // rc = csync_statedb_insert_metadata(csync, csync->statedb.db); @@ -168,15 +167,15 @@ static void check_csync_statedb_insert_metadata(void **state) static void check_csync_statedb_write(void **state) { CSYNC *csync = (CSYNC*)*state; - csync_file_stat_t *st; - int i, rc; + std::unique_ptr st; + int i, rc = 0; for (i = 0; i < 100; i++) { - st = new csync_file_stat_t; + st.reset(new csync_file_stat_t); st->path = QString("file_%1").arg(i).toUtf8(); st->phash = i; - rc = c_rbtree_insert(csync->local.tree, (void *) st); + csync->local.files[st->path] = std::move(st); assert_int_equal(rc, 0); } diff --git a/test/csync/csync_tests/check_csync_update.cpp b/test/csync/csync_tests/check_csync_update.cpp index f8329465f..4fae4e1a7 100644 --- a/test/csync/csync_tests/check_csync_update.cpp +++ b/test/csync/csync_tests/check_csync_update.cpp @@ -227,7 +227,7 @@ static void check_csync_detect_update(void **state) assert_int_equal(rc, 0); /* the instruction should be set to new */ - st = (csync_file_stat_t*)c_rbtree_node_data(csync->local.tree->root); + st = csync->local.files.begin()->second.get(); assert_int_equal(st->instruction, CSYNC_INSTRUCTION_NEW); /* create a statedb */ @@ -250,7 +250,7 @@ static void check_csync_detect_update_db_none(void **state) assert_int_equal(rc, 0); /* the instruction should be set to new */ - st = (csync_file_stat_t*)c_rbtree_node_data(csync->local.tree->root); + st = csync->local.files.begin()->second.get(); assert_int_equal(st->instruction, CSYNC_INSTRUCTION_NEW); @@ -271,7 +271,7 @@ static void check_csync_detect_update_db_eval(void **state) assert_int_equal(rc, 0); /* the instruction should be set to new */ - st = (csync_file_stat_t*)c_rbtree_node_data(csync->local.tree->root); + st = csync->local.files.begin()->second.get(); assert_int_equal(st->instruction, CSYNC_INSTRUCTION_NEW); /* create a statedb */ @@ -296,7 +296,7 @@ static void check_csync_detect_update_db_rename(void **state) /* the instruction should be set to rename */ /* * temporarily broken. - st = (csync_file_stat_t*)c_rbtree_node_data(csync->local.tree->root); + st = csync->local.files.begin()->second.get(); assert_int_equal(st->instruction, CSYNC_INSTRUCTION_RENAME); st->instruction = CSYNC_INSTRUCTION_UPDATED; @@ -318,7 +318,7 @@ static void check_csync_detect_update_db_new(void **state) assert_int_equal(rc, 0); /* the instruction should be set to new */ - st = (csync_file_stat_t*)c_rbtree_node_data(csync->local.tree->root); + st = csync->local.files.begin()->second.get(); assert_int_equal(st->instruction, CSYNC_INSTRUCTION_NEW); diff --git a/test/csync/std_tests/check_std_c_rbtree.c b/test/csync/std_tests/check_std_c_rbtree.c deleted file mode 100644 index a493ae3c9..000000000 --- a/test/csync/std_tests/check_std_c_rbtree.c +++ /dev/null @@ -1,366 +0,0 @@ -/* - * libcsync -- a library to sync a directory with another - * - * Copyright (c) 2008-2013 by Andreas Schneider - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -#include -#include - -#include "torture.h" - -#include "std/c_alloc.h" -#include "std/c_rbtree.h" - -typedef struct test_s { - int key; - int number; -} test_t; - -static int data_cmp(const void *key, const void *data) { - test_t *a, *b; - - a = (test_t *) key; - b = (test_t *) data; - - if (a->key < b->key) { - return -1; - } else if (a->key > b->key) { - return 1; - } - - return 0; -} - -static int key_cmp(const void *key, const void *data) { - int a; - test_t *b; - - a = POINTER_TO_INT(key); - b = (test_t *) data; - - if (a < b->key) { - return -1; - } else if (a > b->key) { - return 1; - } - - return 0; -} - -static int visitor(void *obj, void *data) { - test_t *a; - test_t *b; - - a = (test_t *) obj; - b = (test_t *) data; - - if (a->key == b->key) { - a->number = 42; - } - - return 0; -} - -static void destructor(void *data) { - test_t *freedata = NULL; - - freedata = (test_t *) data; - SAFE_FREE(freedata); -} - -static int setup(void **state) { - c_rbtree_t *tree = NULL; - - c_rbtree_create(&tree, key_cmp, data_cmp); - - *state = tree; - return 0; -} - -static int setup_complete_tree(void **state) { - c_rbtree_t *tree = NULL; - int i = 0; - int rc; - - c_rbtree_create(&tree, key_cmp, data_cmp); - - for (i = 0; i < 100; i++) { - test_t *testdata = NULL; - - testdata = c_malloc(sizeof(test_t)); - assert_non_null(testdata); - - testdata->key = i; - - rc = c_rbtree_insert(tree, (void *) testdata); - assert_int_equal(rc, 0); - } - - *state = tree; - return 0; -} - -static int teardown(void **state) { - c_rbtree_t *tree = *state; - - c_rbtree_destroy(tree, destructor); - c_rbtree_free(tree); - - *state = NULL; - return 0; -} - -static void check_c_rbtree_create_free(void **state) -{ - c_rbtree_t *tree = NULL; - int rc; - - (void) state; /* unused */ - - c_rbtree_create(&tree, key_cmp, data_cmp); - assert_int_equal(tree->size, 0); - - rc = c_rbtree_free(tree); - assert_int_equal(rc, 0); -} - -static void check_c_rbtree_free_null(void **state) -{ - int rc; - - (void) state; /* unused */ - - rc = c_rbtree_free(NULL); - assert_int_equal(rc, -1); -} - -static void check_c_rbtree_insert_delete(void **state) -{ - c_rbtree_t *tree = NULL; - c_rbnode_t *node = NULL; - test_t *testdata = NULL; - int rc; - - (void) state; /* unused */ - - c_rbtree_create(&tree, key_cmp, data_cmp); - - testdata = malloc(sizeof(test_t)); - testdata->key = 42; - - rc = c_rbtree_insert(tree, (void *) testdata); - assert_int_equal(rc, 0); - - node = c_rbtree_head(tree); - assert_non_null(node); - - testdata = c_rbtree_node_data(node); - SAFE_FREE(testdata); - rc = c_rbtree_node_delete(node); - assert_int_equal(rc, 0); - - c_rbtree_free(tree); -} - -static void check_c_rbtree_insert_random(void **state) -{ - c_rbtree_t *tree = *state; - int i = 0, rc; - - for (i = 0; i < 100; i++) { - test_t *testdata = NULL; - - testdata = malloc(sizeof(test_t)); - assert_non_null(testdata); - - testdata->key = i; - - rc = c_rbtree_insert(tree, testdata); - assert_int_equal(rc, 0); - - } - rc = c_rbtree_check_sanity(tree); - assert_int_equal(rc, 0); -} - -static void check_c_rbtree_insert_duplicate(void **state) -{ - c_rbtree_t *tree = *state; - test_t *testdata; - int rc; - - testdata = malloc(sizeof(test_t)); - assert_non_null(testdata); - - testdata->key = 42; - - rc = c_rbtree_insert(tree, (void *) testdata); - assert_int_equal(rc, 0); - - /* add again */ - testdata = malloc(sizeof(test_t)); - assert_non_null(testdata); - - testdata->key = 42; - - /* check for duplicate */ - rc = c_rbtree_insert(tree, (void *) testdata); - assert_int_equal(rc, 1); - - free(testdata); -} - -static void check_c_rbtree_find(void **state) -{ - c_rbtree_t *tree = *state; - int rc, i = 42; - c_rbnode_t *node; - test_t *testdata; - - rc = c_rbtree_check_sanity(tree); - assert_int_equal(rc, 0); - - /* find the node with the key 42 */ - node = c_rbtree_find(tree, (void *) &i); - assert_non_null(node); - - testdata = (test_t *) c_rbtree_node_data(node); - assert_int_equal(testdata->key, 42); -} - -static void check_c_rbtree_delete(void **state) -{ - c_rbtree_t *tree = *state; - int rc, i = 42; - c_rbnode_t *node = NULL; - test_t *freedata = NULL; - - rc = c_rbtree_check_sanity(tree); - assert_int_equal(rc, 0); - - node = c_rbtree_find(tree, (void *) &i); - assert_non_null(node); - - freedata = (test_t *) c_rbtree_node_data(node); - free(freedata); - rc = c_rbtree_node_delete(node); - assert_int_equal(rc, 0); - - rc = c_rbtree_check_sanity(tree); - assert_int_equal(rc, 0); -} - -static void check_c_rbtree_walk(void **state) -{ - c_rbtree_t *tree = *state; - int rc, i = 42; - test_t *testdata; - c_rbnode_t *node; - - rc = c_rbtree_check_sanity(tree); - assert_int_equal(rc, 0); - - testdata = (test_t *) c_malloc(sizeof(test_t)); - testdata->key = 42; - - rc = c_rbtree_walk(tree, testdata, visitor); - assert_int_equal(rc, 0); - - /* find the node with the key 42 */ - node = c_rbtree_find(tree, (void *) &i); - assert_non_null(node); - free(testdata); - - testdata = (test_t *) c_rbtree_node_data(node); - assert_int_equal(testdata->number, 42); -} - -static void check_c_rbtree_walk_null(void **state) -{ - c_rbtree_t *tree = *state; - int rc, i = 42; - test_t *testdata; - c_rbnode_t *node; - - rc = c_rbtree_check_sanity(tree); - assert_int_equal(rc, 0); - - testdata = (test_t *) malloc(sizeof(test_t)); - testdata->key = 42; - - rc = c_rbtree_walk(NULL, testdata, visitor); - assert_int_equal(rc, -1); - assert_int_equal(errno, EINVAL); - - rc = c_rbtree_walk(tree, NULL, visitor); - assert_int_equal(rc, -1); - assert_int_equal(errno, EINVAL); - - rc = c_rbtree_walk(tree, testdata, NULL); - assert_int_equal(rc, -1); - assert_int_equal(errno, EINVAL); - - /* find the node with the key 42 */ - node = c_rbtree_find(tree, (void *) &i); - assert_non_null(node); - - free(testdata); -} - -static void check_c_rbtree_dup(void **state) -{ - c_rbtree_t *tree = *state; - c_rbtree_t *duptree = NULL; - int rc = -1; - - duptree = c_rbtree_dup(tree); - assert_non_null(duptree); - - rc = c_rbtree_check_sanity(duptree); - assert_int_equal(rc, 0); - - c_rbtree_free(duptree); -} - -#if 0 -static void check_c_rbtree_x) -{ - int rc = -1; - - rc = c_rbtree_check_sanity(tree); - fail_unless(rc == 0, "c_rbtree_check_sanity failed with return code %d", rc); -} -#endif - -int torture_run_tests(void) -{ - const struct CMUnitTest tests[] = { - cmocka_unit_test(check_c_rbtree_create_free), - cmocka_unit_test(check_c_rbtree_free_null), - cmocka_unit_test(check_c_rbtree_insert_delete), - cmocka_unit_test_setup_teardown(check_c_rbtree_insert_random, setup, teardown), - cmocka_unit_test_setup_teardown(check_c_rbtree_insert_duplicate, setup, teardown), - cmocka_unit_test_setup_teardown(check_c_rbtree_find, setup_complete_tree, teardown), - cmocka_unit_test_setup_teardown(check_c_rbtree_delete, setup_complete_tree, teardown), - cmocka_unit_test_setup_teardown(check_c_rbtree_walk, setup_complete_tree, teardown), - cmocka_unit_test_setup_teardown(check_c_rbtree_walk_null, setup_complete_tree, teardown), - cmocka_unit_test_setup_teardown(check_c_rbtree_dup, setup_complete_tree, teardown), - }; - - return cmocka_run_group_tests(tests, NULL, NULL); -} -