Mercurial > dovecot > core-2.2
changeset 12910:99e3209fc78d
lib-storage: Fixed mailbox_get_expunges() to return GUIDs with all mailbox formats.
Also added mailbox_get_expunged_uids() for use cases that don't really need
GUIDs.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sat, 26 Mar 2011 00:33:51 +0200 |
parents | 8c409049402c |
children | e5547c86528f |
files | src/lib-storage/index/index-fetch.c src/lib-storage/index/index-storage.h src/lib-storage/index/test-index-fetch.c src/lib-storage/mail-storage-private.h src/lib-storage/mail-storage.c src/lib-storage/mail-storage.h src/lib-storage/test-mailbox.c |
diffstat | 7 files changed, 130 insertions(+), 31 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-storage/index/index-fetch.c Thu Mar 24 00:28:06 2011 +0200 +++ b/src/lib-storage/index/index-fetch.c Sat Mar 26 00:33:51 2011 +0200 @@ -37,51 +37,40 @@ } static void -add_expunges(ARRAY_TYPE(mailbox_expunge_rec) *expunges, - const struct mail_transaction_expunge *src, size_t src_size, - const ARRAY_TYPE(seq_range) *uids_filter) +add_expunges(ARRAY_TYPE(seq_range) *expunged_uids, uint32_t min_uid, + const struct mail_transaction_expunge *src, size_t src_size) { const struct mail_transaction_expunge *end; - struct mailbox_expunge_rec *expunge; - uint32_t uid; end = src + src_size / sizeof(*src); for (; src != end; src++) { - for (uid = src->uid1; uid <= src->uid2; uid++) { - if (seq_range_exists(uids_filter, uid)) { - expunge = array_append_space(expunges); - expunge->uid = uid; - } + if (src->uid2 >= min_uid) { + seq_range_array_add_range(expunged_uids, + src->uid1, src->uid2); } } } static void -add_guid_expunges(ARRAY_TYPE(mailbox_expunge_rec) *expunges, +add_guid_expunges(ARRAY_TYPE(seq_range) *expunged_uids, uint32_t min_uid, const struct mail_transaction_expunge_guid *src, - size_t src_size, const ARRAY_TYPE(seq_range) *uids_filter) + size_t src_size) { const struct mail_transaction_expunge_guid *end; - struct mailbox_expunge_rec *expunge; end = src + src_size / sizeof(*src); for (; src != end; src++) { - if (seq_range_exists(uids_filter, src->uid)) { - expunge = array_append_space(expunges); - expunge->uid = src->uid; - memcpy(expunge->guid_128, src->guid_128, - sizeof(expunge->guid_128)); - } + if (src->uid >= min_uid) + seq_range_array_add(expunged_uids, 0, src->uid); } } -bool index_storage_get_expunges(struct mailbox *box, uint64_t prev_modseq, - const ARRAY_TYPE(seq_range) *uids_filter, - ARRAY_TYPE(mailbox_expunge_rec) *expunges) +static int +index_storage_get_expunges_init(struct mailbox *box, uint64_t prev_modseq, + struct mail_transaction_log_view **log_view_r, + uint32_t *tail_seq_r) { struct mail_transaction_log_view *log_view; - const struct mail_transaction_header *thdr; - const void *tdata; uint32_t log_seq, tail_seq = 0; uoff_t log_offset; bool reset; @@ -96,7 +85,7 @@ (log_seq == box->view->log_file_head_seq && log_offset >= box->view->log_file_head_offset)) { /* we haven't seen this high expunges at all */ - return TRUE; + return 1; } log_view = mail_transaction_log_view_open(box->index->log); @@ -115,9 +104,84 @@ } if (ret <= 0) { mail_transaction_log_view_close(&log_view); - return FALSE; + return -1; } + *log_view_r = log_view; + *tail_seq_r = tail_seq; + return 0; +} + +static void +index_storage_get_expunged_guids(struct mail_transaction_log_view *log_view, + ARRAY_TYPE(seq_range) *expunged_uids, + ARRAY_TYPE(mailbox_expunge_rec) *expunges) +{ + const struct mail_transaction_header *thdr; + const void *tdata; + const struct mail_transaction_expunge_guid *rec, *end; + struct mailbox_expunge_rec *expunge; + struct seq_range_iter iter; + unsigned int n; + uint32_t uid; + + while (mail_transaction_log_view_next(log_view, &thdr, &tdata) > 0) { + if ((thdr->type & MAIL_TRANSACTION_TYPE_MASK) != + MAIL_TRANSACTION_EXPUNGE_GUID) + continue; + + rec = tdata; + end = rec + thdr->size / sizeof(*rec); + for (; rec != end; rec++) { + if (!seq_range_exists(expunged_uids, rec->uid)) + continue; + seq_range_array_remove(expunged_uids, rec->uid); + + expunge = array_append_space(expunges); + expunge->uid = rec->uid; + memcpy(expunge->guid_128, rec->guid_128, + sizeof(expunge->guid_128)); + } + } + + /* everything left in expunged_uids didn't get a GUID */ + seq_range_array_iter_init(&iter, expunged_uids); n = 0; + while (seq_range_array_iter_nth(&iter, n++, &uid)) { + expunge = array_append_space(expunges); + expunge->uid = uid; + } +} + +bool index_storage_get_expunges(struct mailbox *box, uint64_t prev_modseq, + const ARRAY_TYPE(seq_range) *uids_filter, + ARRAY_TYPE(seq_range) *expunged_uids, + ARRAY_TYPE(mailbox_expunge_rec) *expunges) +{ + struct mail_transaction_log_view *log_view; + ARRAY_TYPE(seq_range) tmp_expunged_uids = ARRAY_INIT; + const struct mail_transaction_header *thdr; + const struct seq_range *range; + const void *tdata; + uint32_t min_uid, tail_seq; + int ret; + + i_assert(array_count(uids_filter) > 0); + i_assert(expunged_uids == NULL || expunges == NULL); + + ret = index_storage_get_expunges_init(box, prev_modseq, + &log_view, &tail_seq); + if (ret != 0) + return ret > 0; + + range = array_idx(uids_filter, 0); + min_uid = range->seq1; + + /* first get UIDs of all actual expunges */ + if (expunged_uids == NULL) { + i_array_init(&tmp_expunged_uids, 64); + expunged_uids = &tmp_expunged_uids; + } + mail_transaction_log_view_mark(log_view); while ((ret = mail_transaction_log_view_next(log_view, &thdr, &tdata)) > 0) { if ((thdr->type & MAIL_TRANSACTION_EXTERNAL) == 0) { @@ -126,14 +190,24 @@ } switch (thdr->type & MAIL_TRANSACTION_TYPE_MASK) { case MAIL_TRANSACTION_EXPUNGE: - add_expunges(expunges, tdata, thdr->size, uids_filter); + add_expunges(expunged_uids, min_uid, tdata, thdr->size); break; case MAIL_TRANSACTION_EXPUNGE_GUID: - add_guid_expunges(expunges, tdata, thdr->size, - uids_filter); + add_guid_expunges(expunged_uids, min_uid, + tdata, thdr->size); break; } } + mail_transaction_log_view_rewind(log_view); + + /* drop UIDs that don't match the filter */ + seq_range_array_intersect(expunged_uids, uids_filter); + + if (expunges != NULL) { + index_storage_get_expunged_guids(log_view, expunged_uids, + expunges); + array_free(&tmp_expunged_uids); + } mail_transaction_log_view_close(&log_view); return ret < 0 || tail_seq != 0 ? FALSE : TRUE;
--- a/src/lib-storage/index/index-storage.h Thu Mar 24 00:28:06 2011 +0200 +++ b/src/lib-storage/index/index-storage.h Sat Mar 26 00:33:51 2011 +0200 @@ -137,6 +137,7 @@ ARRAY_TYPE(seq_range) *uids); bool index_storage_get_expunges(struct mailbox *box, uint64_t prev_modseq, const ARRAY_TYPE(seq_range) *uids_filter, + ARRAY_TYPE(seq_range) *expunged_uids, ARRAY_TYPE(mailbox_expunge_rec) *expunges); struct mailbox_header_lookup_ctx *
--- a/src/lib-storage/index/test-index-fetch.c Thu Mar 24 00:28:06 2011 +0200 +++ b/src/lib-storage/index/test-index-fetch.c Sat Mar 26 00:33:51 2011 +0200 @@ -85,6 +85,15 @@ return 1; } +void mail_transaction_log_view_mark(struct mail_transaction_log_view *view ATTR_UNUSED) +{ +} + +void mail_transaction_log_view_rewind(struct mail_transaction_log_view *view ATTR_UNUSED) +{ + expunge_idx = 0; +} + static void test_index_storage_get_expunges(void) { struct mailbox *box; @@ -115,7 +124,7 @@ modseq = 98ULL << 32; for (i = 0; i < 2; i++) { test_assert(index_storage_get_expunges(box, modseq, &uids_filter, - &expunges) == i); + NULL, &expunges) == i); exp = array_get(&expunges, &count); test_assert(count == 5);
--- a/src/lib-storage/mail-storage-private.h Thu Mar 24 00:28:06 2011 +0200 +++ b/src/lib-storage/mail-storage-private.h Sat Mar 26 00:33:51 2011 +0200 @@ -173,6 +173,7 @@ ARRAY_TYPE(seq_range) *uids); bool (*get_expunges)(struct mailbox *box, uint64_t prev_modseq, const ARRAY_TYPE(seq_range) *uids_filter, + ARRAY_TYPE(seq_range) *expunged_uids, ARRAY_TYPE(mailbox_expunge_rec) *expunges); bool (*get_virtual_uid)(struct mailbox *box, const char *backend_mailbox,
--- a/src/lib-storage/mail-storage.c Thu Mar 24 00:28:06 2011 +0200 +++ b/src/lib-storage/mail-storage.c Sat Mar 26 00:33:51 2011 +0200 @@ -1079,7 +1079,15 @@ ARRAY_TYPE(mailbox_expunge_rec) *expunges) { return box->v.get_expunges(box, prev_modseq, - uids_filter, expunges); + uids_filter, NULL, expunges); +} + +bool mailbox_get_expunged_uids(struct mailbox *box, uint64_t prev_modseq, + const ARRAY_TYPE(seq_range) *uids_filter, + ARRAY_TYPE(seq_range) *expunged_uids) +{ + return box->v.get_expunges(box, prev_modseq, + uids_filter, expunged_uids, NULL); } bool mailbox_get_virtual_uid(struct mailbox *box, const char *backend_mailbox,
--- a/src/lib-storage/mail-storage.h Thu Mar 24 00:28:06 2011 +0200 +++ b/src/lib-storage/mail-storage.h Sat Mar 26 00:33:51 2011 +0200 @@ -464,6 +464,11 @@ bool mailbox_get_expunges(struct mailbox *box, uint64_t prev_modseq, const ARRAY_TYPE(seq_range) *uids_filter, ARRAY_TYPE(mailbox_expunge_rec) *expunges); +/* Same as mailbox_get_expunges(), but return only list of UIDs. Not caring + about GUIDs is slightly faster. */ +bool mailbox_get_expunged_uids(struct mailbox *box, uint64_t prev_modseq, + const ARRAY_TYPE(seq_range) *uids_filter, + ARRAY_TYPE(seq_range) *expunged_uids); /* If box is a virtual mailbox, look up UID for the given backend message. Returns TRUE if found, FALSE if not. */ bool mailbox_get_virtual_uid(struct mailbox *box, const char *backend_mailbox,
--- a/src/lib-storage/test-mailbox.c Thu Mar 24 00:28:06 2011 +0200 +++ b/src/lib-storage/test-mailbox.c Sat Mar 26 00:33:51 2011 +0200 @@ -207,6 +207,7 @@ test_mailbox_get_expunged_uids(struct mailbox *box ATTR_UNUSED, uint64_t prev_modseq ATTR_UNUSED, const ARRAY_TYPE(seq_range) *uids_filter ATTR_UNUSED, + ARRAY_TYPE(seq_range) *expunged_uids ATTR_UNUSED, ARRAY_TYPE(mailbox_expunge_rec) *expunges ATTR_UNUSED) { return FALSE;