static void test_trees_nofree(struct dsync_mailbox_tree *tree1, struct dsync_mailbox_tree **_tree2) { struct dsync_mailbox_tree *tree2 = *_tree2; struct dsync_mailbox_tree *orig_tree1, *orig_tree2; struct dsync_mailbox_tree_sync_ctx *ctx; struct dsync_mailbox_node *dup_node1, *dup_node2; const struct dsync_mailbox_tree_sync_change *change; orig_tree1 = dsync_mailbox_tree_dup(tree1); orig_tree2 = dsync_mailbox_tree_dup(tree2); /* test tree1 -> tree2 */ dsync_mailbox_tree_build_guid_hash(tree1, &dup_node1, &dup_node2); dsync_mailbox_tree_build_guid_hash(tree2, &dup_node1, &dup_node2); ctx = dsync_mailbox_trees_sync_init(tree1, tree2, DSYNC_MAILBOX_TREES_SYNC_TYPE_TWOWAY, 0); while ((change = dsync_mailbox_trees_sync_next(ctx)) != NULL) { } dsync_mailbox_trees_sync_deinit(&ctx); test_tree_fixup(tree1); test_tree_fixup(tree2); if (!dsync_mailbox_trees_equal(tree1, tree2)) { test_assert(FALSE); trees_dump(tree1, tree2); } /* test tree2 -> tree1 */ dsync_mailbox_tree_build_guid_hash(orig_tree1, &dup_node1, &dup_node2); dsync_mailbox_tree_build_guid_hash(orig_tree2, &dup_node1, &dup_node2); ctx = dsync_mailbox_trees_sync_init(orig_tree2, orig_tree1, DSYNC_MAILBOX_TREES_SYNC_TYPE_TWOWAY, 0); while ((change = dsync_mailbox_trees_sync_next(ctx)) != NULL) { } dsync_mailbox_trees_sync_deinit(&ctx); test_tree_fixup(orig_tree1); test_tree_fixup(orig_tree2); if (!dsync_mailbox_trees_equal(orig_tree1, orig_tree2)) { test_assert(FALSE); trees_dump(orig_tree1, orig_tree2); } /* make sure both directions produced equal trees */ if (!dsync_mailbox_trees_equal(tree1, orig_tree1)) { test_assert(FALSE); trees_dump(tree1, orig_tree1); } dsync_mailbox_tree_deinit(_tree2); dsync_mailbox_tree_deinit(&orig_tree1); dsync_mailbox_tree_deinit(&orig_tree2); }
bool dsync_brain_recv_mailbox_tree(struct dsync_brain *brain) { const struct dsync_mailbox_node *remote_node; struct dsync_mailbox_node *node, *dup_node1, *dup_node2; const char *const *parts, *name; struct mail_namespace *ns; enum dsync_ibc_recv_ret ret; char sep[2]; bool changed = FALSE; sep[0] = brain->hierarchy_sep; sep[1] = '\0'; while ((ret = dsync_ibc_recv_mailbox_tree_node(brain->ibc, &parts, &remote_node)) > 0) { if (dsync_get_mailbox_name(brain, parts, &name, &ns) < 0) { i_error("Couldn't find namespace for mailbox %s", t_strarray_join(parts, sep)); brain->failed = TRUE; return TRUE; } if (brain->debug) { i_debug("brain %c: Remote mailbox tree: %s %s", brain->master_brain ? 'M' : 'S', t_strarray_join(parts, sep), dsync_mailbox_node_to_string(remote_node)); } node = dsync_mailbox_tree_get(brain->remote_mailbox_tree, name); node->ns = ns; dsync_mailbox_node_copy_data(node, remote_node); } if (ret != DSYNC_IBC_RECV_RET_FINISHED) return changed; if (dsync_mailbox_tree_build_guid_hash(brain->remote_mailbox_tree, &dup_node1, &dup_node2) < 0) { i_error("Remote sent duplicate mailbox GUID %s for mailboxes %s and %s", guid_128_to_string(dup_node1->mailbox_guid), dsync_mailbox_node_get_full_name(brain->remote_mailbox_tree, dup_node1), dsync_mailbox_node_get_full_name(brain->remote_mailbox_tree, dup_node2)); brain->failed = TRUE; } brain->state = DSYNC_STATE_RECV_MAILBOX_TREE_DELETES; return TRUE; }
int dsync_mailbox_tree_fill(struct dsync_mailbox_tree *tree, struct mail_namespace *ns, const char *box_name, const guid_128_t box_guid, const char *const *exclude_mailboxes, enum mail_error *error_r) { const enum mailbox_list_iter_flags list_flags = /* FIXME: we'll skip symlinks, because we can't handle them currently. in future we could detect them and create them by creating the symlink. */ MAILBOX_LIST_ITER_SKIP_ALIASES | MAILBOX_LIST_ITER_NO_AUTO_BOXES; const enum mailbox_list_iter_flags subs_list_flags = MAILBOX_LIST_ITER_NO_AUTO_BOXES | MAILBOX_LIST_ITER_SELECT_SUBSCRIBED | MAILBOX_LIST_ITER_RETURN_NO_FLAGS; struct mailbox_list_iterate_context *iter; struct dsync_mailbox_node *node, *dup_node1, *dup_node2; const struct mailbox_info *info; const char *list_pattern = box_name != NULL && box_name[0] != '\\' ? box_name : "*"; int ret = 0; i_assert(mail_namespace_get_sep(ns) == tree->sep); /* assign namespace to its root, so it gets copied to children */ if (ns->prefix_len > 0) { node = dsync_mailbox_tree_get(tree, t_strndup(ns->prefix, ns->prefix_len-1)); node->ns = ns; } else { tree->root.ns = ns; } /* first add all of the existing mailboxes */ iter = mailbox_list_iter_init(ns->list, list_pattern, list_flags); while ((info = mailbox_list_iter_next(iter)) != NULL) T_BEGIN { if (dsync_mailbox_info_is_wanted(info, box_name, exclude_mailboxes)) { if (dsync_mailbox_tree_add(tree, info, box_guid, error_r) < 0) ret = -1; } } T_END; if (mailbox_list_iter_deinit(&iter) < 0) { i_error("Mailbox listing for namespace '%s' failed: %s", ns->prefix, mailbox_list_get_last_internal_error(ns->list, error_r)); ret = -1; } /* add subscriptions */ iter = mailbox_list_iter_init(ns->list, list_pattern, subs_list_flags); while ((info = mailbox_list_iter_next(iter)) != NULL) { if (dsync_mailbox_tree_add_node(tree, info, &node) == 0) node->subscribed = TRUE; else { *error_r = MAIL_ERROR_TEMP; ret = -1; } } if (mailbox_list_iter_deinit(&iter) < 0) { i_error("Mailbox listing for namespace '%s' failed: %s", ns->prefix, mailbox_list_get_last_internal_error(ns->list, error_r)); ret = -1; } if (ret < 0) return -1; while (dsync_mailbox_tree_build_guid_hash(tree, &dup_node1, &dup_node2) < 0) { if (dsync_mailbox_tree_fix_guid_duplicate(tree, dup_node1, dup_node2) < 0) return -1; } /* add timestamps */ if (dsync_mailbox_tree_add_change_timestamps(tree, ns) < 0) return -1; return 0; }