Mercurial > dovecot > original-hg > dovecot-1.2
changeset 5324:4d3294c59939 HEAD
Fixed desyncing problems with mail index and mailbox list index.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Thu, 15 Mar 2007 15:34:49 +0200 |
parents | 5c8f84bc07b1 |
children | f2a0b8a10086 |
files | src/lib-index/mailbox-list-index-private.h src/lib-index/mailbox-list-index-sync.c src/lib-index/mailbox-list-index.c src/lib-index/mailbox-list-index.h src/lib-storage/list/index-mailbox-list-sync.c src/lib-storage/list/index-mailbox-list.c src/lib-storage/list/index-mailbox-list.h |
diffstat | 7 files changed, 116 insertions(+), 45 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-index/mailbox-list-index-private.h Thu Mar 15 14:04:45 2007 +0200 +++ b/src/lib-index/mailbox-list-index-private.h Thu Mar 15 15:34:49 2007 +0200 @@ -82,7 +82,7 @@ const struct mailbox_list_dir_record *dir, const char *name, const struct mailbox_list_record **rec_r); -int mailbox_list_index_get_dir(struct mailbox_list_index *index, +int mailbox_list_index_get_dir(struct mailbox_list_index_view *view, uint32_t *offset, const struct mailbox_list_dir_record **dir_r); int mailbox_list_index_map(struct mailbox_list_index *index);
--- a/src/lib-index/mailbox-list-index-sync.c Thu Mar 15 14:04:45 2007 +0200 +++ b/src/lib-index/mailbox-list-index-sync.c Thu Mar 15 15:34:49 2007 +0200 @@ -44,12 +44,13 @@ struct mailbox_list_index_sync_ctx { struct mailbox_list_index *index; + struct mailbox_list_index_view *view; pool_t pool; enum mailbox_list_sync_flags flags; const char *sync_path; struct mail_index_sync_ctx *mail_sync_ctx; - struct mail_index_view *view; + struct mail_index_view *mail_view; struct mail_index_transaction *trans; struct mailbox_list_index_header hdr; @@ -96,7 +97,7 @@ size_t max_len; unsigned int i; - if (mailbox_list_index_get_dir(ctx->index, &offset, &dir) < 0) + if (mailbox_list_index_get_dir(ctx->view, &offset, &dir) < 0) return -1; sync_dir = mailbox_list_alloc_sync_dir(ctx, dir->count + @@ -198,7 +199,7 @@ return mailbox_list_index_set_corrupted(ctx->index, "Record with UID=0"); } - if (mail_index_lookup_uid_range(ctx->view, rec->uid, rec->uid, + if (mail_index_lookup_uid_range(ctx->mail_view, rec->uid, rec->uid, &rec->seq, &rec->seq) < 0) return -1; @@ -330,7 +331,7 @@ struct mail_index_sync_rec sync_rec; if (mail_index_sync_begin(ctx->index->mail_index, &ctx->mail_sync_ctx, - &ctx->view, (uint32_t)-1, 0, + &ctx->mail_view, (uint32_t)-1, 0, FALSE, FALSE) < 0) return -1; @@ -347,7 +348,7 @@ ctx->hdr = *ctx->index->hdr; - hdr = mail_index_get_header(ctx->view); + hdr = mail_index_get_header(ctx->mail_view); if (hdr->uid_validity != 0) { if (hdr->uid_validity != ctx->hdr.uid_validity) { return mailbox_list_index_set_corrupted(ctx->index, @@ -355,7 +356,7 @@ } } - ctx->trans = mail_index_transaction_begin(ctx->view, FALSE, TRUE); + ctx->trans = mail_index_transaction_begin(ctx->mail_view, FALSE, TRUE); if (hdr->uid_validity == 0) { mail_index_update_header(ctx->trans, offsetof(struct mail_index_header, uid_validity), @@ -386,6 +387,7 @@ ctx = p_new(pool, struct mailbox_list_index_sync_ctx, 1); ctx->pool = pool; ctx->index = index; + ctx->view = mailbox_list_index_view_init(index, NULL); ctx->sync_path = p_strdup(pool, path); ctx->flags = flags; @@ -405,7 +407,7 @@ struct mail_index_view * mailbox_list_index_sync_get_view(struct mailbox_list_index_sync_ctx *ctx) { - return ctx->view; + return ctx->mail_view; } struct mail_index_transaction * @@ -553,7 +555,7 @@ /* expunge from mail index */ uint32_t seq; - if (mail_index_lookup_uid_range(ctx->view, + if (mail_index_lookup_uid_range(ctx->mail_view, sync_recs[src].uid, sync_recs[src].uid, &seq, &seq) < 0) @@ -646,7 +648,7 @@ i_assert(sync_dir->offset != 0); - if (mailbox_list_index_get_dir(ctx->index, &sync_dir->offset, &dir) < 0) + if (mailbox_list_index_get_dir(ctx->view, &sync_dir->offset, &dir) < 0) return -1; sync_recs = array_get(&sync_dir->records, &count); @@ -831,6 +833,16 @@ ret = mailbox_list_index_compress(ctx); } + if (ret == 0) { + uint64_t used_space = ctx->hdr.used_space; + + /* FIXME: we should use some extension header instead of + reusing sync_size */ + mail_index_update_header(ctx->trans, + offsetof(struct mail_index_header, sync_size), + &used_space, sizeof(used_space), FALSE); + } + if (ctx->trans != NULL) { if (ret < 0) mail_index_transaction_rollback(&ctx->trans); @@ -852,6 +864,7 @@ } } + mailbox_list_index_view_deinit(&ctx->view); pool_unref(ctx->pool); return ret; }
--- a/src/lib-index/mailbox-list-index.c Thu Mar 15 14:04:45 2007 +0200 +++ b/src/lib-index/mailbox-list-index.c Thu Mar 15 15:34:49 2007 +0200 @@ -23,9 +23,13 @@ unsigned int name_path_len; }; -struct mailbox_list_iter_ctx { +struct mailbox_list_index_view { struct mailbox_list_index *index; + struct mail_index_view *mail_view; +}; +struct mailbox_list_iter_ctx { + struct mailbox_list_index_view *view; unsigned int recurse_level; struct mailbox_list_iter_path cur; @@ -394,15 +398,24 @@ return ret; } -int mailbox_list_index_get_dir(struct mailbox_list_index *index, +int mailbox_list_index_get_dir(struct mailbox_list_index_view *view, uint32_t *offset, const struct mailbox_list_dir_record **dir_r) { + struct mailbox_list_index *index = view->index; const struct mailbox_list_dir_record *dir; - uint32_t next_offset, cur_offset = *offset; + uint32_t next_offset, view_sync_offset, cur_offset = *offset; i_assert(index->mmap_size > 0); + if (view->mail_view == NULL) + view_sync_offset = (uint32_t)-1; + else { + const struct mail_index_header *hdr = + mail_index_get_header(view->mail_view); + view_sync_offset = hdr->sync_size; + } + do { if (cur_offset >= index->mmap_size - sizeof(*dir)) { return mailbox_list_index_set_corrupted(index, @@ -419,6 +432,11 @@ return mailbox_list_index_set_corrupted(index, "next_offset points backwards"); } + if (next_offset >= view_sync_offset) { + /* the list index has been changed since the mail + view's last sync. don't show the changes. */ + break; + } cur_offset = next_offset; } while (cur_offset != 0); @@ -465,10 +483,11 @@ } static int -mailbox_list_index_lookup_rec(struct mailbox_list_index *index, +mailbox_list_index_lookup_rec(struct mailbox_list_index_view *view, uint32_t dir_offset, const char *name, const struct mailbox_list_record **rec_r) { + struct mailbox_list_index *index = view->index; const struct mailbox_list_dir_record *dir; const char *p, *hier_name; int ret; @@ -479,7 +498,7 @@ return 0; } - if (mailbox_list_index_get_dir(index, &dir_offset, &dir) < 0) + if (mailbox_list_index_get_dir(view, &dir_offset, &dir) < 0) return -1; p = strchr(name, index->separator); @@ -499,7 +518,7 @@ if (dir_offset == 0) return 0; - return mailbox_list_index_lookup_rec(index, dir_offset, p + 1, rec_r); + return mailbox_list_index_lookup_rec(view, dir_offset, p + 1, rec_r); } int mailbox_list_index_refresh(struct mailbox_list_index *index) @@ -519,20 +538,40 @@ return mailbox_list_index_open_or_create(index); } -int mailbox_list_index_lookup(struct mailbox_list_index *index, +struct mailbox_list_index_view * +mailbox_list_index_view_init(struct mailbox_list_index *index, + struct mail_index_view *mail_view) +{ + struct mailbox_list_index_view *view; + + view = i_new(struct mailbox_list_index_view, 1); + view->index = index; + view->mail_view = mail_view; + return view; +} + +void mailbox_list_index_view_deinit(struct mailbox_list_index_view **_view) +{ + struct mailbox_list_index_view *view = *_view; + + *_view = NULL; + i_free(view); +} + +int mailbox_list_index_lookup(struct mailbox_list_index_view *view, const char *name, uint32_t *uid_r) { const struct mailbox_list_record *rec; - uint32_t offset = sizeof(*index->hdr); + uint32_t offset = sizeof(*view->index->hdr); int ret; - ret = mailbox_list_index_lookup_rec(index, offset, name, &rec); + ret = mailbox_list_index_lookup_rec(view, offset, name, &rec); if (ret == 0) { /* not found, see if it's found after a refresh */ - if ((ret = mailbox_list_index_refresh(index)) <= 0) + if ((ret = mailbox_list_index_refresh(view->index)) <= 0) return ret; - ret = mailbox_list_index_lookup_rec(index, offset, name, &rec); + ret = mailbox_list_index_lookup_rec(view, offset, name, &rec); } *uid_r = ret <= 0 ? 0 : rec->uid; @@ -540,24 +579,24 @@ } struct mailbox_list_iter_ctx * -mailbox_list_index_iterate_init(struct mailbox_list_index *index, +mailbox_list_index_iterate_init(struct mailbox_list_index_view *view, const char *path, int recurse_level) { struct mailbox_list_iter_ctx *ctx; const struct mailbox_list_record *rec; - uint32_t offset = sizeof(*index->hdr); + uint32_t offset = sizeof(*view->index->hdr); int ret; ctx = i_new(struct mailbox_list_iter_ctx, 1); - ctx->index = index; + ctx->view = view; ctx->recurse_level = recurse_level < 0 ? (unsigned int)-1 : (unsigned int)recurse_level; ctx->name_path = str_new(default_pool, 512); - if (mailbox_list_index_refresh(index) < 0) + if (mailbox_list_index_refresh(view->index) < 0) ctx->failed = TRUE; if (!ctx->failed && *path != '\0') { - ret = mailbox_list_index_lookup_rec(index, offset, path, &rec); + ret = mailbox_list_index_lookup_rec(view, offset, path, &rec); if (ret < 0) ctx->failed = TRUE; else { @@ -566,7 +605,7 @@ } } if (!ctx->failed && offset != 0) { - if (mailbox_list_index_get_dir(index, &offset, + if (mailbox_list_index_get_dir(view, &offset, &ctx->cur.dir) < 0) ctx->failed = TRUE; } @@ -616,7 +655,7 @@ } t_push(); - if (mailbox_list_get_name(ctx->index, unsafe_data_stack_pool, + if (mailbox_list_get_name(ctx->view->index, unsafe_data_stack_pool, recs, &name) < 0) { ctx->failed = TRUE; t_pop(); @@ -624,7 +663,7 @@ } str_truncate(ctx->name_path, ctx->cur.name_path_len); if (ctx->cur.name_path_len > 0) - str_append_c(ctx->name_path, ctx->index->separator); + str_append_c(ctx->name_path, ctx->view->index->separator); str_append(ctx->name_path, name); t_pop(); @@ -635,7 +674,7 @@ ctx->cur.name_path_len = str_len(ctx->name_path); ctx->cur.pos = 0; - if (mailbox_list_index_get_dir(ctx->index, &dir_offset, + if (mailbox_list_index_get_dir(ctx->view, &dir_offset, &ctx->cur.dir) < 0) { ctx->failed = TRUE; return -1;
--- a/src/lib-index/mailbox-list-index.h Thu Mar 15 14:04:45 2007 +0200 +++ b/src/lib-index/mailbox-list-index.h Thu Mar 15 15:34:49 2007 +0200 @@ -59,9 +59,17 @@ int mailbox_list_index_sync_commit(struct mailbox_list_index_sync_ctx **ctx); void mailbox_list_index_sync_rollback(struct mailbox_list_index_sync_ctx **ctx); +/* Mailbox list index and mail index must be kept in sync, so lookups and + iterations must know the mail index view. The mail_view can be set to NULL + to use the latest changes. */ +struct mailbox_list_index_view * +mailbox_list_index_view_init(struct mailbox_list_index *index, + struct mail_index_view *mail_view); +void mailbox_list_index_view_deinit(struct mailbox_list_index_view **view); + /* Get mailbox UID for a given name. Returns 1 if found, 0 if not, -1 if error */ -int mailbox_list_index_lookup(struct mailbox_list_index *index, +int mailbox_list_index_lookup(struct mailbox_list_index_view *view, const char *name, uint32_t *uid_r); /* Iterate through all the mailboxes. If recurse_level is -1, all the child @@ -69,7 +77,7 @@ (0 = only the mailboxes directly under the path). Returned mailbox names are allocated from name_pool. */ struct mailbox_list_iter_ctx * -mailbox_list_index_iterate_init(struct mailbox_list_index *index, +mailbox_list_index_iterate_init(struct mailbox_list_index_view *view, const char *path, int recurse_level); /* Returns 1 if mailbox was returned, 0 at the end of iteration, -1 if error */ int mailbox_list_index_iterate_next(struct mailbox_list_iter_ctx *ctx,
--- a/src/lib-storage/list/index-mailbox-list-sync.c Thu Mar 15 14:04:45 2007 +0200 +++ b/src/lib-storage/list/index-mailbox-list-sync.c Thu Mar 15 15:34:49 2007 +0200 @@ -176,7 +176,7 @@ return 0; } - ret = mailbox_list_index_lookup(ilist->list_index, box->name, &uid); + ret = mailbox_list_index_lookup(ilist->list_sync_view, box->name, &uid); if (ret <= 0) return ret; @@ -260,7 +260,8 @@ struct mailbox_list_index_sync_ctx *sync_ctx; int ret; - ret = mailbox_list_index_lookup(ilist->list_index, box->name, uid_r); + ret = mailbox_list_index_lookup(ilist->list_sync_view, + box->name, uid_r); if (ret > 0) { /* we'll need the mailbox synced since we're updating its contents based on what it already contains */ @@ -279,7 +280,8 @@ if (mailbox_list_index_sync_commit(&sync_ctx) < 0) return -1; - ret = mailbox_list_index_lookup(ilist->list_index, box->name, uid_r); + ret = mailbox_list_index_lookup(ilist->list_sync_view, + box->name, uid_r); if (ret != 0) return ret < 0 ? -1 : 0;
--- a/src/lib-storage/list/index-mailbox-list.c Thu Mar 15 14:04:45 2007 +0200 +++ b/src/lib-storage/list/index-mailbox-list.c Thu Mar 15 15:34:49 2007 +0200 @@ -28,7 +28,7 @@ struct mail_index_view_sync_rec sync_rec; int ret; - if (mail_index_view_sync_begin(ctx->view, MAIL_INDEX_SYNC_MASK_ALL, + if (mail_index_view_sync_begin(ctx->mail_view, MAIL_INDEX_SYNC_MASK_ALL, &sync_ctx) < 0) { mailbox_list_set_internal_error(ctx->ctx.list); return -1; @@ -74,7 +74,7 @@ ctx->sync_stamp = st.st_mtime; - hdr = mail_index_get_header(ctx->view); + hdr = mail_index_get_header(ctx->mail_view); return hdr->sync_stamp == ctx->sync_stamp; } @@ -123,16 +123,18 @@ ctx->glob = imap_match_init(default_pool, mask, TRUE, list->hierarchy_sep); - ctx->view = mail_index_view_open(ilist->mail_index); + ctx->mail_view = mail_index_view_open(ilist->mail_index); + ctx->view = mailbox_list_index_view_init(ilist->list_index, + ctx->mail_view); if (index_mailbox_list_is_synced(ctx) > 0) { /* synced, list from index */ mask_parse(list, mask, &prefix, &recurse_level); ctx->info_pool = pool_alloconly_create("mailbox name pool", 128); - ctx->iter_ctx = - mailbox_list_index_iterate_init(ilist->list_index, - prefix, recurse_level); + ctx->iter_ctx = mailbox_list_index_iterate_init(ctx->view, + prefix, + recurse_level); ctx->recurse_level = recurse_level; ctx->prefix = *prefix == '\0' ? i_strdup("") : i_strdup_printf("%s%c", prefix, list->hierarchy_sep); @@ -217,7 +219,7 @@ } while (imap_match(ctx->glob, ctx->info.name) != IMAP_MATCH_YES); /* get the mailbox's flags */ - if (mail_index_lookup_uid_range(ctx->view, iinfo.uid, iinfo.uid, + if (mail_index_lookup_uid_range(ctx->mail_view, iinfo.uid, iinfo.uid, &seq, &seq) < 0) return -1; if (seq == 0) { @@ -226,7 +228,7 @@ return -1; } - if (mail_index_lookup(ctx->view, seq, &rec) < 0) + if (mail_index_lookup(ctx->mail_view, seq, &rec) < 0) return -1; ctx->info.flags = index_mailbox_list_index_flags_translate(rec->flags); @@ -301,8 +303,10 @@ pool_unref(ctx->info_pool); } + if (ctx->mail_view != NULL) + mail_index_view_close(&ctx->mail_view); if (ctx->view != NULL) - mail_index_view_close(&ctx->view); + mailbox_list_index_view_deinit(&ctx->view); if (ctx->sync_ctx != NULL) { /* FIXME: single sync_stamp works only with maildir++ */ @@ -332,6 +336,7 @@ struct index_mailbox_list *ilist = INDEX_LIST_CONTEXT(list); mailbox_list_index_free(&ilist->list_index); + mailbox_list_index_view_deinit(&ilist->list_sync_view); mail_index_free(&ilist->mail_index); ilist->super.deinit(list); @@ -380,6 +385,8 @@ mailbox_list_index_free(&ilist->list_index); return -1; } + ilist->list_sync_view = mailbox_list_index_view_init(ilist->list_index, + NULL); return 0; }
--- a/src/lib-storage/list/index-mailbox-list.h Thu Mar 15 14:04:45 2007 +0200 +++ b/src/lib-storage/list/index-mailbox-list.h Thu Mar 15 15:34:49 2007 +0200 @@ -15,6 +15,7 @@ struct mail_index *mail_index; struct mailbox_list_index *list_index; + struct mailbox_list_index_view *list_sync_view; uint32_t eid_messages, eid_unseen, eid_recent; uint32_t eid_uid_validity, eid_uidnext; @@ -29,7 +30,8 @@ struct mailbox_list_index_sync_ctx *sync_ctx; struct mailbox_list_iterate_context *backend_ctx; - struct mail_index_view *view; + struct mailbox_list_index_view *view; + struct mail_index_view *mail_view; struct mail_index_transaction *trans; char *prefix;