]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-index: Fixes to handling UID changes.
authorTimo Sirainen <tss@iki.fi>
Thu, 6 Aug 2009 00:01:02 +0000 (20:01 -0400)
committerTimo Sirainen <tss@iki.fi>
Thu, 6 Aug 2009 00:01:02 +0000 (20:01 -0400)
--HG--
branch : HEAD

src/lib-index/mail-index-sync-update.c
src/lib-index/mail-index-transaction-export.c
src/lib-index/mail-index-transaction-update.c
src/lib-index/mail-index-transaction.c
src/lib-index/mail-transaction-log-file.c

index 0f49d503f97c80db5dbedf1c9bd97c2133029300..f60cb43d8119a88e0902fa57415edfd70be24489 100644 (file)
@@ -301,10 +301,10 @@ static void sync_uid_update(struct mail_index_sync_map_ctx *ctx,
        map->hdr.next_uid = new_uid+1;
        map->rec_map->last_appended_uid = new_uid;
 
-       rec = MAIL_INDEX_MAP_IDX(map, old_seq-1);
-
        /* add the new record */
        dest = sync_append_record(map);
+       rec = MAIL_INDEX_MAP_IDX(map, old_seq-1);
+       rec->uid = new_uid;
        memcpy(dest, rec, map->hdr.record_size);
 
        /* @UNSAFE: remove the old record */
index 50909ca0acaf67ffcf84fa3f4930775683987a61..212e7bd7757cc3ab2d75a296626605bd1540afc6 100644 (file)
@@ -327,6 +327,61 @@ log_append_keyword_updates(struct mail_index_export_context *ctx)
        return change_mask;
 }
 
+static bool
+mail_index_transaction_export_new_uids(struct mail_index_export_context *ctx,
+                                      struct mail_index_transaction *t)
+{
+       const struct mail_index_record *appends;
+       const struct mail_transaction_uid_update *updates;
+       unsigned int a, u, append_count, update_count;
+
+       if (!array_is_created(&t->uid_updates)) {
+               /* fast path */
+               if (!array_is_created(&t->appends))
+                       return FALSE;
+
+               log_append_buffer(ctx, t->appends.arr.buffer,
+                                 MAIL_TRANSACTION_APPEND);
+               return TRUE;
+       }
+       if (!array_is_created(&t->appends)) {
+               log_append_buffer(ctx, t->uid_updates.arr.buffer,
+                                 MAIL_TRANSACTION_UID_UPDATE);
+               return TRUE;
+       }
+
+       /* we'll need to merge so that UIDs are only being appended.
+          appends quite a lot of separate records unnecessarily,
+          but UID updates are rare.. */
+       appends = array_get(&t->appends, &append_count);
+       updates = array_get(&t->uid_updates, &update_count);
+
+       for (a = u = 0; a < append_count && u < update_count; ) {
+               if (appends[a].uid < updates[u].new_uid) {
+                       mail_transaction_log_append_add(ctx->append_ctx,
+                                       MAIL_TRANSACTION_APPEND,
+                                       &appends[a], sizeof(appends[a]));
+                       a++;
+               } else {
+                       mail_transaction_log_append_add(ctx->append_ctx,
+                                       MAIL_TRANSACTION_UID_UPDATE,
+                                       &updates[u], sizeof(updates[u]));
+                       u++;
+               }
+       }
+       if (a < append_count) {
+               mail_transaction_log_append_add(ctx->append_ctx,
+                               MAIL_TRANSACTION_APPEND, &appends[a],
+                               (append_count - a) * sizeof(appends[a]));
+       }
+       if (u < update_count) {
+               mail_transaction_log_append_add(ctx->append_ctx,
+                               MAIL_TRANSACTION_UID_UPDATE, &updates[u],
+                               (update_count - u) * sizeof(updates[u]));
+       }
+       return TRUE;
+}
+
 void mail_index_transaction_export(struct mail_index_transaction *t,
                                   struct mail_transaction_log_append_ctx *append_ctx)
 {
@@ -345,11 +400,9 @@ void mail_index_transaction_export(struct mail_index_transaction *t,
                log_append_buffer(&ctx, log_get_hdr_update_buffer(t, TRUE),
                                  MAIL_TRANSACTION_HEADER_UPDATE);
        }
-       if (array_is_created(&t->appends)) {
+       if (mail_index_transaction_export_new_uids(&ctx, t))
                change_mask |= MAIL_INDEX_SYNC_TYPE_APPEND;
-               log_append_buffer(&ctx, t->appends.arr.buffer, 
-                                 MAIL_TRANSACTION_APPEND);
-       }
+
        if (array_is_created(&t->updates)) {
                change_mask |= MAIL_INDEX_SYNC_TYPE_FLAGS;
                log_append_buffer(&ctx, t->updates.arr.buffer, 
@@ -387,12 +440,6 @@ void mail_index_transaction_export(struct mail_index_transaction *t,
                log_append_buffer(&ctx, t->expunges.arr.buffer,
                                  MAIL_TRANSACTION_EXPUNGE_GUID);
        }
-       /* keep uid updates last. if there are other updates to the message,
-          they're referring to the old uid. */
-       if (array_is_created(&t->uid_updates)) {
-               log_append_buffer(&ctx, t->uid_updates.arr.buffer,
-                                 MAIL_TRANSACTION_UID_UPDATE);
-       }
 
        if (t->post_hdr_changed) {
                log_append_buffer(&ctx, log_get_hdr_update_buffer(t, FALSE),
index 79769d60cebcaeeedb88f56a2e528e1bc0bc0af9..490055c1a2acc3e3f34c2f73a555638dff0b0da7 100644 (file)
@@ -252,6 +252,8 @@ void mail_index_update_uid(struct mail_index_transaction *t, uint32_t seq,
        u = array_append_space(&t->uid_updates);
        u->old_uid = seq;
        u->new_uid = new_uid;
+
+       t->log_updates = TRUE;
 }
 
 void mail_index_update_modseq(struct mail_index_transaction *t, uint32_t seq,
index 881882f87ea948bb7aa402c970f334e32eada23f..fe3f7302066276eb58a55b2ce8bf6f0910bd3ef1 100644 (file)
@@ -67,9 +67,11 @@ uint32_t mail_index_transaction_get_next_uid(struct mail_index_transaction *t)
        next_uid = t->reset || head_hdr->uid_validity != hdr->uid_validity ?
                1 : hdr->next_uid;
        if (array_is_created(&t->appends) && t->highest_append_uid != 0) {
-               /* get next_uid from appends if they have UIDs */
-               i_assert(next_uid <= t->highest_append_uid);
-               next_uid = t->highest_append_uid + 1;
+               /* get next_uid from appends if they have UIDs. it's possible
+                  that some appends have too low UIDs, they'll be caught
+                  later. */
+               if (next_uid <= t->highest_append_uid)
+                       next_uid = t->highest_append_uid + 1;
        }
 
        /* see if it's been updated in pre/post header changes */
index c1afe752f0eeef204d3acfdbab7a9d0b9e90c05c..d43e2932ada6f9159b442076c092f075f7565c5f 100644 (file)
@@ -808,6 +808,7 @@ void mail_transaction_update_modseq(const struct mail_transaction_header *hdr,
        case MAIL_TRANSACTION_FLAG_UPDATE:
        case MAIL_TRANSACTION_KEYWORD_UPDATE:
        case MAIL_TRANSACTION_KEYWORD_RESET:
+       case MAIL_TRANSACTION_UID_UPDATE:
                /* these changes increase modseq */
                *cur_modseq += 1;
                break;