]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
[m]dbox: Fixes to rebuilding a broken index.
authorTimo Sirainen <tss@iki.fi>
Tue, 2 Mar 2010 14:12:44 +0000 (16:12 +0200)
committerTimo Sirainen <tss@iki.fi>
Tue, 2 Mar 2010 14:12:44 +0000 (16:12 +0200)
--HG--
branch : HEAD

src/lib-storage/index/dbox-common/dbox-sync-rebuild.c
src/lib-storage/index/dbox-multi/mdbox-storage-rebuild.c

index fa7fb9ca13066a2c2c64aab967c0987c25acbe65..98d3608f31881dffdc6dea4874f7bf7b1c2f6df2 100644 (file)
@@ -2,6 +2,7 @@
 
 #include "lib.h"
 #include "array.h"
+#include "mail-index-modseq.h"
 #include "index-storage.h"
 #include "dbox-storage.h"
 #include "dbox-sync-rebuild.h"
@@ -50,6 +51,7 @@ dbox_sync_index_copy_from_old(struct dbox_sync_rebuild_context *ctx,
        const struct mail_index_record *rec;
        ARRAY_TYPE(keyword_indexes) old_keywords;
        struct mail_keywords *kw;
+       uint64_t modseq;
 
        /* copy flags */
        rec = mail_index_lookup(view, old_seq);
@@ -63,6 +65,10 @@ dbox_sync_index_copy_from_old(struct dbox_sync_rebuild_context *ctx,
        mail_index_update_keywords(ctx->trans, new_seq, MODIFY_REPLACE, kw);
        mail_index_keywords_unref(&kw);
 
+       /* copy modseq */
+       modseq = mail_index_modseq_lookup(view, old_seq);
+       mail_index_update_modseq(ctx->trans, new_seq, modseq);
+
        dbox_sync_index_copy_cache(ctx, view, old_seq, new_seq);
 }
 
@@ -83,6 +89,47 @@ void dbox_sync_rebuild_index_metadata(struct dbox_sync_rebuild_context *ctx,
        }
 }
 
+static void dbox_sync_rebuild_header(struct dbox_sync_rebuild_context *ctx)
+{
+       const struct mail_index_header *hdr, *backup_hdr;
+       uint32_t uid_validity, next_uid;
+
+       hdr = mail_index_get_header(ctx->view);
+       backup_hdr = ctx->backup_view == NULL ? NULL :
+               mail_index_get_header(ctx->backup_view);
+
+       /* set uidvalidity */
+       if (hdr->uid_validity != 0)
+               uid_validity = hdr->uid_validity;
+       else if (backup_hdr != NULL && backup_hdr->uid_validity != 0)
+               uid_validity = backup_hdr->uid_validity;
+       else
+               uid_validity = dbox_get_uidvalidity_next(ctx->box->list);
+       mail_index_update_header(ctx->trans,
+               offsetof(struct mail_index_header, uid_validity),
+               &uid_validity, sizeof(uid_validity), TRUE);
+
+       /* set next-uid */
+       if (hdr->next_uid != 0)
+               next_uid = hdr->next_uid;
+       else if (backup_hdr != NULL && backup_hdr->next_uid != 0)
+               next_uid = backup_hdr->next_uid;
+       else
+               next_uid = dbox_get_uidvalidity_next(ctx->box->list);
+       mail_index_update_header(ctx->trans,
+                                offsetof(struct mail_index_header, next_uid),
+                                &next_uid, sizeof(next_uid), TRUE);
+
+       /* set highest-modseq */
+       mail_index_update_highest_modseq(ctx->trans,
+               mail_index_modseq_get_highest(ctx->view));
+       if (ctx->backup_view != NULL) {
+               mail_index_update_highest_modseq(ctx->trans,
+                       mail_index_modseq_get_highest(ctx->backup_view));
+
+       }
+}
+
 struct dbox_sync_rebuild_context *
 dbox_sync_index_rebuild_init(struct mailbox *box,
                             struct mail_index_view *view,
@@ -123,6 +170,7 @@ void dbox_sync_index_rebuild_deinit(struct dbox_sync_rebuild_context **_ctx)
        struct dbox_sync_rebuild_context *ctx = *_ctx;
 
        *_ctx = NULL;
+       dbox_sync_rebuild_header(ctx);
        if (ctx->backup_index != NULL) {
                mail_index_view_close(&ctx->backup_view);
                mail_index_close(ctx->backup_index);
index 51c4f68f1d632987fdb3605551344863ce7cb962..20721ac990481e29fbad34874ba9ca5b6eefdbb3 100644 (file)
@@ -392,6 +392,49 @@ rebuild_mailbox_multi(struct mdbox_storage_rebuild_context *ctx,
        }
 }
 
+static void
+mdbox_rebuild_get_header(struct mail_index_view *view, uint32_t hdr_ext_id,
+                        struct mdbox_index_header *hdr_r)
+{
+       const void *data;
+       size_t data_size;
+
+       mail_index_get_header_ext(view, hdr_ext_id, &data, &data_size);
+       memset(hdr_r, 0, sizeof(*hdr_r));
+       memcpy(hdr_r, data, I_MIN(data_size, sizeof(*hdr_r)));
+}
+
+static void mdbox_header_update(struct dbox_sync_rebuild_context *rebuild_ctx,
+                               struct mdbox_mailbox *mbox)
+{
+       struct mdbox_index_header hdr, backup_hdr;
+
+       mdbox_rebuild_get_header(rebuild_ctx->view, mbox->hdr_ext_id, &hdr);
+       if (rebuild_ctx->backup_view == NULL)
+               memset(&backup_hdr, 0, sizeof(backup_hdr));
+       else {
+               mdbox_rebuild_get_header(rebuild_ctx->backup_view,
+                                        mbox->hdr_ext_id, &backup_hdr);
+       }
+
+       /* make sure we have valid mailbox guid */
+       if (mail_guid_128_is_empty(hdr.mailbox_guid)) {
+               if (!mail_guid_128_is_empty(backup_hdr.mailbox_guid)) {
+                       memcpy(hdr.mailbox_guid, backup_hdr.mailbox_guid,
+                              sizeof(hdr.mailbox_guid));
+               } else {
+                       mail_generate_guid_128(hdr.mailbox_guid);
+               }
+       }
+
+       /* update map's uid-validity */
+       hdr.map_uid_validity = dbox_map_get_uid_validity(mbox->storage->map);
+
+       /* and write changes */
+       mail_index_update_header_ext(rebuild_ctx->trans, mbox->hdr_ext_id, 0,
+                                    &hdr, sizeof(hdr));
+}
+
 static int
 rebuild_mailbox(struct mdbox_storage_rebuild_context *ctx,
                struct mail_namespace *ns, const char *name)
@@ -429,6 +472,7 @@ rebuild_mailbox(struct mdbox_storage_rebuild_context *ctx,
        }
 
        rebuild_ctx = dbox_sync_index_rebuild_init(&mbox->box, view, trans);
+       mdbox_header_update(rebuild_ctx, mbox);
        rebuild_mailbox_multi(ctx, rebuild_ctx, mbox, view, trans);
        dbox_sync_index_rebuild_deinit(&rebuild_ctx);