# HG changeset patch # User Timo Sirainen # Date 1194121996 -7200 # Node ID 715ef6f98f440c01e3080e1a3c55f957760af1ad # Parent 90196328bcce0aa20720eda4cc9c57475bb0af96 Use the flags, keywords and cache from old index even when rebuilding dbox. diff -r 90196328bcce -r 715ef6f98f44 src/lib-storage/index/dbox/dbox-sync-rebuild.c --- a/src/lib-storage/index/dbox/dbox-sync-rebuild.c Sat Nov 03 22:32:33 2007 +0200 +++ b/src/lib-storage/index/dbox/dbox-sync-rebuild.c Sat Nov 03 22:33:16 2007 +0200 @@ -15,10 +15,16 @@ struct dbox_sync_rebuild_context { struct dbox_mailbox *mbox; struct dbox_index_append_context *append_ctx; + + struct mail_index_view *view; struct mail_index_transaction *trans; + uint32_t cache_ext_id; + uint32_t cache_reset_id; struct maildir_uidlist *maildir_uidlist; struct maildir_keywords *mk; + + unsigned int cache_used:1; }; static int dbox_sync_set_uidvalidity(struct dbox_sync_rebuild_context *ctx) @@ -35,14 +41,81 @@ return 0; } -static void dbox_sync_index_metadata(struct dbox_sync_rebuild_context *ctx, - struct dbox_file *file, uint32_t seq) +static void +dbox_sync_index_copy_cache(struct dbox_sync_rebuild_context *ctx, + uint32_t old_seq, uint32_t new_seq) +{ + struct mail_index_map *map; + const void *data; + uint32_t reset_id; + bool expunged; + + if (ctx->cache_ext_id == (uint32_t)-1) + return; + + mail_index_lookup_ext_full(ctx->view, old_seq, ctx->cache_ext_id, + &map, &data, &expunged); + if (expunged) + return; + + if (!mail_index_ext_get_reset_id(ctx->view, map, ctx->cache_ext_id, + &reset_id)) + return; + + if (!ctx->cache_used) { + /* set reset id */ + ctx->cache_used = TRUE; + ctx->cache_reset_id = reset_id; + mail_index_ext_reset(ctx->trans, ctx->cache_ext_id, + ctx->cache_reset_id); + } + if (ctx->cache_reset_id == reset_id) { + mail_index_update_ext(ctx->trans, new_seq, + ctx->cache_ext_id, data, NULL); + } +} + +static void +dbox_sync_index_copy_from_old(struct dbox_sync_rebuild_context *ctx, + uint32_t old_seq, uint32_t new_seq) +{ + struct mail_index *index = mail_index_view_get_index(ctx->view); + const struct mail_index_record *rec; + ARRAY_TYPE(keyword_indexes) old_keywords; + struct mail_keywords *kw; + + /* copy flags */ + rec = mail_index_lookup(ctx->view, old_seq); + mail_index_update_flags(ctx->trans, new_seq, + MODIFY_REPLACE, rec->flags); + + /* copy keywords */ + t_array_init(&old_keywords, 32); + mail_index_lookup_keywords(ctx->view, old_seq, &old_keywords); + kw = mail_index_keywords_create_from_indexes(index, &old_keywords); + mail_index_update_keywords(ctx->trans, new_seq, MODIFY_REPLACE, kw); + mail_index_keywords_free(&kw); + + dbox_sync_index_copy_cache(ctx, old_seq, new_seq); +} + +static void +dbox_sync_index_metadata(struct dbox_sync_rebuild_context *ctx, + struct dbox_file *file, uint32_t seq, uint32_t uid) { const char *value; struct mail_keywords *keywords; enum mail_flags flags = 0; + uint32_t old_seq; unsigned int i; + if (mail_index_lookup_seq(ctx->view, uid, &old_seq)) { + /* the message exists in the old index. + copy the metadata from it. */ + dbox_sync_index_copy_from_old(ctx, old_seq, seq); + return; + } + value = dbox_file_metadata_get(file, DBOX_METADATA_FLAGS); if (value != NULL) { for (i = 0; value[i] != '\0'; i++) { @@ -115,7 +188,7 @@ if (!expunged) { mail_index_append(ctx->trans, uid, &seq); file->maildir_append_seq = seq; - dbox_sync_index_metadata(ctx, file, seq); + dbox_sync_index_metadata(ctx, file, seq, uid); } return 1; } @@ -257,10 +330,20 @@ } } +static void +dbox_index_update_cache_header(struct dbox_sync_rebuild_context *ctx) +{ + const void *data; + size_t size; + + mail_index_get_header_ext(ctx->view, ctx->cache_ext_id, &data, &size); + mail_index_update_header_ext(ctx->trans, ctx->cache_ext_id, + 0, data, size); +} + int dbox_sync_index_rebuild(struct dbox_mailbox *mbox) { struct dbox_sync_rebuild_context ctx; - struct mail_index_view *view; uint32_t seq; uoff_t offset; int ret; @@ -268,14 +351,17 @@ memset(&ctx, 0, sizeof(ctx)); ctx.mbox = mbox; ctx.append_ctx = dbox_index_append_begin(mbox->dbox_index); - view = mail_index_view_open(mbox->ibox.index); - ctx.trans = mail_index_transaction_begin(view, + ctx.view = mail_index_view_open(mbox->ibox.index); + ctx.trans = mail_index_transaction_begin(ctx.view, MAIL_INDEX_TRANSACTION_FLAG_EXTERNAL); mail_index_reset(ctx.trans); + mail_index_ext_lookup(mbox->ibox.index, "cache", &ctx.cache_ext_id); if ((ret = dbox_sync_index_rebuild_ctx(&ctx)) < 0) mail_index_transaction_rollback(&ctx.trans); else { + if (ctx.cache_used) + dbox_index_update_cache_header(&ctx); ret = dbox_index_append_assign_file_ids(ctx.append_ctx); if (ret == 0) { dbox_sync_update_maildir_ids(&ctx); @@ -283,7 +369,7 @@ &seq, &offset); } } - mail_index_view_close(&view); + mail_index_view_close(&ctx.view); if (ret == 0) ret = dbox_index_append_commit(&ctx.append_ctx); diff -r 90196328bcce -r 715ef6f98f44 src/lib-storage/index/dbox/dbox-sync.c --- a/src/lib-storage/index/dbox/dbox-sync.c Sat Nov 03 22:32:33 2007 +0200 +++ b/src/lib-storage/index/dbox/dbox-sync.c Sat Nov 03 22:33:16 2007 +0200 @@ -147,9 +147,17 @@ static void dbox_sync_update_header(struct dbox_sync_context *ctx) { struct dbox_index_header hdr; + const void *data; + size_t data_size; - if (!ctx->flush_dirty_flags) - return; + if (!ctx->flush_dirty_flags) { + /* write the header if it doesn't exist yet */ + mail_index_get_header_ext(ctx->mbox->ibox.view, + ctx->mbox->dbox_hdr_ext_id, + &data, &data_size); + if (data_size != 0) + return; + } hdr.last_dirty_flush_stamp = ioloop_time; mail_index_update_header_ext(ctx->trans, ctx->mbox->dbox_hdr_ext_id, 0, @@ -224,8 +232,8 @@ return ret; } -static bool dbox_sync_want_flush_dirty(struct dbox_mailbox *mbox, - bool close_flush_dirty_flags) +static int dbox_sync_want_flush_dirty(struct dbox_mailbox *mbox, + bool close_flush_dirty_flags) { const struct dbox_index_header *hdr; const void *data; @@ -233,29 +241,30 @@ if (mbox->last_interactive_change < ioloop_time - DBOX_FLUSH_SECS_INTERACTIVE) - return TRUE; + return 1; mail_index_get_header_ext(mbox->ibox.view, mbox->dbox_hdr_ext_id, &data, &data_size); - if (data_size == 0 || data_size != sizeof(*hdr)) { + if (data_size != sizeof(*hdr)) { + /* data_size=0 means it's never been synced as dbox */ if (data_size != 0) { i_warning("dbox %s: Invalid dbox header size", mbox->path); } - return TRUE; + return -1; } hdr = data; if (!close_flush_dirty_flags) { if (hdr->last_dirty_flush_stamp < ioloop_time - DBOX_FLUSH_SECS_IMMEDIATE) - return TRUE; + return 1; } else { if (hdr->last_dirty_flush_stamp < ioloop_time - DBOX_FLUSH_SECS_CLOSE) - return TRUE; + return 1; } - return FALSE; + return 0; } int dbox_sync_begin(struct dbox_mailbox *mbox, @@ -267,9 +276,13 @@ enum mail_index_sync_flags sync_flags = 0; unsigned int i; int ret; + bool rebuild = FALSE; - if (dbox_sync_want_flush_dirty(mbox, close_flush_dirty_flags)) + ret = dbox_sync_want_flush_dirty(mbox, close_flush_dirty_flags); + if (ret > 0) sync_flags |= MAIL_INDEX_SYNC_FLAG_FLUSH_DIRTY; + else if (ret < 0) + rebuild = TRUE; else { if (close_flush_dirty_flags) { /* no need to sync */ @@ -298,8 +311,13 @@ return -1; } - if ((ret = dbox_sync_index(ctx)) > 0) - break; + if (rebuild) { + ret = 0; + rebuild = FALSE; + } else { + if ((ret = dbox_sync_index(ctx)) > 0) + break; + } /* failure. keep the index locked while we're doing a rebuild. */