]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
doveadm sync/backup: Added -g <guid> to sync only the specified mailbox (by GUID)
authorTimo Sirainen <tss@iki.fi>
Mon, 25 Mar 2013 15:02:15 +0000 (17:02 +0200)
committerTimo Sirainen <tss@iki.fi>
Mon, 25 Mar 2013 15:02:15 +0000 (17:02 +0200)
Similar to -m <mailbox name>.

src/doveadm/dsync/doveadm-dsync.c
src/doveadm/dsync/dsync-brain-mailbox-tree.c
src/doveadm/dsync/dsync-brain-private.h
src/doveadm/dsync/dsync-brain.c
src/doveadm/dsync/dsync-brain.h
src/doveadm/dsync/dsync-ibc-pipe.c
src/doveadm/dsync/dsync-ibc-stream.c
src/doveadm/dsync/dsync-ibc.h
src/doveadm/dsync/dsync-mailbox-tree-fill.c
src/doveadm/dsync/dsync-mailbox-tree.h

index 97514522e779dfda3d9947a9ced461cce1e2d0b9..6f1269f61ead13cb78d61d4ae6d6a8fd26fb6d84 100644 (file)
@@ -36,7 +36,7 @@
 #include <ctype.h>
 #include <sys/wait.h>
 
-#define DSYNC_COMMON_GETOPT_ARGS "+dEfl:m:n:Nr:Rs:"
+#define DSYNC_COMMON_GETOPT_ARGS "+dEfg:l:m:n:Nr:Rs:"
 #define DSYNC_REMOTE_CMD_EXIT_WAIT_SECS 30
 
 enum dsync_run_type {
@@ -49,6 +49,7 @@ struct dsync_cmd_context {
        struct doveadm_mail_cmd_context ctx;
        enum dsync_brain_sync_type sync_type;
        const char *mailbox, *namespace_prefix;
+       guid_128_t mailbox_guid;
        const char *state_input, *rawlog_path;
 
        const char *remote_name;
@@ -75,6 +76,7 @@ struct dsync_cmd_context {
        unsigned int backup:1;
        unsigned int reverse_backup:1;
        unsigned int remote_user_prefix:1;
+       unsigned int no_mail_sync:1;
 };
 
 static bool legacy_dsync = FALSE;
@@ -468,13 +470,12 @@ cmd_dsync_run(struct doveadm_mail_cmd_context *_ctx, struct mail_user *user)
        else if (ctx->backup)
                brain_flags |= DSYNC_BRAIN_FLAG_BACKUP_SEND;
 
+       if (ctx->no_mail_sync)
+               brain_flags |= DSYNC_BRAIN_FLAG_NO_MAIL_SYNC;
        if (doveadm_debug)
                brain_flags |= DSYNC_BRAIN_FLAG_DEBUG;
-       if (ctx->mailbox != NULL && *ctx->mailbox == '\0') {
-               brain_flags |= DSYNC_BRAIN_FLAG_NO_MAIL_SYNC;
-               ctx->mailbox = NULL;
-       }
        brain = dsync_brain_master_init(user, ibc, sync_ns, ctx->mailbox,
+                                       ctx->mailbox_guid,
                                        ctx->sync_type, brain_flags,
                                        ctx->lock_timeout,
                                        ctx->state_input == NULL ? "" :
@@ -766,13 +767,23 @@ cmd_mailbox_dsync_parse_arg(struct doveadm_mail_cmd_context *_ctx, int c)
        case 'f':
                ctx->sync_type = DSYNC_BRAIN_SYNC_TYPE_FULL;
                break;
+       case 'g':
+               if (optarg[0] == '\0')
+                       ctx->no_mail_sync = TRUE;
+               else if (guid_128_from_string(optarg, ctx->mailbox_guid) < 0 ||
+                        guid_128_is_empty(ctx->mailbox_guid))
+                       i_error("Invalid -g parameter: %s", optarg);
+               break;
        case 'l':
                ctx->lock = TRUE;
                if (str_to_uint(optarg, &ctx->lock_timeout) < 0)
                        i_error("Invalid -l parameter: %s", optarg);
                break;
        case 'm':
-               ctx->mailbox = optarg;
+               if (optarg[0] == '\0')
+                       ctx->no_mail_sync = TRUE;
+               else
+                       ctx->mailbox = optarg;
                break;
        case 'n':
                ctx->namespace_prefix = optarg;
index a295c516c434c10e310d7af18eebd579ad07420c..a049aee81beb7eb6ea91d135fb8aa805ffd312b2 100644 (file)
@@ -85,14 +85,16 @@ void dsync_brain_mailbox_trees_init(struct dsync_brain *brain)
        /* fill the local mailbox tree */
        if (brain->sync_ns != NULL) {
                if (dsync_mailbox_tree_fill(brain->local_mailbox_tree,
-                                           brain->sync_ns, brain->sync_box) < 0)
+                                           brain->sync_ns, brain->sync_box,
+                                           brain->sync_box_guid) < 0)
                        brain->failed = TRUE;
        } else {
                for (ns = brain->user->namespaces; ns != NULL; ns = ns->next) {
                        if (!dsync_brain_want_namespace(brain, ns))
                                continue;
                        if (dsync_mailbox_tree_fill(brain->local_mailbox_tree,
-                                                   ns, brain->sync_box) < 0)
+                                                   ns, brain->sync_box,
+                                                   brain->sync_box_guid) < 0)
                                brain->failed = TRUE;
                }
        }
index 4fd319de92f99b9a6ecb48a1f942f34913d11f17..0021a034625c16671be107a0660a48ee437bcb8a 100644 (file)
@@ -50,7 +50,8 @@ struct dsync_brain {
        struct mail_user *user;
        struct dsync_ibc *ibc;
        struct mail_namespace *sync_ns;
-       char *sync_box;
+       const char *sync_box;
+       guid_128_t sync_box_guid;
        enum dsync_brain_sync_type sync_type;
 
        unsigned int lock_timeout;
index 33fdce3a0575d830a660cbbb5dadcd6a1fcd21f0..c01dd7649b8b2f80d79f2f64feaa4cb51ca30bdf 100644 (file)
@@ -87,6 +87,7 @@ dsync_brain_set_flags(struct dsync_brain *brain, enum dsync_brain_flags flags)
 struct dsync_brain *
 dsync_brain_master_init(struct mail_user *user, struct dsync_ibc *ibc,
                        struct mail_namespace *sync_ns, const char *sync_box,
+                       const guid_128_t sync_box_guid,
                        enum dsync_brain_sync_type sync_type,
                        enum dsync_brain_flags flags, unsigned int lock_timeout,
                        const char *state)
@@ -103,6 +104,7 @@ dsync_brain_master_init(struct mail_user *user, struct dsync_ibc *ibc,
        if (sync_ns != NULL)
                brain->sync_ns = sync_ns;
        brain->sync_box = p_strdup(brain->pool, sync_box);
+       memcpy(brain->sync_box_guid, sync_box_guid, sizeof(brain->sync_box_guid));
        brain->lock_timeout = lock_timeout;
        brain->master_brain = TRUE;
        dsync_brain_set_flags(brain, flags);
@@ -121,6 +123,8 @@ dsync_brain_master_init(struct mail_user *user, struct dsync_ibc *ibc,
        ibc_set.hostname = my_hostdomain();
        ibc_set.sync_ns_prefix = sync_ns == NULL ? NULL : sync_ns->prefix;
        ibc_set.sync_box = sync_box;
+       memcpy(ibc_set.sync_box_guid, sync_box_guid,
+              sizeof(ibc_set.sync_box_guid));
        ibc_set.sync_type = sync_type;
        ibc_set.lock_timeout = lock_timeout;
        /* reverse the backup direction for the slave */
@@ -302,6 +306,8 @@ static bool dsync_brain_slave_recv_handshake(struct dsync_brain *brain)
                                                     ibc_set->sync_ns_prefix);
        }
        brain->sync_box = p_strdup(brain->pool, ibc_set->sync_box);
+       memcpy(brain->sync_box_guid, ibc_set->sync_box_guid,
+              sizeof(brain->sync_box_guid));
        i_assert(brain->sync_type == DSYNC_BRAIN_SYNC_TYPE_UNKNOWN);
        brain->sync_type = ibc_set->sync_type;
        dsync_brain_set_flags(brain, ibc_set->brain_flags);
index 383f0b9c8135d570a1db62ced401915a4506b155..1dc07b3e312572f9be6d5cf21c07ec68a15c4487 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef DSYNC_BRAIN_H
 #define DSYNC_BRAIN_H
 
+#include "guid.h"
+
 struct mail_namespace;
 struct mail_user;
 struct dsync_ibc;
@@ -31,6 +33,7 @@ enum dsync_brain_sync_type {
 struct dsync_brain *
 dsync_brain_master_init(struct mail_user *user, struct dsync_ibc *ibc,
                        struct mail_namespace *sync_ns, const char *sync_box,
+                       const guid_128_t sync_box_guid,
                        enum dsync_brain_sync_type sync_type,
                        enum dsync_brain_flags flags, unsigned int lock_timeout,
                        const char *state);
index 0c6ba31d93231a0fb1ae952fddfae75f4acba9b6..522724c0fe6040645f2b7c65efd7f387adb3e8d5 100644 (file)
@@ -161,6 +161,8 @@ dsync_ibc_pipe_send_handshake(struct dsync_ibc *ibc,
        item->u.set = *set;
        item->u.set.sync_ns_prefix = p_strdup(item->pool, set->sync_ns_prefix);
        item->u.set.sync_box = p_strdup(item->pool, set->sync_box);
+       memcpy(item->u.set.sync_box_guid, set->sync_box_guid,
+              sizeof(item->u.set.sync_box_guid));
 }
 
 static enum dsync_ibc_recv_ret
index a1969fea638600d32e0e50f8e4de8964c8b54fda..e6017497f7a75cf37beaa277e42c0b2c16a760f8 100644 (file)
@@ -70,7 +70,8 @@ static const struct {
        { .name = "handshake",
          .chr = 'H',
          .required_keys = "hostname",
-         .optional_keys = "sync_ns_prefix sync_box sync_type debug sync_visible_namespaces "
+         .optional_keys = "sync_ns_prefix sync_box sync_box_guid sync_type "
+               "debug sync_visible_namespaces "
                "send_mail_requests backup_send backup_recv lock_timeout"
        },
        { .name = "mailbox_state",
@@ -589,6 +590,10 @@ dsync_ibc_stream_send_handshake(struct dsync_ibc *_ibc,
        }
        if (set->sync_box != NULL)
                dsync_serializer_encode_add(encoder, "sync_box", set->sync_box);
+       if (!guid_128_is_empty(set->sync_box_guid)) {
+               dsync_serializer_encode_add(encoder, "sync_box_guid",
+                       guid_128_to_string(set->sync_box_guid));
+       }
 
        sync_type[0] = sync_type[1] = '\0';
        switch (set->sync_type) {
@@ -655,6 +660,12 @@ dsync_ibc_stream_recv_handshake(struct dsync_ibc *_ibc,
                set->sync_ns_prefix = p_strdup(pool, value);
        if (dsync_deserializer_decode_try(decoder, "sync_box", &value))
                set->sync_box = p_strdup(pool, value);
+       if (dsync_deserializer_decode_try(decoder, "sync_box_guid", &value) &&
+           guid_128_from_string(value, set->sync_box_guid) < 0) {
+               dsync_ibc_input_error(ibc, decoder,
+                                     "Invalid sync_box_guid: %s", value);
+               return DSYNC_IBC_RECV_RET_TRYAGAIN;
+       }
        if (dsync_deserializer_decode_try(decoder, "sync_type", &value)) {
                switch (value[0]) {
                case 'f':
index bb7a726fe2ccc0f1efd1810e6bc5f16118ab4765..c046aaf256a00f54b7e2de76e460e0f0779dc860 100644 (file)
@@ -37,6 +37,8 @@ struct dsync_ibc_settings {
        const char *sync_ns_prefix;
        /* if non-NULL, sync only this mailbox name */
        const char *sync_box;
+       /* if non-empty, sync only this mailbox GUID */
+       guid_128_t sync_box_guid;
 
        enum dsync_brain_sync_type sync_type;
        enum dsync_brain_flags brain_flags;
index 2557a39c6b5457376c45943e9a32c8e232dcc76d..ddf2ebb1f4df076775bd202e945b23897d107ed0 100644 (file)
@@ -30,6 +30,17 @@ dsync_mailbox_tree_add_node(struct dsync_mailbox_tree *tree,
        return 0;
 }
 
+static int
+dsync_mailbox_tree_add_exists_node(struct dsync_mailbox_tree *tree,
+                                  const struct mailbox_info *info,
+                                  struct dsync_mailbox_node **node_r)
+{
+       if (dsync_mailbox_tree_add_node(tree, info, node_r) < 0)
+               return -1;
+       (*node_r)->existence = DSYNC_MAILBOX_NODE_EXISTS;
+       return 0;
+}
+
 static int
 dsync_mailbox_tree_get_selectable(struct mailbox *box,
                                  struct mailbox_metadata *metadata_r,
@@ -55,7 +66,8 @@ dsync_mailbox_tree_get_selectable(struct mailbox *box,
 }
 
 static int dsync_mailbox_tree_add(struct dsync_mailbox_tree *tree,
-                                 const struct mailbox_info *info)
+                                 const struct mailbox_info *info,
+                                 const guid_128_t box_guid)
 {
        struct dsync_mailbox_node *node;
        struct mailbox *box;
@@ -63,16 +75,14 @@ static int dsync_mailbox_tree_add(struct dsync_mailbox_tree *tree,
        struct mailbox_status status;
        const char *errstr;
        enum mail_error error;
+       int ret = 0;
 
        if ((info->flags & MAILBOX_NONEXISTENT) != 0)
                return 0;
-
-       if (dsync_mailbox_tree_add_node(tree, info, &node) < 0)
-               return -1;
-       node->existence = DSYNC_MAILBOX_NODE_EXISTS;
-
-       if ((info->flags & MAILBOX_NOSELECT) != 0)
-               return 0;
+       if ((info->flags & MAILBOX_NOSELECT) != 0) {
+               return !guid_128_is_empty(box_guid) ? 0 :
+                       dsync_mailbox_tree_add_exists_node(tree, info, &node);
+       }
 
        /* get GUID and UIDVALIDITY for selectable mailbox */
        box = mailbox_alloc(info->ns->list, info->vname, 0);
@@ -88,16 +98,24 @@ static int dsync_mailbox_tree_add(struct dsync_mailbox_tree *tree,
                default:
                        i_error("Failed to access mailbox %s: %s",
                                info->vname, errstr);
-                       mailbox_free(&box);
-                       return -1;
+                       ret = -1;
                }
-       } else {
-               memcpy(node->mailbox_guid, metadata.guid,
-                      sizeof(node->mailbox_guid));
-               node->uid_validity = status.uidvalidity;
-               node->uid_next = status.uidnext;
+               mailbox_free(&box);
+               return ret;
        }
        mailbox_free(&box);
+
+       if (!guid_128_is_empty(box_guid) &&
+           !guid_128_equals(box_guid, metadata.guid)) {
+               /* unwanted mailbox */
+               return 0;
+       }
+       if (dsync_mailbox_tree_add_exists_node(tree, info, &node) < 0)
+               return -1;
+       memcpy(node->mailbox_guid, metadata.guid,
+              sizeof(node->mailbox_guid));
+       node->uid_validity = status.uidvalidity;
+       node->uid_next = status.uidnext;
        return 0;
 }
 
@@ -235,7 +253,8 @@ dsync_mailbox_tree_fix_guid_duplicate(struct dsync_mailbox_tree *tree,
 }
 
 int dsync_mailbox_tree_fill(struct dsync_mailbox_tree *tree,
-                           struct mail_namespace *ns, const char *box_name)
+                           struct mail_namespace *ns, const char *box_name,
+                           const guid_128_t box_guid)
 {
        const enum mailbox_list_iter_flags list_flags =
                /* FIXME: we'll skip symlinks, because we can't handle them
@@ -267,7 +286,7 @@ int dsync_mailbox_tree_fill(struct dsync_mailbox_tree *tree,
        /* 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) {
-               if (dsync_mailbox_tree_add(tree, info) < 0)
+               if (dsync_mailbox_tree_add(tree, info, box_guid) < 0)
                        ret = -1;
        }
        if (mailbox_list_iter_deinit(&iter) < 0) {
index 0e35c9913655015f780baf369037702d8a27994f..58e4531c1f089a8cd9442c6fa5721c94ab6bd3bb 100644 (file)
@@ -121,10 +121,11 @@ const char *dsync_mailbox_node_get_full_name(const struct dsync_mailbox_tree *tr
 void dsync_mailbox_node_copy_data(struct dsync_mailbox_node *dest,
                                  const struct dsync_mailbox_node *src);
 
-/* Add nodes to tree from the given namespace. If box_name is non-NULL,
-   add only that mailbox to the tree. */
+/* Add nodes to tree from the given namespace. If box_name or box_guid is
+   non-NULL, add only that mailbox to the tree. */
 int dsync_mailbox_tree_fill(struct dsync_mailbox_tree *tree,
-                           struct mail_namespace *ns, const char *box_name);
+                           struct mail_namespace *ns, const char *box_name,
+                           const guid_128_t box_guid);
 
 /* Return all known deleted mailboxes and directories. */
 const struct dsync_mailbox_delete *