dovecot-2.2: virtual: Delay opening the backend mailboxes until ...

dovecot at dovecot.org dovecot at dovecot.org
Tue Apr 15 15:20:51 UTC 2014


details:   http://hg.dovecot.org/dovecot-2.2/rev/b9bc20b1ef91
changeset: 17214:b9bc20b1ef91
user:      Timo Sirainen <tss at iki.fi>
date:      Tue Apr 15 17:20:02 2014 +0200
description:
virtual: Delay opening the backend mailboxes until it's really necessary.
This should improve the performance a lot with mailbox_list_index=yes when
opening virtual mailboxes whose backend mailboxes are mostly unchanged.

diffstat:

 src/plugins/virtual/virtual-mail.c    |  228 ++++++++++++++++++++-------------
 src/plugins/virtual/virtual-save.c    |   33 +++-
 src/plugins/virtual/virtual-storage.c |   75 +++++++----
 src/plugins/virtual/virtual-storage.h |    1 +
 src/plugins/virtual/virtual-sync.c    |   55 ++++++-
 5 files changed, 256 insertions(+), 136 deletions(-)

diffs (truncated from 776 to 300 lines):

diff -r 13ead8c6aed5 -r b9bc20b1ef91 src/plugins/virtual/virtual-mail.c
--- a/src/plugins/virtual/virtual-mail.c	Tue Apr 15 17:08:34 2014 +0200
+++ b/src/plugins/virtual/virtual-mail.c	Tue Apr 15 17:20:02 2014 +0200
@@ -13,12 +13,14 @@
 	struct mailbox_header_lookup_ctx *wanted_headers;
 
 	/* currently active mail */
-	struct mail *backend_mail;
+	struct mail *cur_backend_mail;
+	struct virtual_mail_index_record cur_vrec;
+
 	/* all allocated mails */
 	ARRAY(struct mail *) backend_mails;
 
 	/* mail is lost if backend_mail doesn't point to correct mail */
-	unsigned int lost:1;
+	unsigned int cur_lost:1;
 };
 
 struct mail *
@@ -85,6 +87,44 @@
 	return NULL;
 }
 
+static int backend_mail_get(struct virtual_mail *vmail,
+			    struct mail **backend_mail_r)
+{
+	struct mail *mail = &vmail->imail.mail.mail;
+	struct virtual_mailbox *mbox = (struct virtual_mailbox *)mail->box;
+	struct virtual_backend_box *bbox;
+
+	*backend_mail_r = NULL;
+
+	if (vmail->cur_backend_mail != NULL) {
+		if (vmail->cur_lost) {
+			mail_set_expunged(&vmail->imail.mail.mail);
+			return -1;
+		}
+		*backend_mail_r = vmail->cur_backend_mail;
+		return 0;
+	}
+
+	bbox = virtual_backend_box_lookup(mbox, vmail->cur_vrec.mailbox_id);
+	vmail->cur_backend_mail = backend_mail_find(vmail, bbox->box);
+	if (vmail->cur_backend_mail == NULL) {
+		if (mailbox_open(bbox->box) < 0) {
+			virtual_box_copy_error(mail->box, bbox->box);
+			return -1;
+		}
+		(void)virtual_mail_set_backend_mail(mail, bbox);
+	}
+	vmail->cur_lost = !mail_set_uid(vmail->cur_backend_mail,
+					vmail->cur_vrec.real_uid);
+	mail->expunged = vmail->cur_lost || vmail->cur_backend_mail->expunged;
+	if (vmail->cur_lost) {
+		mail_set_expunged(&vmail->imail.mail.mail);
+		return -1;
+	}
+	*backend_mail_r = vmail->cur_backend_mail;
+	return 0;
+}
+
 struct mail *
 virtual_mail_set_backend_mail(struct mail *mail,
 			      struct virtual_backend_box *bbox)
@@ -94,41 +134,36 @@
 	struct mailbox_transaction_context *backend_trans;
 	struct mailbox_header_lookup_ctx *backend_headers;
 
+	i_assert(bbox->box->opened);
+
 	backend_trans = virtual_transaction_get(mail->transaction, bbox->box);
 
 	backend_headers = vmail->wanted_headers == NULL ? NULL :
 		mailbox_header_lookup_init(bbox->box,
 					   vmail->wanted_headers->name);
-	vmail->backend_mail = mail_alloc(backend_trans, vmail->wanted_fields,
-					 backend_headers);
+	vmail->cur_backend_mail =
+		mail_alloc(backend_trans, vmail->wanted_fields, backend_headers);
 	if (backend_headers != NULL)
 		mailbox_header_lookup_unref(&backend_headers);
 
-	backend_pmail = (struct mail_private *)vmail->backend_mail;
+	backend_pmail = (struct mail_private *)vmail->cur_backend_mail;
 	backend_pmail->vmail = mail;
-	array_append(&vmail->backend_mails, &vmail->backend_mail, 1);
-	return vmail->backend_mail;
+	array_append(&vmail->backend_mails, &vmail->cur_backend_mail, 1);
+	return vmail->cur_backend_mail;
 }
 
 static void virtual_mail_set_seq(struct mail *mail, uint32_t seq, bool saving)
 {
 	struct virtual_mail *vmail = (struct virtual_mail *)mail;
 	struct virtual_mailbox *mbox = (struct virtual_mailbox *)mail->box;
-	struct virtual_backend_box *bbox;
-	const struct virtual_mail_index_record *vrec;
 	const void *data;
 
 	i_assert(!saving);
 
 	mail_index_lookup_ext(mail->transaction->view, seq,
 			      mbox->virtual_ext_id, &data, NULL);
-	vrec = data;
+	memcpy(&vmail->cur_vrec, data, sizeof(vmail->cur_vrec));
 
-	bbox = virtual_backend_box_lookup(mbox, vrec->mailbox_id);
-	vmail->backend_mail = backend_mail_find(vmail, bbox->box);
-	if (vmail->backend_mail == NULL)
-		(void)virtual_mail_set_backend_mail(mail, bbox);
-	vmail->lost = !mail_set_uid(vmail->backend_mail, vrec->real_uid);
 	memset(&vmail->imail.data, 0, sizeof(vmail->imail.data));
 	p_clear(vmail->imail.mail.data_pool);
 
@@ -136,15 +171,7 @@
 	mail->seq = seq;
 	mail_index_lookup_uid(mail->transaction->view, seq, &mail->uid);
 
-	if (!vmail->lost) {
-		mail->expunged = vmail->backend_mail->expunged;
-		mail->has_nuls = vmail->backend_mail->has_nuls;
-		mail->has_no_nuls = vmail->backend_mail->has_no_nuls;
-	} else {
-		mail->expunged = TRUE;
-		mail->has_nuls = FALSE;
-		mail->has_no_nuls = FALSE;
-	}
+	vmail->cur_backend_mail = NULL;
 }
 
 static bool virtual_mail_set_uid(struct mail *mail, uint32_t uid)
@@ -161,25 +188,37 @@
 static void virtual_mail_set_uid_cache_updates(struct mail *mail, bool set)
 {
 	struct virtual_mail *vmail = (struct virtual_mail *)mail;
-	struct mail_private *p = (struct mail_private *)vmail->backend_mail;
+	struct mail *backend_mail;
+	struct mail_private *p;
 
-	p->v.set_uid_cache_updates(vmail->backend_mail, set);
+	if (backend_mail_get(vmail, &backend_mail) < 0)
+		return;
+	p = (struct mail_private *)backend_mail;
+	p->v.set_uid_cache_updates(backend_mail, set);
 }
 
 static bool virtual_mail_prefetch(struct mail *mail)
 {
 	struct virtual_mail *vmail = (struct virtual_mail *)mail;
-	struct mail_private *p = (struct mail_private *)vmail->backend_mail;
+	struct mail *backend_mail;
+	struct mail_private *p;
 
-	return p->v.prefetch(vmail->backend_mail);
+	if (backend_mail_get(vmail, &backend_mail) < 0)
+		return TRUE;
+	p = (struct mail_private *)backend_mail;
+	return p->v.prefetch(backend_mail);
 }
 
 static void virtual_mail_precache(struct mail *mail)
 {
 	struct virtual_mail *vmail = (struct virtual_mail *)mail;
-	struct mail_private *p = (struct mail_private *)vmail->backend_mail;
+	struct mail *backend_mail;
+	struct mail_private *p;
 
-	p->v.precache(vmail->backend_mail);
+	if (backend_mail_get(vmail, &backend_mail) < 0)
+		return;
+	p = (struct mail_private *)backend_mail;
+	p->v.precache(backend_mail);
 }
 
 static void
@@ -188,29 +227,25 @@
 				    struct mailbox_header_lookup_ctx *headers)
 {
 	struct virtual_mail *vmail = (struct virtual_mail *)mail;
-	struct mail_private *p = (struct mail_private *)vmail->backend_mail;
+	struct mail *backend_mail;
+	struct mail_private *p;
 
-	p->v.add_temp_wanted_fields(vmail->backend_mail, fields, headers);
-}
-
-static int virtual_mail_handle_lost(struct virtual_mail *vmail)
-{
-	if (!vmail->lost)
-		return 0;
-
-	mail_set_expunged(&vmail->imail.mail.mail);
-	return -1;
+	if (backend_mail_get(vmail, &backend_mail) < 0)
+		return;
+	p = (struct mail_private *)backend_mail;
+	p->v.add_temp_wanted_fields(backend_mail, fields, headers);
 }
 
 static int
 virtual_mail_get_parts(struct mail *mail, struct message_part **parts_r)
 {
 	struct virtual_mail *vmail = (struct virtual_mail *)mail;
+	struct mail *backend_mail;
 
-	if (virtual_mail_handle_lost(vmail) < 0)
+	if (backend_mail_get(vmail, &backend_mail) < 0)
 		return -1;
-	if (mail_get_parts(vmail->backend_mail, parts_r) < 0) {
-		virtual_box_copy_error(mail->box, vmail->backend_mail->box);
+	if (mail_get_parts(backend_mail, parts_r) < 0) {
+		virtual_box_copy_error(mail->box, backend_mail->box);
 		return -1;
 	}
 	return 0;
@@ -220,15 +255,16 @@
 virtual_mail_get_date(struct mail *mail, time_t *date_r, int *timezone_r)
 {
 	struct virtual_mail *vmail = (struct virtual_mail *)mail;
+	struct mail *backend_mail;
 	int tz;
 
 	if (timezone_r == NULL)
 		timezone_r = &tz;
 
-	if (virtual_mail_handle_lost(vmail) < 0)
+	if (backend_mail_get(vmail, &backend_mail) < 0)
 		return -1;
-	if (mail_get_date(vmail->backend_mail, date_r, timezone_r) < 0) {
-		virtual_box_copy_error(mail->box, vmail->backend_mail->box);
+	if (mail_get_date(backend_mail, date_r, timezone_r) < 0) {
+		virtual_box_copy_error(mail->box, backend_mail->box);
 		return -1;
 	}
 	return 0;
@@ -237,11 +273,12 @@
 static int virtual_mail_get_received_date(struct mail *mail, time_t *date_r)
 {
 	struct virtual_mail *vmail = (struct virtual_mail *)mail;
+	struct mail *backend_mail;
 
-	if (virtual_mail_handle_lost(vmail) < 0)
+	if (backend_mail_get(vmail, &backend_mail) < 0)
 		return -1;
-	if (mail_get_received_date(vmail->backend_mail, date_r) < 0) {
-		virtual_box_copy_error(mail->box, vmail->backend_mail->box);
+	if (mail_get_received_date(backend_mail, date_r) < 0) {
+		virtual_box_copy_error(mail->box, backend_mail->box);
 		return -1;
 	}
 	return 0;
@@ -250,11 +287,12 @@
 static int virtual_mail_get_save_date(struct mail *mail, time_t *date_r)
 {
 	struct virtual_mail *vmail = (struct virtual_mail *)mail;
+	struct mail *backend_mail;
 
-	if (virtual_mail_handle_lost(vmail) < 0)
+	if (backend_mail_get(vmail, &backend_mail) < 0)
 		return -1;
-	if (mail_get_save_date(vmail->backend_mail, date_r) < 0) {
-		virtual_box_copy_error(mail->box, vmail->backend_mail->box);
+	if (mail_get_save_date(backend_mail, date_r) < 0) {
+		virtual_box_copy_error(mail->box, backend_mail->box);
 		return -1;
 	}
 	return 0;
@@ -263,11 +301,12 @@
 static int virtual_mail_get_virtual_mail_size(struct mail *mail, uoff_t *size_r)
 {
 	struct virtual_mail *vmail = (struct virtual_mail *)mail;
+	struct mail *backend_mail;
 
-	if (virtual_mail_handle_lost(vmail) < 0)
+	if (backend_mail_get(vmail, &backend_mail) < 0)
 		return -1;
-	if (mail_get_virtual_size(vmail->backend_mail, size_r) < 0) {
-		virtual_box_copy_error(mail->box, vmail->backend_mail->box);
+	if (mail_get_virtual_size(backend_mail, size_r) < 0) {
+		virtual_box_copy_error(mail->box, backend_mail->box);
 		return -1;
 	}
 	return 0;
@@ -276,11 +315,12 @@
 static int virtual_mail_get_physical_size(struct mail *mail, uoff_t *size_r)
 {
 	struct virtual_mail *vmail = (struct virtual_mail *)mail;
+	struct mail *backend_mail;
 
-	if (virtual_mail_handle_lost(vmail) < 0)
+	if (backend_mail_get(vmail, &backend_mail) < 0)
 		return -1;
-	if (mail_get_physical_size(vmail->backend_mail, size_r) < 0) {
-		virtual_box_copy_error(mail->box, vmail->backend_mail->box);
+	if (mail_get_physical_size(backend_mail, size_r) < 0) {
+		virtual_box_copy_error(mail->box, backend_mail->box);
 		return -1;
 	}
 	return 0;


More information about the dovecot-cvs mailing list