]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
doveadm backup: If -D parameter is given, log the reason why mailbox gets deleted.
authorTimo Sirainen <tss@iki.fi>
Mon, 21 Oct 2013 18:38:17 +0000 (21:38 +0300)
committerTimo Sirainen <tss@iki.fi>
Mon, 21 Oct 2013 18:38:17 +0000 (21:38 +0300)
src/doveadm/dsync/dsync-brain-mailbox-tree.c
src/doveadm/dsync/dsync-mailbox-tree-sync.c
src/doveadm/dsync/dsync-mailbox-tree.h
src/doveadm/dsync/test-dsync-mailbox-tree-sync.c

index 7eb13e851c86b4af57c35b4495efe15efe623133..a4a4999a595fdc6236ad6d2ab8992c5d422edf27 100644 (file)
@@ -268,6 +268,9 @@ static void dsync_brain_mailbox_trees_sync(struct dsync_brain *brain)
        struct dsync_mailbox_tree_sync_ctx *ctx;
        const struct dsync_mailbox_tree_sync_change *change;
        enum dsync_mailbox_trees_sync_type sync_type;
+       enum dsync_mailbox_trees_sync_flags sync_flags =
+               (brain->debug ? DSYNC_MAILBOX_TREES_SYNC_FLAG_DEBUG : 0) |
+               (brain->master_brain ? DSYNC_MAILBOX_TREES_SYNC_FLAG_MASTER_BRAIN : 0);
 
        if (brain->no_backup_overwrite)
                sync_type = DSYNC_MAILBOX_TREES_SYNC_TYPE_TWOWAY;
@@ -280,7 +283,7 @@ static void dsync_brain_mailbox_trees_sync(struct dsync_brain *brain)
 
        ctx = dsync_mailbox_trees_sync_init(brain->local_mailbox_tree,
                                            brain->remote_mailbox_tree,
-                                           sync_type);
+                                           sync_type, sync_flags);
        while ((change = dsync_mailbox_trees_sync_next(ctx)) != NULL) {
                if (dsync_brain_mailbox_tree_sync_change(brain, change) < 0)
                        brain->failed = TRUE;
index 7f80e693f684f52fdf3f1f5984654ba726450a10..841d88190b895929e8dae4da8f4033b0fe002369 100644 (file)
@@ -8,6 +8,7 @@
 #include "hex-binary.h"
 #include "aqueue.h"
 #include "hash.h"
+#include "dsync-brain-private.h"
 #include "dsync-mailbox-tree-private.h"
 
 #define TEMP_MAX_NAME_LEN 100
@@ -24,8 +25,10 @@ struct dsync_mailbox_tree_bfs_iter {
 
 struct dsync_mailbox_tree_sync_ctx {
        pool_t pool;
+       struct dsync_brain *brain;
        struct dsync_mailbox_tree *local_tree, *remote_tree;
        enum dsync_mailbox_trees_sync_type sync_type;
+       enum dsync_mailbox_trees_sync_flags sync_flags;
 
        ARRAY(struct dsync_mailbox_tree_sync_change) changes;
        unsigned int change_idx;
@@ -144,11 +147,19 @@ sync_set_node_deleted(struct dsync_mailbox_tree *tree,
 static void
 sync_delete_mailbox_node(struct dsync_mailbox_tree_sync_ctx *ctx,
                         struct dsync_mailbox_tree *tree,
-                        struct dsync_mailbox_node *node)
+                        struct dsync_mailbox_node *node, const char *reason)
 {
        struct dsync_mailbox_tree_sync_change *change;
        const char *name;
 
+       if ((ctx->sync_flags & DSYNC_MAILBOX_TREES_SYNC_FLAG_DEBUG) != 0 &&
+           tree == ctx->local_tree) {
+               i_debug("brain %c: Deleting mailbox '%s' (GUID %s): %s",
+                       (ctx->sync_flags & DSYNC_MAILBOX_TREES_SYNC_FLAG_MASTER_BRAIN) != 0 ? 'M' : 'S',
+                       dsync_mailbox_node_get_full_name(tree, node),
+                       guid_128_to_string(node->mailbox_guid), reason);
+       }
+
        if (tree == ctx->local_tree) {
                /* delete this mailbox locally */
                change = array_append_space(&ctx->changes);
@@ -165,7 +176,7 @@ sync_delete_mailbox_node(struct dsync_mailbox_tree_sync_ctx *ctx,
 static void
 sync_delete_mailbox(struct dsync_mailbox_tree_sync_ctx *ctx,
                    struct dsync_mailbox_tree *tree,
-                   struct dsync_mailbox_node *node)
+                   struct dsync_mailbox_node *node, const char *reason)
 {
        struct dsync_mailbox_tree *other_tree;
        struct dsync_mailbox_node *other_node;
@@ -178,9 +189,9 @@ sync_delete_mailbox(struct dsync_mailbox_tree_sync_ctx *ctx,
        if (other_node == NULL) {
                /* doesn't exist / already deleted */
        } else {
-               sync_delete_mailbox_node(ctx, other_tree, other_node);
+               sync_delete_mailbox_node(ctx, other_tree, other_node, reason);
        }
-       sync_delete_mailbox_node(ctx, tree, node);
+       sync_delete_mailbox_node(ctx, tree, node, reason);
 }
 
 static void
@@ -206,7 +217,8 @@ sync_tree_sort_and_delete_mailboxes(struct dsync_mailbox_tree_sync_ctx *ctx,
                        if (!ignore_deletes) {
                                /* this mailbox was deleted. delete it from the
                                   other side as well */
-                               sync_delete_mailbox(ctx, tree, node);
+                               sync_delete_mailbox(ctx, tree, node,
+                                                   "Mailbox has been deleted");
                        } else {
                                /* we want to restore the mailbox back.
                                   just treat it as if it didn't exist */
@@ -904,18 +916,33 @@ sync_rename_temp_mailboxes(struct dsync_mailbox_tree_sync_ctx *ctx,
 }
 
 static bool sync_is_wrong_mailbox(struct dsync_mailbox_node *node,
-                                 const struct dsync_mailbox_node *wanted_node)
+                                 const struct dsync_mailbox_node *wanted_node,
+                                 const char **reason_r)
 {
-       if (wanted_node->existence != DSYNC_MAILBOX_NODE_EXISTS)
+       if (wanted_node->existence != DSYNC_MAILBOX_NODE_EXISTS) {
+               *reason_r = wanted_node->existence == DSYNC_MAILBOX_NODE_DELETED ?
+                       "Mailbox has been deleted" : "Mailbox doesn't exist";
                return TRUE;
-       if (node->uid_validity != wanted_node->uid_validity)
+       }
+       if (node->uid_validity != wanted_node->uid_validity) {
+               *reason_r = t_strdup_printf("UIDVALIDITY changed (%u -> %u)",
+                                           wanted_node->uid_validity,
+                                           node->uid_validity);
                return TRUE;
+       }
        if (node->uid_next > wanted_node->uid_next) {
                /* we can't lower the UIDNEXT */
+               *reason_r = t_strdup_printf("UIDNEXT is too high (%u > %u)",
+                                           node->uid_next,
+                                           wanted_node->uid_next);
+               return TRUE;
+       }
+       if (memcmp(node->mailbox_guid, wanted_node->mailbox_guid,
+                  sizeof(node->mailbox_guid)) != 0) {
+               *reason_r = "GUID changed";
                return TRUE;
        }
-       return memcmp(node->mailbox_guid, wanted_node->mailbox_guid,
-                     sizeof(node->mailbox_guid)) != 0;
+       return FALSE;
 }
 
 static void
@@ -925,6 +952,7 @@ sync_delete_wrong_mailboxes_branch(struct dsync_mailbox_tree_sync_ctx *ctx,
                                   struct dsync_mailbox_node *node,
                                   const struct dsync_mailbox_node *wanted_node)
 {
+       const char *reason;
        int ret;
 
        while (node != NULL && wanted_node != NULL) {
@@ -937,20 +965,22 @@ sync_delete_wrong_mailboxes_branch(struct dsync_mailbox_tree_sync_ctx *ctx,
                if (ret < 0) {
                        /* node shouldn't exist */
                        if (node->existence == DSYNC_MAILBOX_NODE_EXISTS &&
-                           !dsync_mailbox_node_is_dir(node))
-                               sync_delete_mailbox_node(ctx, tree, node);
+                           !dsync_mailbox_node_is_dir(node)) {
+                               sync_delete_mailbox_node(ctx, tree, node,
+                                       "Mailbox doesn't exist");
+                       }
                        node = node->next;
                } else if (ret > 0) {
                        /* wanted_node doesn't exist. it's created later. */
                        wanted_node = wanted_node->next;
-               } else {
-                       if (sync_is_wrong_mailbox(node, wanted_node) &&
+               } else T_BEGIN {
+                       if (sync_is_wrong_mailbox(node, wanted_node, &reason) &&
                            node->existence == DSYNC_MAILBOX_NODE_EXISTS &&
                            !dsync_mailbox_node_is_dir(node))
-                               sync_delete_mailbox_node(ctx, tree, node);
+                               sync_delete_mailbox_node(ctx, tree, node, reason);
                        node = node->next;
                        wanted_node = wanted_node->next;
-               }
+               } T_END;
        }
        for (; node != NULL; node = node->next) {
                /* node and its children shouldn't exist */
@@ -961,7 +991,7 @@ sync_delete_wrong_mailboxes_branch(struct dsync_mailbox_tree_sync_ctx *ctx,
                }
                if (node->existence == DSYNC_MAILBOX_NODE_EXISTS &&
                    !dsync_mailbox_node_is_dir(node))
-                       sync_delete_mailbox_node(ctx, tree, node);
+                       sync_delete_mailbox_node(ctx, tree, node, "Mailbox doesn't exist");
        }
 }
 
@@ -1157,7 +1187,8 @@ dsync_mailbox_tree_update_child_timestamps(struct dsync_mailbox_node *node,
 struct dsync_mailbox_tree_sync_ctx *
 dsync_mailbox_trees_sync_init(struct dsync_mailbox_tree *local_tree,
                              struct dsync_mailbox_tree *remote_tree,
-                             enum dsync_mailbox_trees_sync_type sync_type)
+                             enum dsync_mailbox_trees_sync_type sync_type,
+                             enum dsync_mailbox_trees_sync_flags sync_flags)
 {
        struct dsync_mailbox_tree_sync_ctx *ctx;
        pool_t pool;
@@ -1173,6 +1204,7 @@ dsync_mailbox_trees_sync_init(struct dsync_mailbox_tree *local_tree,
        ctx->local_tree = local_tree;
        ctx->remote_tree = remote_tree;
        ctx->sync_type = sync_type;
+       ctx->sync_flags = sync_flags;
        i_array_init(&ctx->changes, 128);
 
        ignore_deletes = sync_type == DSYNC_MAILBOX_TREES_SYNC_TYPE_PRESERVE_LOCAL;
index 956a5705692a8b04c682ccb04f22392dabb21ed3..a8e52e51d49e56da9877dc4f730db0ceba06a5af 100644 (file)
@@ -4,6 +4,7 @@
 #include "guid.h"
 
 struct mail_namespace;
+struct dsync_brain;
 
 enum dsync_mailbox_trees_sync_type {
        /* two-way sync for both mailboxes */
@@ -14,6 +15,13 @@ enum dsync_mailbox_trees_sync_type {
        DSYNC_MAILBOX_TREES_SYNC_TYPE_PRESERVE_REMOTE
 };
 
+enum dsync_mailbox_trees_sync_flags {
+       /* Enable debugging */
+       DSYNC_MAILBOX_TREES_SYNC_FLAG_DEBUG             = 0x01,
+       /* Show ourself as "master brain" in the debug output */
+       DSYNC_MAILBOX_TREES_SYNC_FLAG_MASTER_BRAIN      = 0x02
+};
+
 enum dsync_mailbox_node_existence {
        /* this is just a filler node for children or for
           subscription deletion */
@@ -174,7 +182,8 @@ void dsync_mailbox_tree_iter_deinit(struct dsync_mailbox_tree_iter **iter);
 struct dsync_mailbox_tree_sync_ctx *
 dsync_mailbox_trees_sync_init(struct dsync_mailbox_tree *local_tree,
                              struct dsync_mailbox_tree *remote_tree,
-                             enum dsync_mailbox_trees_sync_type sync_type);
+                             enum dsync_mailbox_trees_sync_type sync_type,
+                             enum dsync_mailbox_trees_sync_flags sync_flags);
 const struct dsync_mailbox_tree_sync_change *
 dsync_mailbox_trees_sync_next(struct dsync_mailbox_tree_sync_ctx *ctx);
 void dsync_mailbox_trees_sync_deinit(struct dsync_mailbox_tree_sync_ctx **ctx);
index e0fc7bf8937402ec26e002d604c4c4db5506b092..85cf6e2c43b9fd596d22bd3ee7aec719898dac77 100644 (file)
@@ -170,7 +170,7 @@ static void test_trees_nofree(struct dsync_mailbox_tree *tree1,
        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);
+                                           DSYNC_MAILBOX_TREES_SYNC_TYPE_TWOWAY, 0);
        while ((change = dsync_mailbox_trees_sync_next(ctx)) != NULL) {
        }
        dsync_mailbox_trees_sync_deinit(&ctx);
@@ -185,7 +185,7 @@ static void test_trees_nofree(struct dsync_mailbox_tree *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);
+                                           DSYNC_MAILBOX_TREES_SYNC_TYPE_TWOWAY, 0);
        while ((change = dsync_mailbox_trees_sync_next(ctx)) != NULL) {
        }
        dsync_mailbox_trees_sync_deinit(&ctx);