# HG changeset patch # User Timo Sirainen # Date 1199613561 -7200 # Node ID 26dbad6c08f36c3992a0881dfc0c34de580434c9 # Parent 0c1859ca8ee9148d7a54f0ca370cddb84c5a0678 If a message was expunged but is still visible in a view, its flags/keywords might have been updated if an uid range included the expunged message. diff -r 0c1859ca8ee9 -r 26dbad6c08f3 src/lib-index/mail-index-sync-keywords.c --- a/src/lib-index/mail-index-sync-keywords.c Sun Jan 06 11:24:04 2008 +0200 +++ b/src/lib-index/mail-index-sync-keywords.c Sun Jan 06 11:59:21 2008 +0200 @@ -191,23 +191,19 @@ i_assert(*keyword_idx_r / CHAR_BIT < ext->record_size); } -static int +static void keywords_update_records(struct mail_index_sync_map_ctx *ctx, const struct mail_index_ext *ext, unsigned int keyword_idx, enum modify_type type, - uint32_t uid1, uint32_t uid2) + uint32_t seq1, uint32_t seq2) { struct mail_index_view *view = ctx->view; struct mail_index_record *rec; unsigned char *data, data_mask; unsigned int data_offset; - uint32_t seq1, seq2; i_assert(keyword_idx != (unsigned int)-1); - if (!mail_index_lookup_seq_range(view, uid1, uid2, &seq1, &seq2)) - return 1; - mail_index_sync_write_seq_update(ctx, seq1, seq2); data_offset = keyword_idx / CHAR_BIT; @@ -237,7 +233,6 @@ default: i_unreached(); } - return 1; } int mail_index_sync_keywords(struct mail_index_sync_map_ctx *ctx, @@ -248,9 +243,10 @@ const char *keyword_name; const struct mail_index_ext *ext; const uint32_t *uid, *end; + struct sync_uid_range_iter iter; + uint32_t seq1, seq2; uint32_t seqset_offset, ext_map_idx; unsigned int keyword_idx; - int ret; seqset_offset = sizeof(*rec) + rec->name_size; if ((seqset_offset % 4) != 0) @@ -293,12 +289,11 @@ } while (uid+2 <= end) { - ret = keywords_update_records(ctx, ext, keyword_idx, - rec->modify_type, - uid[0], uid[1]); - if (ret <= 0) - return ret; - + sync_uid_range_iter_init(&iter, ctx, uid[0], uid[1]); + while (sync_uid_range_iter_next(&iter, &seq1, &seq2)) { + keywords_update_records(ctx, ext, keyword_idx, + rec->modify_type, seq1, seq2); + } uid += 2; } @@ -314,6 +309,7 @@ struct mail_index_record *rec; const struct mail_index_ext *ext; const struct mail_transaction_keyword_reset *end; + struct sync_uid_range_iter iter; uint32_t ext_map_idx, seq1, seq2; if (!mail_index_map_lookup_ext(map, "keywords", &ext_map_idx)) { @@ -324,15 +320,14 @@ ext = array_idx(&map->extensions, ext_map_idx); end = CONST_PTR_OFFSET(r, hdr->size); for (; r != end; r++) { - if (!mail_index_lookup_seq_range(ctx->view, r->uid1, r->uid2, - &seq1, &seq2)) - continue; - - mail_index_sync_write_seq_update(ctx, seq1, seq2); - for (seq1--; seq1 < seq2; seq1++) { - rec = MAIL_INDEX_MAP_IDX(map, seq1); - memset(PTR_OFFSET(rec, ext->record_offset), - 0, ext->record_size); + sync_uid_range_iter_init(&iter, ctx, r->uid1, r->uid2); + while (sync_uid_range_iter_next(&iter, &seq1, &seq2)) { + mail_index_sync_write_seq_update(ctx, seq1, seq2); + for (seq1--; seq1 < seq2; seq1++) { + rec = MAIL_INDEX_MAP_IDX(map, seq1); + memset(PTR_OFFSET(rec, ext->record_offset), + 0, ext->record_size); + } } } return 1; diff -r 0c1859ca8ee9 -r 26dbad6c08f3 src/lib-index/mail-index-sync-private.h --- a/src/lib-index/mail-index-sync-private.h Sun Jan 06 11:24:04 2008 +0200 +++ b/src/lib-index/mail-index-sync-private.h Sun Jan 06 11:59:21 2008 +0200 @@ -8,6 +8,11 @@ }; ARRAY_DEFINE_TYPE(uid_range, struct uid_range); +struct sync_uid_range_iter { + struct mail_index_sync_map_ctx *ctx; + uint32_t seq1, seq2; +}; + struct mail_index_sync_list { const ARRAY_TYPE(uid_range) *array; unsigned int idx; @@ -52,6 +57,12 @@ int mail_index_sync_map(struct mail_index_map **map, enum mail_index_sync_handler_type type, bool force); +void sync_uid_range_iter_init(struct sync_uid_range_iter *iter, + struct mail_index_sync_map_ctx *ctx, + uint32_t uid1, uint32_t uid2); +bool sync_uid_range_iter_next(struct sync_uid_range_iter *iter, + uint32_t *seq1_r, uint32_t *seq2_r); + int mail_index_sync_record(struct mail_index_sync_map_ctx *ctx, const struct mail_transaction_header *hdr, const void *data); diff -r 0c1859ca8ee9 -r 26dbad6c08f3 src/lib-index/mail-index-sync-update.c --- a/src/lib-index/mail-index-sync-update.c Sun Jan 06 11:24:04 2008 +0200 +++ b/src/lib-index/mail-index-sync-update.c Sun Jan 06 11:59:21 2008 +0200 @@ -88,6 +88,55 @@ return ctx->view->map; } +void sync_uid_range_iter_init(struct sync_uid_range_iter *iter, + struct mail_index_sync_map_ctx *ctx, + uint32_t uid1, uint32_t uid2) +{ + memset(iter, 0, sizeof(*iter)); + iter->ctx = ctx; + if (!mail_index_lookup_seq_range(ctx->view, uid1, uid2, + &iter->seq1, &iter->seq2)) + iter->seq1 = 1; +} + +bool sync_uid_range_iter_next(struct sync_uid_range_iter *iter, + uint32_t *seq1_r, uint32_t *seq2_r) +{ + struct mail_index_view *view; + uint32_t seq; + + if (iter->seq1 > iter->seq2) + return FALSE; + + if (iter->ctx->type != MAIL_INDEX_SYNC_HANDLER_VIEW) { + *seq1_r = iter->seq1; + *seq2_r = iter->seq2; + iter->seq1 = iter->seq2 + 1; + return TRUE; + } + view = iter->ctx->view; + + /* with views we have to drop expunged messages from the range. + first skip over any expunged messages from the beginning of the + range. */ + for (seq = iter->seq1; seq <= iter->seq2; seq++) { + if (!mail_index_is_expunged(view, seq)) + break; + } + if (seq > iter->seq2) + return FALSE; + *seq1_r = seq; + + /* go forward until we find the first expunged message */ + for (seq++; seq <= iter->seq2; seq++) { + if (mail_index_is_expunged(view, seq)) + break; + } + *seq2_r = seq - 1; + iter->seq1 = seq; + return TRUE; +} + static int mail_index_header_update_counts(struct mail_index_header *hdr, uint8_t old_flags, uint8_t new_flags, @@ -338,16 +387,14 @@ return 1; } -static int sync_flag_update(const struct mail_transaction_flag_update *u, - struct mail_index_sync_map_ctx *ctx) +static void sync_flag_update_range(struct mail_index_sync_map_ctx *ctx, + const struct mail_transaction_flag_update *u, + uint32_t seq1, uint32_t seq2) { struct mail_index_view *view = ctx->view; struct mail_index_record *rec; uint8_t flag_mask, old_flags; - uint32_t idx, seq1, seq2; - - if (!mail_index_lookup_seq_range(view, u->uid1, u->uid2, &seq1, &seq2)) - return 1; + uint32_t idx; mail_index_sync_write_seq_update(ctx, seq1, seq2); @@ -377,6 +424,17 @@ rec->flags, TRUE); } } +} + +static int sync_flag_update(const struct mail_transaction_flag_update *u, + struct mail_index_sync_map_ctx *ctx) +{ + struct sync_uid_range_iter iter; + uint32_t seq1, seq2; + + sync_uid_range_iter_init(&iter, ctx, u->uid1, u->uid2); + while (sync_uid_range_iter_next(&iter, &seq1, &seq2)) + sync_flag_update_range(ctx, u, seq1, seq2); return 1; } diff -r 0c1859ca8ee9 -r 26dbad6c08f3 src/lib-index/mail-index-view-sync.c --- a/src/lib-index/mail-index-view-sync.c Sun Jan 06 11:24:04 2008 +0200 +++ b/src/lib-index/mail-index-view-sync.c Sun Jan 06 11:59:21 2008 +0200 @@ -309,8 +309,6 @@ ctx->expunges = expunges; ctx->finish_min_msg_count = reset || quick_sync ? 0 : view->map->hdr.messages_count - expunge_count; - mail_index_sync_map_init(&ctx->sync_map_ctx, view, - MAIL_INDEX_SYNC_HANDLER_VIEW); if (reset && view->map->hdr.messages_count > 0 && (flags & MAIL_INDEX_VIEW_SYNC_FLAG_FIX_INCONSISTENT) == 0) { @@ -360,6 +358,11 @@ } } + if (ctx->sync_map_update) { + mail_index_sync_map_init(&ctx->sync_map_ctx, view, + MAIL_INDEX_SYNC_HANDLER_VIEW); + } + #ifdef DEBUG mail_index_map_check(view->map); #endif @@ -686,7 +689,8 @@ view->map->hdr.log_file_tail_offset = 0; } - mail_index_sync_map_deinit(&ctx->sync_map_ctx); + if (ctx->sync_map_update) + mail_index_sync_map_deinit(&ctx->sync_map_ctx); mail_index_view_sync_clean_log_syncs(ctx->view); #ifdef DEBUG