From d1baa8c6f97cdb1b3c2c44a73cc21f9dfc7a963f Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Wed, 5 Aug 2009 20:01:02 -0400 Subject: [PATCH] lib-index: Fixes to handling UID changes. --HG-- branch : HEAD --- src/lib-index/mail-index-sync-update.c | 4 +- src/lib-index/mail-index-transaction-export.c | 67 ++++++++++++++++--- src/lib-index/mail-index-transaction-update.c | 2 + src/lib-index/mail-index-transaction.c | 8 ++- src/lib-index/mail-transaction-log-file.c | 1 + 5 files changed, 67 insertions(+), 15 deletions(-) diff --git a/src/lib-index/mail-index-sync-update.c b/src/lib-index/mail-index-sync-update.c index 0f49d503f9..f60cb43d81 100644 --- a/src/lib-index/mail-index-sync-update.c +++ b/src/lib-index/mail-index-sync-update.c @@ -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 */ diff --git a/src/lib-index/mail-index-transaction-export.c b/src/lib-index/mail-index-transaction-export.c index 50909ca0ac..212e7bd775 100644 --- a/src/lib-index/mail-index-transaction-export.c +++ b/src/lib-index/mail-index-transaction-export.c @@ -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), diff --git a/src/lib-index/mail-index-transaction-update.c b/src/lib-index/mail-index-transaction-update.c index 79769d60ce..490055c1a2 100644 --- a/src/lib-index/mail-index-transaction-update.c +++ b/src/lib-index/mail-index-transaction-update.c @@ -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, diff --git a/src/lib-index/mail-index-transaction.c b/src/lib-index/mail-index-transaction.c index 881882f87e..fe3f730206 100644 --- a/src/lib-index/mail-index-transaction.c +++ b/src/lib-index/mail-index-transaction.c @@ -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 */ diff --git a/src/lib-index/mail-transaction-log-file.c b/src/lib-index/mail-transaction-log-file.c index c1afe752f0..d43e2932ad 100644 --- a/src/lib-index/mail-transaction-log-file.c +++ b/src/lib-index/mail-transaction-log-file.c @@ -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; -- 2.47.3