From: Timo Sirainen Date: Tue, 29 Jun 2010 19:21:51 +0000 (+0100) Subject: single-dbox: Fixed broken mailbox handling. X-Git-Tag: 2.0.rc1~60 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=e5fb952c6d49d3b6bff1746551566202e92947da;p=thirdparty%2Fdovecot%2Fcore.git single-dbox: Fixed broken mailbox handling. --HG-- branch : HEAD --- diff --git a/src/lib-storage/index/dbox-single/sdbox-storage.c b/src/lib-storage/index/dbox-single/sdbox-storage.c index 78990a4beb..c5a1e05b29 100644 --- a/src/lib-storage/index/dbox-single/sdbox-storage.c +++ b/src/lib-storage/index/dbox-single/sdbox-storage.c @@ -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, diff --git a/src/lib-storage/index/dbox-single/sdbox-storage.h b/src/lib-storage/index/dbox-single/sdbox-storage.h index a2c0ff3b22..02438c25db 100644 --- a/src/lib-storage/index/dbox-single/sdbox-storage.h +++ b/src/lib-storage/index/dbox-single/sdbox-storage.h @@ -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; }; diff --git a/src/lib-storage/index/dbox-single/sdbox-sync-rebuild.c b/src/lib-storage/index/dbox-single/sdbox-sync-rebuild.c index 1041ecceaa..34ca509f24 100644 --- a/src/lib-storage/index/dbox-single/sdbox-sync-rebuild.c +++ b/src/lib-storage/index/dbox-single/sdbox-sync-rebuild.c @@ -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; } diff --git a/src/lib-storage/index/dbox-single/sdbox-sync.c b/src/lib-storage/index/dbox-single/sdbox-sync.c index 2b599d4308..d6334a0221 100644 --- a/src/lib-storage/index/dbox-single/sdbox-sync.c +++ b/src/lib-storage/index/dbox-single/sdbox-sync.c @@ -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); diff --git a/src/lib-storage/index/dbox-single/sdbox-sync.h b/src/lib-storage/index/dbox-single/sdbox-sync.h index 10116674ae..880410df49 100644 --- a/src/lib-storage/index/dbox-single/sdbox-sync.h +++ b/src/lib-storage/index/dbox-single/sdbox-sync.h @@ -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);