]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
single-dbox: Fixed broken mailbox handling.
authorTimo Sirainen <tss@iki.fi>
Tue, 29 Jun 2010 19:21:51 +0000 (20:21 +0100)
committerTimo Sirainen <tss@iki.fi>
Tue, 29 Jun 2010 19:21:51 +0000 (20:21 +0100)
--HG--
branch : HEAD

src/lib-storage/index/dbox-single/sdbox-storage.c
src/lib-storage/index/dbox-single/sdbox-storage.h
src/lib-storage/index/dbox-single/sdbox-sync-rebuild.c
src/lib-storage/index/dbox-single/sdbox-sync.c
src/lib-storage/index/dbox-single/sdbox-sync.h

index 78990a4beb79347f70fd818eca8a45df3d9eb1bf..c5a1e05b2945e888146be1ec3293849f8c8d06f0 100644 (file)
@@ -84,10 +84,13 @@ sdbox_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
 int sdbox_read_header(struct sdbox_mailbox *mbox,
                      struct sdbox_index_header *hdr, bool log_error)
 {
+       struct mail_index_view *view;
        const void *data;
        size_t data_size;
+       int ret;
 
-       mail_index_get_header_ext(mbox->box.view, mbox->hdr_ext_id,
+       view = mail_index_view_open(mbox->box.index);
+       mail_index_get_header_ext(view, mbox->hdr_ext_id,
                                  &data, &data_size);
        if (data_size < SDBOX_INDEX_HEADER_MIN_SIZE &&
            (!mbox->creating || data_size != 0)) {
@@ -97,11 +100,14 @@ int sdbox_read_header(struct sdbox_mailbox *mbox,
                                "dbox %s: Invalid dbox header size",
                                mbox->box.path);
                }
-               return -1;
+               ret = -1;
+       } else {
+               memset(hdr, 0, sizeof(*hdr));
+               memcpy(hdr, data, I_MIN(data_size, sizeof(*hdr)));
+               ret = 0;
        }
-       memset(hdr, 0, sizeof(*hdr));
-       memcpy(hdr, data, I_MIN(data_size, sizeof(*hdr)));
-       return 0;
+       mail_index_view_close(&view);
+       return ret;
 }
 
 void sdbox_update_header(struct sdbox_mailbox *mbox,
@@ -198,9 +204,15 @@ static int sdbox_mailbox_create_indexes(struct mailbox *box,
        return ret;
 }
 
-static void sdbox_set_mailbox_corrupted(struct mailbox *box ATTR_UNUSED)
+static void sdbox_set_mailbox_corrupted(struct mailbox *box)
 {
-       /* FIXME */
+       struct sdbox_mailbox *mbox = (struct sdbox_mailbox *)box;
+       struct sdbox_index_header hdr;
+
+       if (sdbox_read_header(mbox, &hdr, TRUE) < 0 || hdr.rebuild_count == 0)
+               mbox->corrupted_rebuild_count = 1;
+       else
+               mbox->corrupted_rebuild_count = hdr.rebuild_count;
 }
 
 static void sdbox_set_file_corrupted(struct dbox_file *_file)
@@ -210,6 +222,15 @@ static void sdbox_set_file_corrupted(struct dbox_file *_file)
        sdbox_set_mailbox_corrupted(&file->mbox->box);
 }
 
+static void sdbox_mailbox_close(struct mailbox *box)
+{
+       struct sdbox_mailbox *mbox = (struct sdbox_mailbox *)box;
+
+       if (mbox->corrupted_rebuild_count != 0)
+               (void)sdbox_sync(mbox, 0);
+       index_storage_mailbox_close(box);
+}
+
 static int
 sdbox_mailbox_get_guid(struct mailbox *box, uint8_t guid[MAIL_GUID_128_SIZE])
 {
@@ -264,7 +285,7 @@ struct mailbox sdbox_mailbox = {
                index_storage_allow_new_keywords,
                index_storage_mailbox_enable,
                dbox_mailbox_open,
-               index_storage_mailbox_close,
+               sdbox_mailbox_close,
                index_storage_mailbox_free,
                dbox_mailbox_create,
                dbox_mailbox_update,
index a2c0ff3b22135aaa4cfbed7b69a86f46a3998325..02438c25dbf1ab52d0a9b5395ca9916664b2fd59 100644 (file)
@@ -10,7 +10,8 @@
 
 #define SDBOX_INDEX_HEADER_MIN_SIZE (sizeof(uint32_t))
 struct sdbox_index_header {
-       uint32_t oldv1_highest_maildir_uid;
+       /* increased every time a full mailbox rebuild is done */
+       uint32_t rebuild_count;
        uint8_t mailbox_guid[MAIL_GUID_128_SIZE];
 };
 
@@ -23,6 +24,9 @@ struct sdbox_mailbox {
        struct sdbox_storage *storage;
 
        uint32_t hdr_ext_id;
+       /* if non-zero, storage should be rebuilt (except if rebuild_count
+          has changed from this value) */
+       uint32_t corrupted_rebuild_count;
 
        unsigned int creating:1;
 };
index 1041ecceaa12433bc4e575c6bd5a96bf138950e9..34ca509f247dd8547e58f380cf8be92513da3d6f 100644 (file)
@@ -36,12 +36,16 @@ static int sdbox_sync_add_file_index(struct dbox_sync_rebuild_context *ctx,
                        return 0;
                ret = dbox_file_get_mail_stream(file, 0, NULL);
        }
+       if (ret == 0) {
+               if ((ret = dbox_file_fix(file, 0)) == 0)
+                       ret = dbox_file_get_mail_stream(file, 0, NULL);
+       }
 
        if (ret <= 0) {
                if (ret < 0)
                        return -1;
 
-               i_warning("dbox: Ignoring broken file: %s", file->cur_path);
+               i_warning("dbox: Skipping unfixable file: %s", file->cur_path);
                return 0;
        }
 
@@ -132,6 +136,8 @@ static void sdbox_sync_update_header(struct dbox_sync_rebuild_context *ctx)
                memset(&hdr, 0, sizeof(hdr));
        if (!mail_guid_128_is_empty(hdr.mailbox_guid))
                mail_generate_guid_128(hdr.mailbox_guid);
+       if (++hdr.rebuild_count == 0)
+               hdr.rebuild_count = 1;
        mail_index_update_header_ext(ctx->trans, mbox->hdr_ext_id, 0,
                                     &hdr, sizeof(hdr));
 }
@@ -154,13 +160,22 @@ sdbox_sync_index_rebuild_singles(struct dbox_sync_rebuild_context *ctx)
        return ret;
 }
 
-int sdbox_sync_index_rebuild(struct sdbox_mailbox *mbox)
+int sdbox_sync_index_rebuild(struct sdbox_mailbox *mbox, bool force)
 {
        struct dbox_sync_rebuild_context *ctx;
        struct mail_index_view *view;
        struct mail_index_transaction *trans;
+       struct sdbox_index_header hdr;
        int ret;
 
+       if (!force && sdbox_read_header(mbox, &hdr, FALSE) == 0) {
+               if (hdr.rebuild_count != mbox->corrupted_rebuild_count &&
+                   hdr.rebuild_count != 0) {
+                       /* already rebuilt by someone else */
+                       return 0;
+               }
+       }
+
        view = mail_index_view_open(mbox->box.index);
        trans = mail_index_transaction_begin(view,
                                        MAIL_INDEX_TRANSACTION_FLAG_EXTERNAL);
@@ -174,5 +189,6 @@ int sdbox_sync_index_rebuild(struct sdbox_mailbox *mbox)
        else
                ret = mail_index_transaction_commit(&trans);
        mail_index_view_close(&view);
+       mbox->corrupted_rebuild_count = 0;
        return ret;
 }
index 2b599d430804371428d745272190df1e2bc144a2..d6334a02212b712f3b86bcf5c03ac704e2ad00e6 100644 (file)
@@ -104,7 +104,6 @@ static int sdbox_sync_index(struct sdbox_sync_context *ctx)
        const struct mail_index_header *hdr;
        struct mail_index_sync_rec sync_rec;
        uint32_t seq1, seq2;
-       int ret = 1;
 
        hdr = mail_index_get_header(ctx->sync_view);
        if (hdr->uid_validity == 0) {
@@ -122,7 +121,7 @@ static int sdbox_sync_index(struct sdbox_sync_context *ctx)
 
        if (box->v.sync_notify != NULL)
                box->v.sync_notify(box, 0, 0);
-       return ret;
+       return 1;
 }
 
 static int
@@ -151,10 +150,12 @@ int sdbox_sync_begin(struct sdbox_mailbox *mbox, enum sdbox_sync_flags flags,
        enum mail_index_sync_flags sync_flags;
        unsigned int i;
        int ret;
-       bool rebuild;
+       bool rebuild, force_rebuild;
 
-       rebuild = sdbox_refresh_header(mbox, TRUE, FALSE) < 0 ||
-               (flags & SDBOX_SYNC_FLAG_FORCE_REBUILD) != 0;
+       force_rebuild = (flags & SDBOX_SYNC_FLAG_FORCE_REBUILD) != 0;
+       rebuild = force_rebuild ||
+               mbox->corrupted_rebuild_count != 0 ||
+               sdbox_refresh_header(mbox, TRUE, FALSE) < 0;
 
        ctx = i_new(struct sdbox_sync_context, 1);
        ctx->mbox = mbox;
@@ -181,8 +182,7 @@ int sdbox_sync_begin(struct sdbox_mailbox *mbox, enum sdbox_sync_flags flags,
                        return ret;
                }
 
-               /* now that we're locked, check again if we want to rebuild. */
-               if (sdbox_refresh_header(mbox, FALSE, TRUE) < 0)
+               if (rebuild)
                        ret = 0;
                else {
                        if ((ret = sdbox_sync_index(ctx)) > 0)
@@ -201,7 +201,9 @@ int sdbox_sync_begin(struct sdbox_mailbox *mbox, enum sdbox_sync_flags flags,
                                /* do a full resync and try again. */
                                i_warning("dbox %s: Rebuilding index",
                                          ctx->mbox->box.path);
-                               ret = sdbox_sync_index_rebuild(mbox);
+                               rebuild = FALSE;
+                               ret = sdbox_sync_index_rebuild(mbox,
+                                                              force_rebuild);
                        }
                }
                mail_index_sync_rollback(&ctx->index_sync_ctx);
index 10116674ae3257d521717dc4597399bf9ef530d3..880410df490f98d728ae81b6b4adb3c58d008bab 100644 (file)
@@ -29,7 +29,7 @@ int sdbox_sync_begin(struct sdbox_mailbox *mbox, enum sdbox_sync_flags flags,
 int sdbox_sync_finish(struct sdbox_sync_context **ctx, bool success);
 int sdbox_sync(struct sdbox_mailbox *mbox, enum sdbox_sync_flags flags);
 
-int sdbox_sync_index_rebuild(struct sdbox_mailbox *mbox);
+int sdbox_sync_index_rebuild(struct sdbox_mailbox *mbox, bool force);
 
 struct mailbox_sync_context *
 sdbox_storage_sync_init(struct mailbox *box, enum mailbox_sync_flags flags);