Mercurial > dovecot > core-2.2
changeset 9684:fb8bc26d7194 HEAD
Changed mail_index_append_assign_uids() to mail_index_append_finish_uids() with API changes.
It's now possible to call mail_index_append() with UIDs before locking
mailbox and have the _finish_uids() change them if another session had
already used those UIDs.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Mon, 27 Jul 2009 19:00:56 -0400 |
parents | b56b06cdd1d7 |
children | be433e394f69 |
files | src/lib-index/mail-index-transaction-update.c src/lib-index/mail-index.h src/lib-index/test-mail-index-transaction-update.c src/lib-storage/index/cydir/cydir-save.c src/lib-storage/index/dbox/dbox-map.c src/lib-storage/index/dbox/dbox-map.h src/lib-storage/index/dbox/dbox-save.c src/lib-storage/index/maildir/maildir-save.c |
diffstat | 8 files changed, 101 insertions(+), 65 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-index/mail-index-transaction-update.c Mon Jul 27 18:54:02 2009 -0400 +++ b/src/lib-index/mail-index-transaction-update.c Mon Jul 27 19:00:56 2009 -0400 @@ -196,24 +196,46 @@ } } -void mail_index_append_assign_uids(struct mail_index_transaction *t, - uint32_t first_uid, uint32_t *next_uid_r) +void mail_index_append_finish_uids(struct mail_index_transaction *t, + uint32_t first_uid, + ARRAY_TYPE(seq_range) *uids_r) { struct mail_index_record *recs; unsigned int i, count; - + struct seq_range *range; + uint32_t next_uid; + if (!array_is_created(&t->appends)) return; - i_assert(first_uid > t->highest_append_uid); - + /* first find the highest assigned uid */ recs = array_get_modifiable(&t->appends, &count); + i_assert(count > 0); + + next_uid = first_uid; for (i = 0; i < count; i++) { - if (recs[i].uid == 0) - recs[i].uid = first_uid++; + if (next_uid <= recs[i].uid) + next_uid = recs[i].uid + 1; } - *next_uid_r = first_uid; + /* assign missing uids */ + for (i = 0; i < count; i++) { + if (recs[i].uid == 0 || recs[i].uid < first_uid) + recs[i].uid = next_uid++; + } + + /* write the saved uids range */ + array_clear(uids_r); + range = array_append_space(uids_r); + range->seq1 = range->seq2 = recs[0].uid; + for (i = 1; i < count; i++) { + if (range->seq2 + 1 == recs[i].uid) + range->seq2++; + else { + range = array_append_space(uids_r); + range->seq1 = range->seq2 = recs[i].uid; + } + } } void mail_index_update_uid(struct mail_index_transaction *t, uint32_t seq,
--- a/src/lib-index/mail-index.h Mon Jul 27 18:54:02 2009 -0400 +++ b/src/lib-index/mail-index.h Mon Jul 27 19:00:56 2009 -0400 @@ -396,10 +396,13 @@ /* Append a new record to index. */ void mail_index_append(struct mail_index_transaction *t, uint32_t uid, uint32_t *seq_r); -/* Assigns UIDs for appended mails all at once. UID must have been given as 0 - for mail_index_append(). Returns the next unused UID. */ -void mail_index_append_assign_uids(struct mail_index_transaction *t, - uint32_t first_uid, uint32_t *next_uid_r); +/* Assign UIDs for mails with uid=0 or uid<first_uid. Assumes that mailbox is + locked in a way that UIDs can be safely assigned. Returns UIDs for all + asigned messages, in their sequence order (so UIDs are not necessary + ascending). */ +void mail_index_append_finish_uids(struct mail_index_transaction *t, + uint32_t first_uid, + ARRAY_TYPE(seq_range) *uids_r); /* Update message's UID. The new UID must not be lower than next_uid at the commit time, otherwise the UID update fails and is just ignored. If there are appends in the same transaction, the updated UIDs must be
--- a/src/lib-index/test-mail-index-transaction-update.c Mon Jul 27 18:54:02 2009 -0400 +++ b/src/lib-index/test-mail-index-transaction-update.c Mon Jul 27 19:00:56 2009 -0400 @@ -57,8 +57,10 @@ { struct mail_index_transaction *t; const struct mail_index_record *appends; + ARRAY_TYPE(seq_range) saved_uids_arr; + const struct seq_range *saved_uids; unsigned int count; - uint32_t seq, next_uid; + uint32_t seq; hdr.messages_count = 4; t = mail_index_transaction_new(); @@ -71,8 +73,11 @@ test_assert(seq == 6); test_assert(!t->appends_nonsorted); - mail_index_append_assign_uids(t, 123, &next_uid); - test_assert(next_uid == 125); + t_array_init(&saved_uids_arr, 128); + mail_index_append_finish_uids(t, 123, &saved_uids_arr); + saved_uids = array_get(&saved_uids_arr, &count); + test_assert(count == 1); + test_assert(saved_uids[0].seq1 == 123 && saved_uids[0].seq2 == 124); appends = array_get(&t->appends, &count); test_assert(appends[0].uid == 123); @@ -99,15 +104,20 @@ test_assert(seq == 9); test_assert(t->highest_append_uid == 128); - mail_index_append_assign_uids(t, 129, &next_uid); - test_assert(next_uid == 131); + mail_index_append_finish_uids(t, 125, &saved_uids_arr); + saved_uids = array_get(&saved_uids_arr, &count); + test_assert(count == 4); + test_assert(saved_uids[0].seq1 == 129 && saved_uids[0].seq2 == 129); + test_assert(saved_uids[1].seq1 == 126 && saved_uids[1].seq2 == 126); + test_assert(saved_uids[2].seq1 == 130 && saved_uids[2].seq2 == 131); + test_assert(saved_uids[3].seq1 == 128 && saved_uids[3].seq2 == 128); appends = array_get(&t->appends, &count); test_assert(count == 5); test_assert(appends[0].uid == 129); test_assert(appends[1].uid == 126); - test_assert(appends[2].uid == 124); - test_assert(appends[3].uid == 130); + test_assert(appends[2].uid == 130); + test_assert(appends[3].uid == 131); test_assert(appends[4].uid == 128); test_end(); }
--- a/src/lib-storage/index/cydir/cydir-save.c Mon Jul 27 18:54:02 2009 -0400 +++ b/src/lib-storage/index/cydir/cydir-save.c Mon Jul 27 19:00:56 2009 -0400 @@ -232,11 +232,11 @@ { struct mailbox_transaction_context *_t = ctx->ctx.transaction; const struct mail_index_header *hdr; - struct seq_range *range; - uint32_t i, uid, next_uid; + struct seq_range_iter iter; + uint32_t uid; const char *dir; string_t *src_path, *dest_path; - unsigned int src_prefixlen, dest_prefixlen; + unsigned int n, src_prefixlen, dest_prefixlen; i_assert(ctx->finished); @@ -247,13 +247,9 @@ } hdr = mail_index_get_header(ctx->sync_ctx->sync_view); - uid = hdr->next_uid; - mail_index_append_assign_uids(ctx->trans, uid, &next_uid); - + mail_index_append_finish_uids(ctx->trans, hdr->next_uid, + &_t->changes->saved_uids); _t->changes->uid_validity = ctx->sync_ctx->uid_validity; - range = array_append_space(&_t->changes->saved_uids); - range->seq1 = uid; - range->seq2 = next_uid - 1; dir = mailbox_list_get_path(ctx->mbox->ibox.box.list, ctx->mbox->ibox.box.name, @@ -268,10 +264,11 @@ str_append_c(dest_path, '/'); dest_prefixlen = str_len(dest_path); - for (i = 0; i < ctx->mail_count; i++, uid++) { + seq_range_array_iter_init(&iter, &_t->changes->saved_uids); n = 0; + while (seq_range_array_iter_nth(&iter, n++, &uid) > 0) { str_truncate(src_path, src_prefixlen); str_truncate(dest_path, dest_prefixlen); - str_printfa(src_path, "%u", i); + str_printfa(src_path, "%u", n-1); str_printfa(dest_path, "%u.", uid); if (rename(str_c(src_path), str_c(dest_path)) < 0) {
--- a/src/lib-storage/index/dbox/dbox-map.c Mon Jul 27 18:54:02 2009 -0400 +++ b/src/lib-storage/index/dbox/dbox-map.c Mon Jul 27 19:00:56 2009 -0400 @@ -964,7 +964,9 @@ const struct mail_index_header *hdr; struct dbox_mail_index_map_record rec; unsigned int i, count; - uint32_t seq, first_uid, next_uid; + ARRAY_TYPE(seq_range) uids; + const struct seq_range *range; + uint32_t seq; uint16_t ref16; int ret = 0; @@ -998,9 +1000,10 @@ /* assign map UIDs for appended records */ hdr = mail_index_get_header(ctx->sync_view); - first_uid = hdr->next_uid; - mail_index_append_assign_uids(ctx->trans, first_uid, &next_uid); - i_assert(next_uid - first_uid == count); + t_array_init(&uids, 1); + mail_index_append_finish_uids(ctx->trans, hdr->next_uid, &uids); + range = array_idx(&uids, 0); + i_assert(range[0].seq2 - range[0].seq1 + 1 == count); if (hdr->uid_validity == 0) { /* we don't really care about uidvalidity, but it can't be 0 */ @@ -1016,8 +1019,8 @@ return -1; } - *first_map_uid_r = first_uid; - *last_map_uid_r = next_uid - 1; + *first_map_uid_r = range[0].seq1; + *last_map_uid_r = range[0].seq2; return ret; } @@ -1062,21 +1065,26 @@ } int dbox_map_append_assign_uids(struct dbox_map_append_context *ctx, - uint32_t first_uid, uint32_t last_uid) + const ARRAY_TYPE(seq_range) *uids) { struct dbox_file *const *files; - unsigned int i, count; - uint32_t next_uid = first_uid; + struct seq_range_iter iter; + unsigned int i, count, n = 0; + uint32_t uid; + bool ret; + seq_range_array_iter_init(&iter, uids); files = array_get(&ctx->files, &count); for (i = 0; i < count; i++) { if (files[i]->single_mbox == NULL) continue; - if (dbox_file_assign_id(files[i], next_uid++) < 0) + ret = seq_range_array_iter_nth(&iter, n++, &uid); + i_assert(ret); + if (dbox_file_assign_id(files[i], uid) < 0) return -1; } - i_assert(next_uid == last_uid + 1); + i_assert(!seq_range_array_iter_nth(&iter, n, &uid)); return 0; }
--- a/src/lib-storage/index/dbox/dbox-map.h Mon Jul 27 18:54:02 2009 -0400 +++ b/src/lib-storage/index/dbox/dbox-map.h Mon Jul 27 19:00:56 2009 -0400 @@ -77,7 +77,7 @@ uint32_t *last_map_uid_r); /* Assign UIDs to all created single-files. */ int dbox_map_append_assign_uids(struct dbox_map_append_context *ctx, - uint32_t first_uid, uint32_t last_uid); + const ARRAY_TYPE(seq_range) *uids); /* The appends are existing messages that were simply moved to a new file. map_uids contains the moved messages' map UIDs. */ int dbox_map_append_move(struct dbox_map_append_context *ctx,
--- a/src/lib-storage/index/dbox/dbox-save.c Mon Jul 27 18:54:02 2009 -0400 +++ b/src/lib-storage/index/dbox/dbox-save.c Mon Jul 27 19:00:56 2009 -0400 @@ -310,8 +310,7 @@ { struct mailbox_transaction_context *_t = ctx->ctx.transaction; const struct mail_index_header *hdr; - struct seq_range *range; - uint32_t uid, first_map_uid, last_map_uid, next_uid; + uint32_t first_map_uid, last_map_uid; i_assert(ctx->finished); @@ -334,15 +333,13 @@ /* assign UIDs for new messages */ hdr = mail_index_get_header(ctx->sync_ctx->sync_view); - uid = hdr->next_uid; - mail_index_append_assign_uids(ctx->trans, uid, &next_uid); + mail_index_append_finish_uids(ctx->trans, hdr->next_uid, + &_t->changes->saved_uids); /* if we saved any single-files, rename the files to contain UIDs */ if (ctx->single_count > 0) { - uint32_t last_uid = uid + ctx->single_count - 1; - - if (dbox_map_append_assign_uids(ctx->append_ctx, uid, - last_uid) < 0) { + if (dbox_map_append_assign_uids(ctx->append_ctx, + &_t->changes->saved_uids) < 0) { dbox_transaction_save_rollback(ctx); return -1; } @@ -388,9 +385,6 @@ mail_free(&ctx->mail); _t->changes->uid_validity = hdr->uid_validity; - range = array_append_space(&_t->changes->saved_uids); - range->seq1 = uid; - range->seq2 = next_uid - 1; return 0; }
--- a/src/lib-storage/index/maildir/maildir-save.c Mon Jul 27 18:54:02 2009 -0400 +++ b/src/lib-storage/index/maildir/maildir-save.c Mon Jul 27 19:00:56 2009 -0400 @@ -625,11 +625,11 @@ static int maildir_save_sync_index(struct maildir_save_context *ctx) { - struct maildir_transaction_context *t = - (struct maildir_transaction_context *)ctx->ctx.transaction; + struct mailbox_transaction_context *_t = ctx->ctx.transaction; struct maildir_mailbox *mbox = ctx->mbox; - struct seq_range *range; + const struct seq_range *uids; uint32_t uid, first_uid, next_uid; + unsigned int i, count; int ret; /* we'll need to keep the lock past the sync deinit */ @@ -656,12 +656,19 @@ /* if messages were added to index, assign them UIDs */ first_uid = maildir_uidlist_get_next_uid(mbox->uidlist); i_assert(first_uid != 0); - mail_index_append_assign_uids(ctx->trans, first_uid, &next_uid); - i_assert(next_uid = first_uid + ctx->files_count); + mail_index_append_finish_uids(ctx->trans, first_uid, + &_t->changes->saved_uids); + i_assert(ctx->files_count == seq_range_count(&_t->changes->saved_uids)); /* these mails are all recent in our session */ - for (uid = first_uid; uid < next_uid; uid++) - index_mailbox_set_recent_uid(&mbox->ibox, uid); + next_uid = first_uid; + uids = array_get(&_t->changes->saved_uids, &count); + for (i = 0; i < count; i++) { + if (next_uid < uids[i].seq2) + next_uid = uids[i].seq2; + for (uid = uids[i].seq1; uid <= uids[i].seq2; uid++) + index_mailbox_set_recent_uid(&mbox->ibox, uid); + } if (!mbox->ibox.keep_recent) { /* maildir_sync_index() dropped recent flags from @@ -672,11 +679,6 @@ first_recent_uid), &next_uid, sizeof(next_uid), FALSE); } - - /* this will work even if index isn't updated */ - range = array_append_space(&t->ictx.mailbox_ctx.changes->saved_uids); - range->seq1 = first_uid; - range->seq2 = next_uid - 1; return 0; }