]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
last tried fixes with sequences-in-log approach. moving to uids next, wonder
authorTimo Sirainen <tss@iki.fi>
Thu, 20 May 2004 13:43:47 +0000 (16:43 +0300)
committerTimo Sirainen <tss@iki.fi>
Thu, 20 May 2004 13:43:47 +0000 (16:43 +0300)
why I didn't earlier.

--HG--
branch : HEAD

src/lib-index/mail-index-sync.c
src/lib-index/mail-transaction-log-view.c
src/lib-index/mail-transaction-util.c
src/lib-index/mail-transaction-util.h

index 0cfe72851d21f864e073cfb3229c7d1819097a1d..6a3bb12e8b0bcf6d006083e02b191480b497bf1b 100644 (file)
@@ -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)
index 2ae861b5afe06e368e02a7c12b64f004e0ad0c84..36be7c7e8d58d6362446dd039167a77777ffa14c 100644 (file)
@@ -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;
index 9cace39f35e25551125a31273f946ad794ef0d7b..d69306bce9610729d8592aac2119a6ab814db5e2 100644 (file)
@@ -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;
 }
index f2a05c87e9edc0b0a67397bc94d0d98779c858dc..6e30c2bc70923f135479856cbf57a410631289b5 100644 (file)
@@ -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