dovecot-2.0: lib-storage: Fixed mailbox_get_expunges() to return...

dovecot at dovecot.org dovecot at dovecot.org
Sat Mar 26 00:42:51 EET 2011


details:   http://hg.dovecot.org/dovecot-2.0/rev/99e3209fc78d
changeset: 12703:99e3209fc78d
user:      Timo Sirainen <tss at iki.fi>
date:      Sat Mar 26 00:33:51 2011 +0200
description:
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.

diffstat:

 src/lib-storage/index/index-fetch.c      |  132 +++++++++++++++++++++++++-------
 src/lib-storage/index/index-storage.h    |    1 +
 src/lib-storage/index/test-index-fetch.c |   11 ++-
 src/lib-storage/mail-storage-private.h   |    1 +
 src/lib-storage/mail-storage.c           |   10 ++-
 src/lib-storage/mail-storage.h           |    5 +
 src/lib-storage/test-mailbox.c           |    1 +
 7 files changed, 130 insertions(+), 31 deletions(-)

diffs (287 lines):

diff -r 8c409049402c -r 99e3209fc78d src/lib-storage/index/index-fetch.c
--- 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;
diff -r 8c409049402c -r 99e3209fc78d src/lib-storage/index/index-storage.h
--- 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 *
diff -r 8c409049402c -r 99e3209fc78d src/lib-storage/index/test-index-fetch.c
--- 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);
diff -r 8c409049402c -r 99e3209fc78d src/lib-storage/mail-storage-private.h
--- 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,
diff -r 8c409049402c -r 99e3209fc78d src/lib-storage/mail-storage.c
--- 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,
diff -r 8c409049402c -r 99e3209fc78d src/lib-storage/mail-storage.h
--- 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,
diff -r 8c409049402c -r 99e3209fc78d src/lib-storage/test-mailbox.c
--- 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;


More information about the dovecot-cvs mailing list