From: Timo Sirainen Date: Sun, 23 May 2004 16:30:24 +0000 (+0300) Subject: View's message count shouldn't change until after view is synced. X-Git-Tag: 1.1.alpha1~4062 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5a58037ad75b88356d82240fab2bc604de03107e;p=thirdparty%2Fdovecot%2Fcore.git View's message count shouldn't change until after view is synced. --HG-- branch : HEAD --- diff --git a/src/lib-index/mail-index-view-private.h b/src/lib-index/mail-index-view-private.h index 024d8829cd..ebd745bf35 100644 --- a/src/lib-index/mail-index-view-private.h +++ b/src/lib-index/mail-index-view-private.h @@ -10,6 +10,9 @@ struct mail_index_view { unsigned int indexid; struct mail_index_map *map; + struct mail_index_header tmp_hdr_copy; + uint32_t messages_count; /* last synced one, map may be different */ + uint32_t log_file_seq; uoff_t log_file_offset; buffer_t *log_syncs; diff --git a/src/lib-index/mail-index-view-sync.c b/src/lib-index/mail-index-view-sync.c index e935145107..29f1ca53ca 100644 --- a/src/lib-index/mail-index-view-sync.c +++ b/src/lib-index/mail-index-view-sync.c @@ -12,7 +12,6 @@ struct mail_index_view_sync_ctx { enum mail_index_sync_type sync_mask; struct mail_index_map *sync_map; buffer_t *expunges; - uint32_t messages_count; const struct mail_transaction_header *hdr; const void *data; @@ -20,6 +19,7 @@ struct mail_index_view_sync_ctx { size_t data_offset; unsigned int skipped:1; unsigned int last_read:1; + unsigned int sync_map_update:1; }; static int @@ -79,7 +79,6 @@ int mail_index_view_sync_begin(struct mail_index_view *view, { const struct mail_index_header *hdr; struct mail_index_view_sync_ctx *ctx; - struct mail_index_map *map; enum mail_transaction_type mask; buffer_t *expunges = NULL; @@ -110,20 +109,23 @@ int mail_index_view_sync_begin(struct mail_index_view *view, return -1; } - if (sync_mask == MAIL_INDEX_SYNC_MASK_ALL) { - map = view->index->map; - map->refcount++; - } else { - map = mail_index_map_to_memory(view->map); - } - view->syncing = TRUE; - ctx = i_new(struct mail_index_view_sync_ctx, 1); ctx->view = view; ctx->sync_mask = sync_mask; - ctx->sync_map = map; ctx->expunges = expunges; - ctx->messages_count = mail_index_view_get_message_count(view); + + if ((sync_mask & MAIL_INDEX_SYNC_TYPE_EXPUNGE) != 0) { + ctx->sync_map = view->index->map; + ctx->sync_map->refcount++; + } else { + /* we need a private copy of the map if we don't want to + sync expunges */ + if (MAIL_INDEX_MAP_IS_IN_MEMORY(view->map)) + ctx->sync_map_update = TRUE; + ctx->sync_map = mail_index_map_to_memory(view->map); + } + + view->syncing = TRUE; *ctx_r = ctx; return 0; @@ -254,8 +256,7 @@ static int mail_index_view_sync_map(struct mail_index_view_sync_ctx *ctx) sync_expunge, sync_append, sync_flag_update, sync_cache_update }; - return mail_transaction_map(ctx->hdr, ctx->data, - &map_funcs, ctx); + return mail_transaction_map(ctx->hdr, ctx->data, &map_funcs, ctx); } static int mail_index_view_sync_next_trans(struct mail_index_view_sync_ctx *ctx, @@ -284,7 +285,7 @@ static int mail_index_view_sync_next_trans(struct mail_index_view_sync_ctx *ctx, if (view_is_transaction_synced(view, *seq_r, *offset_r)) return 0; - if (ctx->sync_mask != MAIL_INDEX_SYNC_MASK_ALL) { + if (ctx->sync_map_update) { if (mail_index_view_sync_map(ctx) < 0) return -1; } @@ -411,6 +412,9 @@ void mail_index_view_sync_end(struct mail_index_view_sync_ctx *ctx) view->map = ctx->sync_map; view->map_protected = FALSE; + if ((ctx->sync_mask & MAIL_INDEX_SYNC_TYPE_APPEND) != 0) + view->messages_count = view->map->records_count; + mail_transaction_log_view_unset(view->log_view); if (ctx->expunges != NULL) diff --git a/src/lib-index/mail-index-view.c b/src/lib-index/mail-index-view.c index 6b1a5ed410..9b7576c723 100644 --- a/src/lib-index/mail-index-view.c +++ b/src/lib-index/mail-index-view.c @@ -17,6 +17,7 @@ struct mail_index_view *mail_index_view_open(struct mail_index *index) view->indexid = index->indexid; view->map = index->map; view->map->refcount++; + view->messages_count = view->map->records_count; view->log_file_seq = view->map->log_file_seq; view->log_file_offset = view->map->log_file_offset; @@ -115,7 +116,7 @@ void mail_index_view_unlock(struct mail_index_view *view) uint32_t mail_index_view_get_message_count(struct mail_index_view *view) { - return view->map->records_count; + return view->messages_count; } int mail_index_view_is_inconsistent(struct mail_index_view *view) @@ -148,7 +149,14 @@ int mail_index_get_header(struct mail_index_view *view, if (mail_index_view_lock(view) < 0) return -1; - *hdr_r = view->map->hdr; + if (view->map->hdr->messages_count == view->messages_count) + *hdr_r = view->map->hdr; + else { + /* messages_count differs, use a modified copy */ + view->tmp_hdr_copy = *view->map->hdr; + view->tmp_hdr_copy.messages_count = view->messages_count; + *hdr_r = &view->tmp_hdr_copy; + } return 0; } @@ -160,7 +168,7 @@ int mail_index_lookup(struct mail_index_view *view, uint32_t seq, uint32_t uid; i_assert(seq > 0); - i_assert(seq <= view->map->records_count); + i_assert(seq <= view->messages_count); if (mail_index_view_lock(view) < 0) return -1; @@ -195,7 +203,7 @@ int mail_index_lookup_uid(struct mail_index_view *view, uint32_t seq, uint32_t *uid_r) { i_assert(seq > 0); - i_assert(seq <= view->map->records_count); + i_assert(seq <= view->messages_count); if (mail_index_view_lock(view) < 0) return -1; @@ -214,7 +222,7 @@ static uint32_t mail_index_bsearch_uid(struct mail_index_view *view, rec = view->map->records; idx = left_idx = *left_idx_p; - right_idx = view->map->records_count; + right_idx = view->messages_count; while (left_idx < right_idx) { idx = (left_idx + right_idx) / 2; @@ -227,7 +235,7 @@ static uint32_t mail_index_bsearch_uid(struct mail_index_view *view, break; } - if (idx == view->map->records_count) { + if (idx == view->messages_count) { /* no messages available */ return 0; } @@ -237,7 +245,7 @@ static uint32_t mail_index_bsearch_uid(struct mail_index_view *view, if (nearest_side > 0) { /* we want uid or larger */ return rec[idx].uid > uid ? idx+1 : - idx == view->map->records_count-1 ? 0 : idx+2; + idx == view->messages_count-1 ? 0 : idx+2; } else { /* we want uid or smaller */ return rec[idx].uid < uid ? idx + 1 : idx; @@ -313,7 +321,7 @@ int mail_index_lookup_first(struct mail_index_view *view, enum mail_flags flags, } rec = &view->map->records[seq-1]; - for (; seq <= view->map->records_count; seq++, rec++) { + for (; seq <= view->messages_count; seq++, rec++) { if ((rec->flags & flags_mask) == (uint8_t)flags) { *seq_r = seq; break;