From: Timo Sirainen Date: Thu, 20 May 2004 13:43:47 +0000 (+0300) Subject: last tried fixes with sequences-in-log approach. moving to uids next, wonder X-Git-Tag: 1.1.alpha1~4074 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1f2c3bde353d45f6d76c5210adf1e0a952247f3a;p=thirdparty%2Fdovecot%2Fcore.git last tried fixes with sequences-in-log approach. moving to uids next, wonder why I didn't earlier. --HG-- branch : HEAD --- diff --git a/src/lib-index/mail-index-sync.c b/src/lib-index/mail-index-sync.c index 0cfe72851d..6a3bb12e8b 100644 --- a/src/lib-index/mail-index-sync.c +++ b/src/lib-index/mail-index-sync.c @@ -14,30 +14,32 @@ static void mail_index_sync_sort_flags(struct mail_index_sync_ctx *ctx) const struct mail_transaction_flag_update *src, *src_end; const struct mail_transaction_flag_update *dest; struct mail_transaction_flag_update new_update; - struct mail_transaction_expunge_traverse_ctx *exp_ctx; + struct mail_transaction_expunge_iter_ctx *exp_ctx; uint32_t last; size_t i, dest_count; src = ctx->data; src_end = PTR_OFFSET(src, ctx->hdr->size); + if (src == src_end) + return; dest = buffer_get_data(ctx->updates_buf, &dest_count); dest_count /= sizeof(*dest); - exp_ctx = mail_transaction_expunge_traverse_init(ctx->expunges_buf); + exp_ctx = mail_transaction_expunge_iter_init(ctx->expunges_buf); + mail_transaction_expunge_iter_seek(exp_ctx, src->seq1, src->seq2); - for (i = 0; src != src_end; src++) { + for (i = 0; src != src_end; ) { new_update = *src; - /* find seq1 */ - new_update.seq1 += - mail_transaction_expunge_traverse_to(exp_ctx, - src->seq1); - - /* find seq2 */ - new_update.seq2 += - mail_transaction_expunge_traverse_to(exp_ctx, - src->seq2); + if (!mail_transaction_expunge_iter_get(exp_ctx, + &new_update.seq1, + &new_update.seq2)) { + mail_transaction_expunge_iter_seek(exp_ctx, src->seq1, + src->seq2); + src++; + continue; + } /* insert it into buffer, split it in multiple parts if needed to make sure the ordering stays the same */ @@ -66,7 +68,7 @@ static void mail_index_sync_sort_flags(struct mail_index_sync_ctx *ctx) dest = buffer_get_data(ctx->updates_buf, NULL); dest_count++; } - mail_transaction_expunge_traverse_deinit(exp_ctx); + mail_transaction_expunge_iter_deinit(exp_ctx); } static void mail_index_sync_sort_transaction(struct mail_index_sync_ctx *ctx) diff --git a/src/lib-index/mail-transaction-log-view.c b/src/lib-index/mail-transaction-log-view.c index 2ae861b5af..36be7c7e8d 100644 --- a/src/lib-index/mail-transaction-log-view.c +++ b/src/lib-index/mail-transaction-log-view.c @@ -15,7 +15,7 @@ struct mail_transaction_log_view { enum mail_transaction_type type_mask; buffer_t *expunges_buf, *data_buf; - struct mail_transaction_expunge_traverse_ctx *exp_ctx; + struct mail_transaction_expunge_iter_ctx *exp_ctx; struct mail_transaction_header tmp_hdr; struct mail_transaction_log_file *file; @@ -319,23 +319,21 @@ static int seqfix_expunge(const struct mail_transaction_expunge *e, { struct mail_transaction_log_view *view = context; struct mail_transaction_expunge new_e; - uint32_t expunges_before; - expunges_before = mail_transaction_expunge_traverse_to(view->exp_ctx, - e->seq2); - if (expunges_before == 0) { - buffer_append(view->data_buf, e, sizeof(*e)); - return 1; + if (!mail_transaction_expunge_iter_seek(view->exp_ctx, + e->seq1, e->seq2)) { + new_e = *e; + /*FIXME:buffer_append(view->data_buf, e, sizeof(*e)); + return 1;*/ } - /* FIXME: if there's expunges in the middle of the - range, we'd have to split this to multiple records */ + new_e.uid1 = new_e.uid2 = 0; // FIXME: this breaks anyway - new_e = *e; - new_e.seq2 += expunges_before; - new_e.seq1 += mail_transaction_expunge_traverse_to(view->exp_ctx, - new_e.seq1); - buffer_append(view->data_buf, &new_e, sizeof(new_e)); + while (mail_transaction_expunge_iter_get(view->exp_ctx, + &new_e.seq1, &new_e.seq2)) { + i_assert(new_e.seq1 != 0); + buffer_append(view->data_buf, &new_e, sizeof(new_e)); + } return 1; } @@ -344,23 +342,17 @@ static int seqfix_flag_update(const struct mail_transaction_flag_update *u, { struct mail_transaction_log_view *view = context; struct mail_transaction_flag_update new_u; - uint32_t expunges_before; - expunges_before = mail_transaction_expunge_traverse_to(view->exp_ctx, - u->seq2); - if (expunges_before == 0) { + if (!mail_transaction_expunge_iter_seek(view->exp_ctx, + u->seq1, u->seq2)) { buffer_append(view->data_buf, u, sizeof(*u)); return 1; } - /* FIXME: if there's expunges in the middle of the - range, we'd have to split this to multiple records */ - new_u = *u; - new_u.seq2 += expunges_before; - new_u.seq1 += mail_transaction_expunge_traverse_to(view->exp_ctx, - new_u.seq1); - buffer_append(view->data_buf, &new_u, sizeof(new_u)); + while (mail_transaction_expunge_iter_get(view->exp_ctx, + &new_u.seq1, &new_u.seq2)) + buffer_append(view->data_buf, &new_u, sizeof(new_u)); return 1; } @@ -369,17 +361,17 @@ static int seqfix_cache_update(const struct mail_transaction_cache_update *u, { struct mail_transaction_log_view *view = context; struct mail_transaction_cache_update new_u; - uint32_t expunges_before; - - expunges_before = mail_transaction_expunge_traverse_to(view->exp_ctx, - u->seq); - if (expunges_before != 0) { - new_u = *u; - new_u.seq += expunges_before; - u = &new_u; + + if (!mail_transaction_expunge_iter_seek(view->exp_ctx, + u->seq, u->seq)) { + buffer_append(view->data_buf, u, sizeof(*u)); + return 1; } - buffer_append(view->data_buf, u, sizeof(*u)); + new_u = *u; + if (mail_transaction_expunge_iter_get(view->exp_ctx, + &new_u.seq, &new_u.seq)) + buffer_append(view->data_buf, &new_u, sizeof(new_u)); return 1; } @@ -432,15 +424,18 @@ int mail_transaction_log_view_next(struct mail_transaction_log_view *view, buffer_set_used_size(view->data_buf, 0); } - view->exp_ctx = mail_transaction_expunge_traverse_init( - view->expunges_buf); + view->exp_ctx = + mail_transaction_expunge_iter_init(view->expunges_buf); ret = mail_transaction_map(hdr, data, &seqfix_funcs, view); - mail_transaction_expunge_traverse_deinit(view->exp_ctx); + mail_transaction_expunge_iter_deinit(view->exp_ctx); if (ret > 0) { - /* modified */ - i_assert(buffer_get_used_size(view->data_buf) == - hdr->size); + /* modified - size may have changed, so update header */ + view->tmp_hdr = *hdr; + view->tmp_hdr.size = + buffer_get_used_size(view->data_buf); + *hdr_r = &view->tmp_hdr; + *data_r = buffer_get_data(view->data_buf, NULL); } else { i_assert(buffer_get_used_size(view->data_buf) == 0); @@ -452,9 +447,11 @@ int mail_transaction_log_view_next(struct mail_transaction_log_view *view, data, hdr->size); /* hide expunge protection */ - view->tmp_hdr = *hdr; + if (*hdr_r != &view->tmp_hdr) { + view->tmp_hdr = *hdr; + *hdr_r = &view->tmp_hdr; + } view->tmp_hdr.type &= ~MAIL_TRANSACTION_EXPUNGE_PROT; - *hdr_r = &view->tmp_hdr; } return 1; diff --git a/src/lib-index/mail-transaction-util.c b/src/lib-index/mail-transaction-util.c index 9cace39f35..d69306bce9 100644 --- a/src/lib-index/mail-transaction-util.c +++ b/src/lib-index/mail-transaction-util.c @@ -6,11 +6,11 @@ #include "mail-transaction-log.h" #include "mail-transaction-util.h" -struct mail_transaction_expunge_traverse_ctx { +struct mail_transaction_expunge_iter_ctx { const struct mail_transaction_expunge *expunges; - size_t expunges_count, cur_idx, old_idx; - uint32_t cur_seq, expunges_before; - uint32_t old_seq, old_expunges_before; + size_t expunges_count; + uint32_t cur_seq, cur_idx, expunges_before; + uint32_t iter_seq, iter_count, iter_idx; }; const struct mail_transaction_type_map mail_transaction_type_map[] = { @@ -149,7 +149,7 @@ mail_transaction_log_sort_expunges(buffer_t *expunges_buf, if (src->seq1 + expunges_before < dest[i].seq1) break; - i_assert(src->uid2 > dest[i].uid1); + i_assert(src->uid2 == 0 || src->uid2 > dest[i].uid1); expunges_before += dest[i].seq2 - dest[i].seq1 + 1; } @@ -169,7 +169,8 @@ mail_transaction_log_sort_expunges(buffer_t *expunges_buf, new_exp.seq2 += count; if (new_exp.seq2 == dest[i].seq2) new_exp.uid2 = dest[i].uid2; - i_assert(new_exp.uid2 >= dest[i].uid2); + i_assert(new_exp.uid2 == 0 || + new_exp.uid2 >= dest[i].uid2); i++; } @@ -201,14 +202,13 @@ mail_transaction_log_sort_expunges(buffer_t *expunges_buf, } } -struct mail_transaction_expunge_traverse_ctx * -mail_transaction_expunge_traverse_init(const buffer_t *expunges_buf) +struct mail_transaction_expunge_iter_ctx * +mail_transaction_expunge_iter_init(const buffer_t *expunges_buf) { - struct mail_transaction_expunge_traverse_ctx *ctx; + struct mail_transaction_expunge_iter_ctx *ctx; - ctx = i_new(struct mail_transaction_expunge_traverse_ctx, 1); + ctx = i_new(struct mail_transaction_expunge_iter_ctx, 1); ctx->cur_seq = 1; - ctx->old_seq = 1; if (expunges_buf != NULL) { ctx->expunges = @@ -218,34 +218,25 @@ mail_transaction_expunge_traverse_init(const buffer_t *expunges_buf) return ctx; } -void mail_transaction_expunge_traverse_deinit( - struct mail_transaction_expunge_traverse_ctx *ctx) +void mail_transaction_expunge_iter_deinit( + struct mail_transaction_expunge_iter_ctx *ctx) { i_free(ctx); } -uint32_t mail_transaction_expunge_traverse_to( - struct mail_transaction_expunge_traverse_ctx *ctx, uint32_t seq) +int mail_transaction_expunge_iter_seek( + struct mail_transaction_expunge_iter_ctx *ctx, + uint32_t seq1, uint32_t seq2) { uint32_t idx, count, last_seq; - if (seq < ctx->cur_seq) { - /* allow seeking one back */ - ctx->cur_idx = ctx->old_idx; - ctx->cur_seq = ctx->old_seq; - ctx->expunges_before = ctx->old_expunges_before; - } else { - ctx->old_idx = ctx->cur_idx; - ctx->old_seq = ctx->cur_seq; - ctx->old_expunges_before = ctx->expunges_before; - } - i_assert(seq >= ctx->cur_seq); + i_assert(seq1 >= ctx->cur_seq); idx = ctx->cur_idx; last_seq = idx == 0 ? 1 : ctx->expunges[idx-1].seq2 + 1; for (; idx < ctx->expunges_count; idx++) { count = ctx->expunges[idx].seq1 - last_seq; - if (ctx->cur_seq + count > seq) + if (ctx->cur_seq + count > seq1) break; ctx->cur_seq += count; @@ -254,6 +245,42 @@ uint32_t mail_transaction_expunge_traverse_to( last_seq = ctx->expunges[idx].seq2+1; } + ctx->iter_idx = idx; + ctx->iter_seq = seq1 + ctx->expunges_before; + ctx->iter_count = seq2 - seq1 + 1; + ctx->cur_idx = idx; - return ctx->expunges_before; + return ctx->expunges_before != 0 || + (idx != ctx->expunges_count && ctx->expunges[idx].seq1 <= seq2); +} + +int mail_transaction_expunge_iter_get( + struct mail_transaction_expunge_iter_ctx *ctx, + uint32_t *seq1_r, uint32_t *seq2_r) +{ + if (ctx->iter_count == 0) + return 0; + + *seq1_r = ctx->iter_seq; + + if (ctx->iter_idx == ctx->expunges_count || + ctx->expunges[ctx->iter_idx].seq1 >= + ctx->iter_seq + ctx->iter_count) { + /* last one */ + *seq2_r = ctx->iter_seq + ctx->iter_count - 1; + ctx->iter_count = 0; + return 1; + } + + ctx->iter_count -= ctx->expunges[ctx->iter_idx].seq1 - ctx->iter_seq; + i_assert(ctx->iter_count > 0); + + /* have to split this one */ + *seq2_r = ctx->expunges[ctx->iter_idx].seq1-1; + do { + ctx->iter_seq = ctx->expunges[ctx->iter_idx].seq2+1; + ctx->iter_idx++; + } while (ctx->iter_idx != ctx->expunges_count && + ctx->expunges[ctx->iter_idx].seq1 == ctx->iter_seq); + return 1; } diff --git a/src/lib-index/mail-transaction-util.h b/src/lib-index/mail-transaction-util.h index f2a05c87e9..6e30c2bc70 100644 --- a/src/lib-index/mail-transaction-util.h +++ b/src/lib-index/mail-transaction-util.h @@ -30,13 +30,24 @@ int mail_transaction_map(const struct mail_transaction_header *hdr, void mail_transaction_log_sort_expunges(buffer_t *expunges_buf, const struct mail_transaction_expunge *src, - size_t src_buf_size);; + size_t src_buf_size); -struct mail_transaction_expunge_traverse_ctx * -mail_transaction_expunge_traverse_init(const buffer_t *expunges_buf); -void mail_transaction_expunge_traverse_deinit( - struct mail_transaction_expunge_traverse_ctx *ctx); -uint32_t mail_transaction_expunge_traverse_to( - struct mail_transaction_expunge_traverse_ctx *ctx, uint32_t seq); +/* Iterate through expunges buffer. iter_seek()'s seq1/seq2 is assumed to be + in post-expunge view, iter_get() updates them to pre-expunge view. Some + post-expunge sequence arrays may go through expunges, we split them so it + won't be visible. */ +struct mail_transaction_expunge_iter_ctx * +mail_transaction_expunge_iter_init(const buffer_t *expunges_buf); +void mail_transaction_expunge_iter_deinit( + struct mail_transaction_expunge_iter_ctx *ctx); +/* Returns TRUE if seq1 or seq2 will be modified by iter_get(). If FALSE is + returned calling iter_get() is a bit pointless. */ +int mail_transaction_expunge_iter_seek( + struct mail_transaction_expunge_iter_ctx *ctx, + uint32_t seq1, uint32_t seq2); +/* Returns TRUE while sequences are returned. */ +int mail_transaction_expunge_iter_get( + struct mail_transaction_expunge_iter_ctx *ctx, + uint32_t *seq1_r, uint32_t *seq2_r); #endif