dovecot-2.2: dsync: Change duplicate local mailbox GUIDs if they...
dovecot at dovecot.org
dovecot at dovecot.org
Wed Feb 27 11:22:08 EET 2013
details: http://hg.dovecot.org/dovecot-2.2/rev/6bebab0d5c02
changeset: 15982:6bebab0d5c02
user: Timo Sirainen <tss at iki.fi>
date: Wed Feb 27 11:21:48 2013 +0200
description:
dsync: Change duplicate local mailbox GUIDs if they're found.
diffstat:
src/doveadm/dsync/dsync-brain-mailbox-tree.c | 27 ++++++++----
src/doveadm/dsync/dsync-mailbox-tree-fill.c | 49 +++++++++++++++++++++--
src/doveadm/dsync/dsync-mailbox-tree.c | 24 +++++-----
src/doveadm/dsync/dsync-mailbox-tree.h | 11 +++-
src/doveadm/dsync/test-dsync-mailbox-tree-sync.c | 9 ++-
5 files changed, 87 insertions(+), 33 deletions(-)
diffs (247 lines):
diff -r 323b76127e3a -r 6bebab0d5c02 src/doveadm/dsync/dsync-brain-mailbox-tree.c
--- a/src/doveadm/dsync/dsync-brain-mailbox-tree.c Wed Feb 27 11:04:14 2013 +0200
+++ b/src/doveadm/dsync/dsync-brain-mailbox-tree.c Wed Feb 27 11:21:48 2013 +0200
@@ -315,7 +315,7 @@
bool dsync_brain_recv_mailbox_tree(struct dsync_brain *brain)
{
const struct dsync_mailbox_node *remote_node;
- struct dsync_mailbox_node *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;
@@ -335,14 +335,22 @@
node->ns = ns;
dsync_mailbox_node_copy_data(node, remote_node);
}
- if (ret == DSYNC_IBC_RECV_RET_FINISHED) {
- if (dsync_mailbox_tree_build_guid_hash(brain->remote_mailbox_tree) < 0)
- brain->failed = TRUE;
+ if (ret != DSYNC_IBC_RECV_RET_FINISHED)
+ return changed;
- brain->state = DSYNC_STATE_RECV_MAILBOX_TREE_DELETES;
- changed = TRUE;
+ 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;
}
- return changed;
+
+ brain->state = DSYNC_STATE_RECV_MAILBOX_TREE_DELETES;
+ return TRUE;
}
static void
@@ -351,7 +359,7 @@
const struct dsync_mailbox_delete *other_del)
{
const struct dsync_mailbox_node *node;
- struct dsync_mailbox_node *other_node;
+ struct dsync_mailbox_node *other_node, *old_node;
const char *name;
/* see if we can find the deletion based on mailbox tree that should
@@ -388,7 +396,8 @@
other_node->ns = node->ns;
other_node->existence = DSYNC_MAILBOX_NODE_DELETED;
- if (dsync_mailbox_tree_guid_hash_add(other_tree, other_node) < 0)
+ if (dsync_mailbox_tree_guid_hash_add(other_tree, other_node,
+ &old_node) < 0)
i_unreached();
}
diff -r 323b76127e3a -r 6bebab0d5c02 src/doveadm/dsync/dsync-mailbox-tree-fill.c
--- a/src/doveadm/dsync/dsync-mailbox-tree-fill.c Wed Feb 27 11:04:14 2013 +0200
+++ b/src/doveadm/dsync/dsync-mailbox-tree-fill.c Wed Feb 27 11:21:48 2013 +0200
@@ -191,6 +191,40 @@
return 0;
}
+static int
+dsync_mailbox_tree_fix_guid_duplicate(struct dsync_mailbox_tree *tree,
+ struct dsync_mailbox_node *node1,
+ struct dsync_mailbox_node *node2)
+{
+ struct mailbox *box;
+ struct mailbox_update update;
+ const char *node2_name;
+ int ret = 0;
+
+ memset(&update, 0, sizeof(update));
+ guid_128_generate(update.mailbox_guid);
+
+ node2_name = dsync_mailbox_node_get_full_name(tree, node2);
+ i_error("Duplicate mailbox GUID %s for mailboxes %s and %s - "
+ "giving a new GUID %s to %s",
+ guid_128_to_string(node1->mailbox_guid),
+ dsync_mailbox_node_get_full_name(tree, node1), node2_name,
+ guid_128_to_string(update.mailbox_guid), node2_name);
+
+ i_assert(node2->ns != NULL);
+ box = mailbox_alloc(node2->ns->list, node2->name, 0);
+ if (mailbox_update(box, &update) < 0) {
+ i_error("Couldn't update mailbox %s GUID: %s",
+ node2->name, mailbox_get_last_error(box, NULL));
+ ret = -1;
+ } else {
+ memcpy(node2->mailbox_guid, update.mailbox_guid,
+ sizeof(node2->mailbox_guid));
+ }
+ mailbox_free(&box);
+ return ret;
+}
+
int dsync_mailbox_tree_fill(struct dsync_mailbox_tree *tree,
struct mail_namespace *ns, const char *box_name)
{
@@ -205,7 +239,7 @@
MAILBOX_LIST_ITER_SELECT_SUBSCRIBED |
MAILBOX_LIST_ITER_RETURN_NO_FLAGS;
struct mailbox_list_iterate_context *iter;
- struct dsync_mailbox_node *node;
+ struct dsync_mailbox_node *node, *dup_node1, *dup_node2;
const struct mailbox_info *info;
const char *list_pattern = box_name != NULL ? box_name : "*";
int ret = 0;
@@ -244,12 +278,17 @@
i_error("Mailbox listing for namespace '%s' failed", ns->prefix);
ret = -1;
}
+ if (ret < 0)
+ return -1;
- if (dsync_mailbox_tree_build_guid_hash(tree) < 0)
- ret = -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)
- ret = -1;
- return ret;
+ return -1;
+ return 0;
}
diff -r 323b76127e3a -r 6bebab0d5c02 src/doveadm/dsync/dsync-mailbox-tree.c
--- a/src/doveadm/dsync/dsync-mailbox-tree.c Wed Feb 27 11:04:14 2013 +0200
+++ b/src/doveadm/dsync/dsync-mailbox-tree.c Wed Feb 27 11:21:48 2013 +0200
@@ -292,7 +292,8 @@
}
int dsync_mailbox_tree_guid_hash_add(struct dsync_mailbox_tree *tree,
- struct dsync_mailbox_node *node)
+ struct dsync_mailbox_node *node,
+ struct dsync_mailbox_node **old_node_r)
{
struct dsync_mailbox_node *old_node;
uint8_t *guid = node->mailbox_guid;
@@ -300,24 +301,20 @@
if (guid_128_is_empty(node->mailbox_guid))
return 0;
- old_node = hash_table_lookup(tree->guid_hash, guid);
+ *old_node_r = old_node = hash_table_lookup(tree->guid_hash, guid);
if (old_node == NULL)
hash_table_insert(tree->guid_hash, guid, node);
- else if (old_node != node) {
- i_error("Duplicate mailbox GUID %s "
- "for mailboxes %s and %s",
- guid_128_to_string(node->mailbox_guid),
- dsync_mailbox_node_get_full_name(tree, old_node),
- dsync_mailbox_node_get_full_name(tree, node));
+ else if (old_node != node)
return -1;
- }
return 0;
}
-int dsync_mailbox_tree_build_guid_hash(struct dsync_mailbox_tree *tree)
+int dsync_mailbox_tree_build_guid_hash(struct dsync_mailbox_tree *tree,
+ struct dsync_mailbox_node **dup_node1_r,
+ struct dsync_mailbox_node **dup_node2_r)
{
struct dsync_mailbox_tree_iter *iter;
- struct dsync_mailbox_node *node;
+ struct dsync_mailbox_node *node, *old_node;
const char *name;
int ret = 0;
@@ -327,8 +324,11 @@
}
iter = dsync_mailbox_tree_iter_init(tree);
while (dsync_mailbox_tree_iter_next(iter, &name, &node)) {
- if (dsync_mailbox_tree_guid_hash_add(tree, node) < 0)
+ if (dsync_mailbox_tree_guid_hash_add(tree, node, &old_node) < 0) {
+ *dup_node1_r = node;
+ *dup_node2_r = old_node;
ret = -1;
+ }
}
dsync_mailbox_tree_iter_deinit(&iter);
return ret;
diff -r 323b76127e3a -r 6bebab0d5c02 src/doveadm/dsync/dsync-mailbox-tree.h
--- a/src/doveadm/dsync/dsync-mailbox-tree.h Wed Feb 27 11:04:14 2013 +0200
+++ b/src/doveadm/dsync/dsync-mailbox-tree.h Wed Feb 27 11:21:48 2013 +0200
@@ -137,11 +137,16 @@
struct dsync_mailbox_node *
dsync_mailbox_tree_find_delete(struct dsync_mailbox_tree *tree,
const struct dsync_mailbox_delete *del);
-/* Build GUID lookup hash, if it's not already built. */
-int dsync_mailbox_tree_build_guid_hash(struct dsync_mailbox_tree *tree);
+/* Build GUID lookup hash, if it's not already built. Returns 0 if ok, -1 if
+ there are duplicate GUIDs. The nodes with the duplicate GUIDs are
+ returned. */
+int dsync_mailbox_tree_build_guid_hash(struct dsync_mailbox_tree *tree,
+ struct dsync_mailbox_node **dup_node1_r,
+ struct dsync_mailbox_node **dup_node2_r);
/* Manually add a new node to hash. */
int dsync_mailbox_tree_guid_hash_add(struct dsync_mailbox_tree *tree,
- struct dsync_mailbox_node *node);
+ struct dsync_mailbox_node *node,
+ struct dsync_mailbox_node **old_node_r);
/* Set remote separator used for directory deletions in
dsync_mailbox_tree_find_delete() */
void dsync_mailbox_tree_set_remote_sep(struct dsync_mailbox_tree *tree,
diff -r 323b76127e3a -r 6bebab0d5c02 src/doveadm/dsync/test-dsync-mailbox-tree-sync.c
--- a/src/doveadm/dsync/test-dsync-mailbox-tree-sync.c Wed Feb 27 11:04:14 2013 +0200
+++ b/src/doveadm/dsync/test-dsync-mailbox-tree-sync.c Wed Feb 27 11:21:48 2013 +0200
@@ -159,14 +159,15 @@
{
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);
- dsync_mailbox_tree_build_guid_hash(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);
while ((change = dsync_mailbox_trees_sync_next(ctx)) != NULL) {
@@ -180,8 +181,8 @@
}
/* test tree2 -> tree1 */
- dsync_mailbox_tree_build_guid_hash(orig_tree1);
- dsync_mailbox_tree_build_guid_hash(orig_tree2);
+ 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);
while ((change = dsync_mailbox_trees_sync_next(ctx)) != NULL) {
More information about the dovecot-cvs
mailing list