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