dovecot-2.2: lib-storage: If mailboxes' vsizes are used, keep th...

dovecot at dovecot.org dovecot at dovecot.org
Sat Jul 11 09:20:18 UTC 2015


details:   http://hg.dovecot.org/dovecot-2.2/rev/46cbde67f50b
changeset: 18907:46cbde67f50b
user:      Timo Sirainen <tss at iki.fi>
date:      Sat Jul 11 12:16:56 2015 +0300
description:
lib-storage: If mailboxes' vsizes are used, keep them updated also in mailbox list index.
This allows looking them up quickly without opening the actual mailbox
indexes.

diffstat:

 src/lib-storage/list/mailbox-list-index-backend.c |    2 +-
 src/lib-storage/list/mailbox-list-index-notify.c  |    2 +-
 src/lib-storage/list/mailbox-list-index-status.c  |  131 +++++++++++++++++++--
 src/lib-storage/list/mailbox-list-index.h         |    5 +-
 src/lib-storage/list/mailbox-list-notify-tree.c   |    2 +-
 5 files changed, 122 insertions(+), 20 deletions(-)

diffs (truncated from 309 to 300 lines):

diff -r 421f595a0e93 -r 46cbde67f50b src/lib-storage/list/mailbox-list-index-backend.c
--- a/src/lib-storage/list/mailbox-list-index-backend.c	Sat Jul 11 12:14:48 2015 +0300
+++ b/src/lib-storage/list/mailbox-list-index-backend.c	Sat Jul 11 12:16:56 2015 +0300
@@ -175,7 +175,7 @@
 				       T_MAIL_ERR_MAILBOX_NOT_FOUND(name));
 		ret = -1;
 	} else if (!mailbox_list_index_status(_list, view, seq, 0,
-					      &status, mailbox_guid) ||
+					      &status, mailbox_guid, NULL) ||
 		   guid_128_is_empty(mailbox_guid)) {
 		mailbox_list_set_error(_list, MAIL_ERROR_NOTFOUND,
 				       T_MAIL_ERR_MAILBOX_NOT_FOUND(name));
diff -r 421f595a0e93 -r 46cbde67f50b src/lib-storage/list/mailbox-list-index-notify.c
--- a/src/lib-storage/list/mailbox-list-index-notify.c	Sat Jul 11 12:14:48 2015 +0300
+++ b/src/lib-storage/list/mailbox-list-index-notify.c	Sat Jul 11 12:16:56 2015 +0300
@@ -160,7 +160,7 @@
 	memset(status_r, 0, sizeof(*status_r));
 	memset(guid_r, 0, GUID_128_SIZE);
 	(void)mailbox_list_index_status(inotify->notify.list, view, seq,
-					items, status_r, guid_r);
+					items, status_r, guid_r, NULL);
 	return index_node;
 }
 
diff -r 421f595a0e93 -r 46cbde67f50b src/lib-storage/list/mailbox-list-index-status.c
--- a/src/lib-storage/list/mailbox-list-index-status.c	Sat Jul 11 12:14:48 2015 +0300
+++ b/src/lib-storage/list/mailbox-list-index-status.c	Sat Jul 11 12:16:56 2015 +0300
@@ -14,10 +14,12 @@
 	struct mailbox_status status;
 	guid_128_t guid;
 	uint32_t seq;
+	struct mailbox_index_vsize vsize;
 
 	bool rec_changed;
 	bool msgs_changed;
 	bool hmodseq_changed;
+	bool vsize_changed;
 };
 
 struct index_list_storage_module index_list_storage_module =
@@ -108,7 +110,8 @@
 			       struct mail_index_view *view,
 			       uint32_t seq, enum mailbox_status_items items,
 			       struct mailbox_status *status_r,
-			       uint8_t *mailbox_guid)
+			       uint8_t *mailbox_guid,
+			       struct mailbox_index_vsize *vsize_r)
 {
 	struct mailbox_list_index *ilist = INDEX_LIST_CONTEXT(list);
 	const void *data;
@@ -161,6 +164,14 @@
 		else
 			status_r->highest_modseq = *rec;
 	}
+	if (vsize_r != NULL) {
+		mail_index_lookup_ext(view, seq, ilist->vsize_ext_id,
+				      &data, &expunged);
+		if (data == NULL)
+			ret = FALSE;
+		else
+			memcpy(vsize_r, data, sizeof(*vsize_r));
+	}
 	return ret;
 }
 
@@ -184,7 +195,7 @@
 		return ret;
 
 	ret = mailbox_list_index_status(box->list, view, seq, items,
-					status_r, NULL) ? 1 : 0;
+					status_r, NULL, NULL) ? 1 : 0;
 	mail_index_view_close(&view);
 	return ret;
 }
@@ -221,13 +232,81 @@
 		return ret;
 
 	ret = mailbox_list_index_status(box->list, view, seq, 0,
-					&status, guid_r) ? 1 : 0;
+					&status, guid_r, NULL) ? 1 : 0;
 	if (ret > 0 && guid_128_is_empty(guid_r))
 		ret = 0;
 	mail_index_view_close(&view);
 	return ret;
 }
 
+static int index_list_get_cached_vsize(struct mailbox *box, uoff_t *vsize_r)
+{
+	struct mailbox_list_index *ilist = INDEX_LIST_CONTEXT(box->list);
+	struct mailbox_status status;
+	struct mailbox_index_vsize vsize;
+	struct mail_index_view *view;
+	uint32_t seq;
+	int ret;
+
+	i_assert(!ilist->syncing);
+
+	if ((ret = index_list_open_view(box, &view, &seq)) <= 0)
+		return ret;
+
+	ret = mailbox_list_index_status(box->list, view, seq,
+					STATUS_MESSAGES | STATUS_UIDNEXT,
+					&status, NULL, &vsize) ? 1 : 0;
+	if (ret > 0 && (vsize.highest_uid + 1 != status.uidnext ||
+			vsize.message_count != status.messages)) {
+		/* out of date vsize info */
+		ret = 0;
+	}
+	if (ret > 0)
+		*vsize_r = vsize.vsize;
+	mail_index_view_close(&view);
+	return ret;
+}
+
+static int
+index_list_try_get_metadata(struct mailbox *box,
+			    enum mailbox_metadata_items items,
+			    struct mailbox_metadata *metadata_r)
+{
+	enum mailbox_metadata_items noncached_items;
+	int ret;
+
+	if (box->opened) {
+		/* if mailbox is already opened, don't bother using the values
+		   in mailbox list index. they have a higher chance of being
+		   wrong. */
+		return 0;
+	}
+	/* see if we have a chance of fulfilling this without opening
+	   the mailbox. */
+	noncached_items = items & ~(MAILBOX_METADATA_GUID |
+				    MAILBOX_METADATA_VIRTUAL_SIZE);
+	if ((noncached_items & MAILBOX_METADATA_PHYSICAL_SIZE) != 0 &&
+	    box->mail_vfuncs->get_physical_size ==
+	    box->mail_vfuncs->get_virtual_size)
+		noncached_items = items & ~MAILBOX_METADATA_PHYSICAL_SIZE;
+
+	if (noncached_items != 0)
+		return 0;
+
+	if ((items & MAILBOX_METADATA_GUID) != 0) {
+		if ((ret = index_list_get_cached_guid(box, metadata_r->guid)) <= 0)
+			return ret;
+	}
+	if ((items & (MAILBOX_METADATA_VIRTUAL_SIZE |
+		      MAILBOX_METADATA_PHYSICAL_SIZE)) != 0) {
+		if ((ret = index_list_get_cached_vsize(box, &metadata_r->virtual_size)) <= 0)
+			return ret;
+		if ((items & MAILBOX_METADATA_PHYSICAL_SIZE) != 0)
+			metadata_r->physical_size = metadata_r->virtual_size;
+	}
+	return 1;
+}
+
 static int
 index_list_get_metadata(struct mailbox *box,
 			enum mailbox_metadata_items items,
@@ -235,14 +314,25 @@
 {
 	struct index_list_mailbox *ibox = INDEX_LIST_STORAGE_CONTEXT(box);
 
-	if (items == MAILBOX_METADATA_GUID && !box->opened) {
-		if (index_list_get_cached_guid(box, metadata_r->guid) > 0)
-			return 0;
-		/* nonsynced / error, fallback to doing it the slow way */
-	}
+	if (index_list_try_get_metadata(box, items, metadata_r) != 0)
+		return 0;
 	return ibox->module_ctx.super.get_metadata(box, items, metadata_r);
 }
 
+static void
+index_list_update_fill_vsize(struct mailbox *box,
+			     struct mail_index_view *view,
+			     struct index_list_changes *changes_r)
+{
+	const void *data;
+	size_t size;
+
+	mail_index_get_header_ext(view, box->vsize_hdr_ext_id,
+				  &data, &size);
+	if (size == sizeof(changes_r->vsize))
+		memcpy(&changes_r->vsize, data, sizeof(changes_r->vsize));
+}
+
 static bool
 index_list_update_fill_changes(struct mailbox *box,
 			       struct mail_index_view *list_view,
@@ -286,6 +376,7 @@
 		/* modseqs not enabled yet, but we can't return 0 */
 		changes_r->status.highest_modseq = 1;
 	}
+	index_list_update_fill_vsize(box, view, changes_r);
 	mail_index_view_close(&view); hdr = NULL;
 
 	if (mailbox_get_metadata(box, MAILBOX_METADATA_GUID, &metadata) == 0)
@@ -299,13 +390,15 @@
 {
 	struct mailbox_list_index *ilist = INDEX_LIST_CONTEXT(box->list);
 	struct mailbox_status old_status;
+	struct mailbox_index_vsize old_vsize;
 	guid_128_t old_guid;
 
 	memset(&old_status, 0, sizeof(old_status));
+	memset(&old_vsize, 0, sizeof(old_vsize));
 	memset(old_guid, 0, sizeof(old_guid));
 	(void)mailbox_list_index_status(box->list, list_view, changes->seq,
 					CACHED_STATUS_ITEMS,
-					&old_status, old_guid);
+					&old_status, old_guid, &old_vsize);
 
 	changes->rec_changed =
 		old_status.uidvalidity != changes->status.uidvalidity &&
@@ -331,13 +424,11 @@
 				      ilist->hmodseq_ext_id, &data, &expunged);
 		changes->hmodseq_changed = data != NULL;
 	}
-
-	if (changes->hmodseq_changed &&
-	    old_status.highest_modseq != changes->status.highest_modseq)
-		changes->hmodseq_changed = TRUE;
+	if (memcmp(&old_vsize, &changes->vsize, sizeof(old_vsize)) != 0)
+		changes->vsize_changed = TRUE;
 
 	return changes->rec_changed || changes->msgs_changed ||
-		changes->hmodseq_changed;
+		changes->hmodseq_changed || changes->vsize_changed;
 }
 
 static void
@@ -382,6 +473,11 @@
 				      ilist->hmodseq_ext_id,
 				      &changes->status.highest_modseq, NULL);
 	}
+	if (changes->vsize_changed) {
+		mail_index_update_ext(list_trans, changes->seq,
+				      ilist->vsize_ext_id,
+				      &changes->vsize, NULL);
+	}
 }
 
 static int index_list_update_mailbox(struct mailbox *box)
@@ -482,7 +578,7 @@
 
 	(void)mailbox_list_index_status(box->list, list_view, changes.seq,
 					CACHED_STATUS_ITEMS, &status,
-					mailbox_guid);
+					mailbox_guid, NULL);
 	if (update->uid_validity != 0) {
 		changes.rec_changed = TRUE;
 		changes.status.uidvalidity = update->uid_validity;
@@ -575,7 +671,7 @@
 
 	status.recent = 0;
 	(void)mailbox_list_index_status(box->list, view, seq, STATUS_RECENT,
-					&status, NULL);
+					&status, NULL, NULL);
 	mail_index_view_close(&view);
 
 	if (status.recent != 0)
@@ -604,4 +700,7 @@
 	ilist->hmodseq_ext_id =
 		mail_index_ext_register(ilist->index, "hmodseq", 0,
 					sizeof(uint64_t), sizeof(uint64_t));
+	ilist->vsize_ext_id =
+		mail_index_ext_register(ilist->index, "vsize", 0,
+			sizeof(struct mailbox_index_vsize), sizeof(uint64_t));
 }
diff -r 421f595a0e93 -r 46cbde67f50b src/lib-storage/list/mailbox-list-index.h
--- a/src/lib-storage/list/mailbox-list-index.h	Sat Jul 11 12:14:48 2015 +0300
+++ b/src/lib-storage/list/mailbox-list-index.h	Sat Jul 11 12:16:56 2015 +0300
@@ -36,6 +36,7 @@
 	MODULE_CONTEXT(obj, mailbox_list_index_module)
 
 struct mail_index_view;
+struct mailbox_index_vsize;
 
 /* stored in mail_index_record.flags: */
 enum mailbox_list_index_flags {
@@ -88,6 +89,7 @@
 	const char *path;
 	struct mail_index *index;
 	uint32_t ext_id, msgs_ext_id, hmodseq_ext_id, subs_hdr_ext_id;
+	uint32_t vsize_ext_id;
 	struct timeval last_refresh_timeval;
 
 	pool_t mailbox_pool;
@@ -170,7 +172,8 @@
 			       struct mail_index_view *view,
 			       uint32_t seq, enum mailbox_status_items items,
 			       struct mailbox_status *status_r,
-			       uint8_t *mailbox_guid);
+			       uint8_t *mailbox_guid,
+			       struct mailbox_index_vsize *vsize_r);
 void mailbox_list_index_status_set_info_flags(struct mailbox *box, uint32_t uid,
 					      enum mailbox_info_flags *flags);
 void mailbox_list_index_update_mailbox_index(struct mailbox *box,
diff -r 421f595a0e93 -r 46cbde67f50b src/lib-storage/list/mailbox-list-notify-tree.c
--- a/src/lib-storage/list/mailbox-list-notify-tree.c	Sat Jul 11 12:14:48 2015 +0300
+++ b/src/lib-storage/list/mailbox-list-notify-tree.c	Sat Jul 11 12:16:56 2015 +0300


More information about the dovecot-cvs mailing list