]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
doveadm: Implemented force-resync functionality.
authorTimo Sirainen <tss@iki.fi>
Fri, 10 Apr 2009 18:10:39 +0000 (14:10 -0400)
committerTimo Sirainen <tss@iki.fi>
Fri, 10 Apr 2009 18:10:39 +0000 (14:10 -0400)
--HG--
branch : HEAD

src/lib-storage/index/dbox/dbox-sync.c
src/lib-storage/index/dbox/dbox-sync.h
src/lib-storage/index/maildir/maildir-sync.c
src/lib-storage/index/mbox/mbox-sync.c
src/lib-storage/mail-storage.c
src/lib-storage/mail-storage.h
src/util/doveadm.c

index 24dbb25f76781bc323474a248cbdcc11be031f61..fe86c76d06e5275e6de048df98699c9a1199c392 100644 (file)
@@ -219,7 +219,8 @@ int dbox_sync_begin(struct dbox_mailbox *mbox, enum dbox_sync_flags flags,
        int ret;
        bool rebuild, storage_rebuilt = FALSE;
 
-       rebuild = dbox_refresh_header(mbox) < 0;
+       rebuild = dbox_refresh_header(mbox) < 0 ||
+               (flags & DBOX_SYNC_FLAG_FORCE_REBUILD) != 0;
        if (rebuild) {
                if (dbox_storage_rebuild(mbox->storage) < 0)
                        return -1;
@@ -322,11 +323,11 @@ int dbox_sync_finish(struct dbox_sync_context **_ctx, bool success)
        return ret;
 }
 
-int dbox_sync(struct dbox_mailbox *mbox)
+int dbox_sync(struct dbox_mailbox *mbox, enum dbox_sync_flags flags)
 {
        struct dbox_sync_context *sync_ctx;
 
-       if (dbox_sync_begin(mbox, 0, &sync_ctx) < 0)
+       if (dbox_sync_begin(mbox, flags, &sync_ctx) < 0)
                return -1;
 
        if (sync_ctx == NULL)
@@ -338,14 +339,18 @@ struct mailbox_sync_context *
 dbox_storage_sync_init(struct mailbox *box, enum mailbox_sync_flags flags)
 {
        struct dbox_mailbox *mbox = (struct dbox_mailbox *)box;
+       enum dbox_sync_flags dbox_sync_flags = 0;
        int ret = 0;
 
        if (!box->opened)
                index_storage_mailbox_open(&mbox->ibox);
 
        if (index_mailbox_want_full_sync(&mbox->ibox, flags) ||
-           mbox->storage->sync_rebuild)
-               ret = dbox_sync(mbox);
+           mbox->storage->sync_rebuild) {
+               if ((flags & MAILBOX_SYNC_FLAG_FORCE_RESYNC) != 0)
+                       dbox_sync_flags |= DBOX_SYNC_FLAG_FORCE_REBUILD;
+               ret = dbox_sync(mbox, dbox_sync_flags);
+       }
 
        return index_mailbox_sync_init(box, flags, ret < 0);
 }
index 439e1f770a222f695f7924f5f8ffa28c774a8b2f..90f8c287cc65150b2b12d4c29730fe06afc8b3e8 100644 (file)
@@ -5,8 +5,9 @@ struct mailbox;
 struct dbox_mailbox;
 
 enum dbox_sync_flags {
-       DBOX_SYNC_FLAG_FORCE    = 0x01,
-       DBOX_SYNC_FLAG_FSYNC    = 0x02
+       DBOX_SYNC_FLAG_FORCE            = 0x01,
+       DBOX_SYNC_FLAG_FSYNC            = 0x02,
+       DBOX_SYNC_FLAG_FORCE_REBUILD    = 0x04
 };
 
 struct dbox_sync_file_entry {
@@ -35,7 +36,7 @@ struct dbox_sync_context {
 int dbox_sync_begin(struct dbox_mailbox *mbox, enum dbox_sync_flags flags,
                    struct dbox_sync_context **ctx_r);
 int dbox_sync_finish(struct dbox_sync_context **ctx, bool success);
-int dbox_sync(struct dbox_mailbox *mbox);
+int dbox_sync(struct dbox_mailbox *mbox, enum dbox_sync_flags flags);
 
 int dbox_sync_purge(struct mail_storage *storage);
 int dbox_sync_file(struct dbox_sync_context *ctx,
index e197050d8fdcb9731446f2c5401c03bf63c06566..c7ef7ab088f9a4f1e0e624584c7e98959281e054 100644 (file)
@@ -893,16 +893,17 @@ maildir_storage_sync_init(struct mailbox *box, enum mailbox_sync_flags flags)
 {
        struct maildir_mailbox *mbox = (struct maildir_mailbox *)box;
        struct maildir_sync_context *ctx;
-       bool lost_files;
+       bool lost_files, force_resync;
        int ret = 0;
 
        if (!box->opened)
                index_storage_mailbox_open(&mbox->ibox);
 
+       force_resync = (flags & MAILBOX_SYNC_FLAG_FORCE_RESYNC) != 0;
        if (index_mailbox_want_full_sync(&mbox->ibox, flags)) {
                T_BEGIN {
                        ctx = maildir_sync_context_new(mbox, flags);
-                       ret = maildir_sync_context(ctx, FALSE, NULL,
+                       ret = maildir_sync_context(ctx, force_resync, NULL,
                                                   &lost_files);
                        maildir_sync_deinit(ctx);
                } T_END;
index 64c4acafcf238466e3294d1b3eaac22a4efbb2e5..ec123f57bf6a6d2d3e69b71fe71b89410a0cf45d 100644 (file)
@@ -1929,6 +1929,11 @@ mbox_storage_sync_init(struct mailbox *box, enum mailbox_sync_flags flags)
                        mbox_sync_flags |= MBOX_SYNC_UNDIRTY;
                if ((flags & MAILBOX_SYNC_FLAG_FULL_WRITE) != 0)
                        mbox_sync_flags |= MBOX_SYNC_REWRITE;
+               if ((flags & MAILBOX_SYNC_FLAG_FORCE_RESYNC) != 0) {
+                       mbox_sync_flags |= MBOX_SYNC_UNDIRTY |
+                               MBOX_SYNC_REWRITE | MBOX_SYNC_FORCE_SYNC;
+               }
+
                ret = mbox_sync(mbox, mbox_sync_flags);
        }
 
index 866f405c32e63d13ed4f3e0626ec1081d7cdb48f..86ed2c4174077b996f98eb007ff1483b7fff2069 100644 (file)
@@ -346,7 +346,8 @@ const char *mail_storage_get_last_error(struct mail_storage *storage,
           error. If storage->error is NONE, it means we forgot to set it at
           some point.. */
        if (storage->error == MAIL_ERROR_NONE) {
-               *error_r = MAIL_ERROR_TEMP;
+               if (error_r != NULL)
+                       *error_r = MAIL_ERROR_TEMP;
                return storage->error_string != NULL ? storage->error_string :
                        "BUG: Unknown internal error";
        }
@@ -358,7 +359,8 @@ const char *mail_storage_get_last_error(struct mail_storage *storage,
                                        storage->error);
        }
 
-       *error_r = storage->error;
+       if (error_r != NULL)
+               *error_r = storage->error;
        return storage->error_string;
 }
 
index af1b82b929dbf48f77b1b5505870f125d2f0aaf3..06b662d22cc9b4bf4540e58a49fd0bdab523912f 100644 (file)
@@ -151,7 +151,9 @@ enum mailbox_sync_flags {
        MAILBOX_SYNC_FLAG_FIX_INCONSISTENT      = 0x40,
        /* Syncing after an EXPUNGE command. This is just an informational
           flag for plugins. */
-       MAILBOX_SYNC_FLAG_EXPUNGE               = 0x80
+       MAILBOX_SYNC_FLAG_EXPUNGE               = 0x80,
+       /* Force doing a full resync of indexes. */
+       MAILBOX_SYNC_FLAG_FORCE_RESYNC          = 0x100
 };
 
 enum mailbox_sync_type {
index f0d6bb10e3ce2d1b70cb23b47d5573f3c7e06338..1ce8a37ac7314a809c91cbc697691a29c92d65fa 100644 (file)
@@ -16,21 +16,66 @@ static struct mail_user *mail_user;
 static void ATTR_NORETURN
 usage(void)
 {
-       i_fatal("usage: doveadm purge <user>\n");
+       i_fatal(
+"usage: doveadm \n"
+"  purge <user>\n"
+"  force-resync <user> <mailbox>\n"
+);
 }
 
-static int cmd_purge(struct mail_user *user)
+static void cmd_purge(struct mail_user *user)
 {
        struct mail_namespace *ns;
-       int ret = 0;
 
        for (ns = user->namespaces; ns != NULL; ns = ns->next) {
-               if (ns->type == NAMESPACE_PRIVATE && ns->alias_for == NULL) {
-                       if (mail_storage_purge(ns->storage) < 0)
-                               ret = -1;
+               if (ns->type != NAMESPACE_PRIVATE || ns->alias_for != NULL)
+                       continue;
+
+               if (mail_storage_purge(ns->storage) < 0) {
+                       i_error("Purging namespace '%s' failed: %s", ns->prefix,
+                               mail_storage_get_last_error(ns->storage, NULL));
                }
        }
-       return ret;
+}
+
+static struct mailbox *
+mailbox_find_and_open(struct mail_user *user, const char *mailbox)
+{
+       struct mail_namespace *ns;
+       struct mail_storage *storage;
+       struct mailbox *box;
+       const char *orig_mailbox = mailbox;
+
+       ns = mail_namespace_find(user->namespaces, &mailbox);
+       if (ns == NULL)
+               i_fatal("Can't find namespace for mailbox %s", mailbox);
+
+       storage = ns->storage;
+       box = mailbox_open(&storage, mailbox, NULL, MAILBOX_OPEN_KEEP_RECENT |
+                          MAILBOX_OPEN_IGNORE_ACLS);
+       if (box == NULL) {
+               i_fatal("Opening mailbox %s failed: %s", orig_mailbox,
+                       mail_storage_get_last_error(storage, NULL));
+       }
+       return box;
+}
+
+static void cmd_force_resync(struct mail_user *user, const char *mailbox)
+{
+       struct mail_storage *storage;
+       struct mailbox *box;
+
+       if (mailbox == NULL)
+               usage();
+
+       box = mailbox_find_and_open(user, mailbox);
+       storage = mailbox_get_storage(box);
+       if (mailbox_sync(box, MAILBOX_SYNC_FLAG_FORCE_RESYNC |
+                        MAILBOX_SYNC_FLAG_FIX_INCONSISTENT, 0, NULL) < 0) {
+               i_fatal("Forcing a resync on mailbox %s failed: %s", mailbox,
+                       mail_storage_get_last_error(storage, NULL));
+       }
+       mailbox_close(&box);
 }
 
 int main(int argc, char *argv[])
@@ -38,7 +83,7 @@ int main(int argc, char *argv[])
        enum mail_storage_service_flags service_flags = 0;
        struct master_service *service;
        const char *getopt_str, *user;
-       int c, ret = 0;
+       int c;
 
        service = master_service_init("doveadm", MASTER_SERVICE_FLAG_STANDALONE,
                                      argc, argv);
@@ -71,12 +116,14 @@ int main(int argc, char *argv[])
                                             mail_user->username));
 
        if (strcmp(argv[optind], "purge") == 0)
-               ret = cmd_purge(mail_user);
+               cmd_purge(mail_user);
+       else if (strcmp(argv[optind], "force-resync") == 0)
+               cmd_force_resync(mail_user, argv[optind+2]);
        else
                usage();
 
        mail_user_unref(&mail_user);
        mail_storage_service_deinit_user();
        master_service_deinit(&service);
-       return ret < 0 ? 1 : 0;
+       return 0;
 }