dovecot-2.1: imapc: Keep the last fetched message body cached un...
dovecot at dovecot.org
dovecot at dovecot.org
Fri Sep 30 18:44:50 EEST 2011
details: http://hg.dovecot.org/dovecot-2.1/rev/5726f89486a0
changeset: 13564:5726f89486a0
user: Timo Sirainen <tss at iki.fi>
date: Fri Sep 30 18:53:09 2011 +0300
description:
imapc: Keep the last fetched message body cached until mailbox is closed.
This primarily helps partial IMAP fetches so each partial fetch doesn't
redownload the message body.
diffstat:
src/lib-storage/index/imapc/imapc-mail-fetch.c | 37 +++++++++++++++++++++++++-
src/lib-storage/index/imapc/imapc-mail.c | 19 +++++++++++++
src/lib-storage/index/imapc/imapc-mail.h | 2 +
src/lib-storage/index/imapc/imapc-mailbox.c | 5 ++-
src/lib-storage/index/imapc/imapc-storage.c | 13 +++++++++
src/lib-storage/index/imapc/imapc-storage.h | 13 +++++++++
6 files changed, 87 insertions(+), 2 deletions(-)
diffs (208 lines):
diff -r 690f60827f59 -r 5726f89486a0 src/lib-storage/index/imapc/imapc-mail-fetch.c
--- a/src/lib-storage/index/imapc/imapc-mail-fetch.c Fri Sep 30 18:19:17 2011 +0300
+++ b/src/lib-storage/index/imapc/imapc-mail-fetch.c Fri Sep 30 18:53:09 2011 +0300
@@ -109,12 +109,40 @@
return 0;
}
+static void imapc_mail_cache_get(struct imapc_mail *mail,
+ struct imapc_mail_cache *cache)
+{
+ if (mail->body_fetched)
+ return;
+
+ if (cache->fd != -1) {
+ mail->fd = cache->fd;
+ mail->imail.data.stream =
+ i_stream_create_fd(mail->fd, 0, FALSE);
+ cache->fd = -1;
+ } else if (cache->buf != NULL) {
+ mail->body = cache->buf;
+ mail->imail.data.stream =
+ i_stream_create_from_data(mail->body->data,
+ mail->body->used);
+ cache->buf = NULL;
+ } else {
+ return;
+ }
+ mail->body_fetched = TRUE;
+ imapc_mail_init_stream(mail, TRUE);
+}
+
bool imapc_mail_prefetch(struct mail *_mail)
{
struct imapc_mail *mail = (struct imapc_mail *)_mail;
+ struct imapc_mailbox *mbox = (struct imapc_mailbox *)_mail->box;
struct index_mail_data *data = &mail->imail.data;
enum mail_fetch_field fields = 0;
+ if (mbox->prev_mail_cache.uid == _mail->uid)
+ imapc_mail_cache_get(mail, &mbox->prev_mail_cache);
+
if ((mail->imail.wanted_fields & MAIL_FETCH_RECEIVED_DATE) != 0 &&
data->received_date == (time_t)-1)
fields |= MAIL_FETCH_RECEIVED_DATE;
@@ -256,6 +284,11 @@
return;
/* maybe the existing stream has no body. replace it. */
i_stream_unref(&imail->data.stream);
+ if (mail->fd != -1) {
+ if (close(mail->fd) < 0)
+ i_error("close(imapc mail) failed: %m");
+ mail->fd = -1;
+ }
}
if (arg->type == IMAP_ARG_LITERAL_SIZE) {
@@ -265,7 +298,8 @@
i_error("dup() failed: %m");
return;
}
- imail->data.stream = i_stream_create_fd(fd, 0, TRUE);
+ mail->fd = fd;
+ imail->data.stream = i_stream_create_fd(fd, 0, FALSE);
} else {
if (!imap_arg_get_nstring(arg, &value))
return;
@@ -282,6 +316,7 @@
imail->data.stream = i_stream_create_from_data(mail->body->data,
mail->body->used);
}
+ mail->body_fetched = body;
imapc_mail_init_stream(mail, body);
}
diff -r 690f60827f59 -r 5726f89486a0 src/lib-storage/index/imapc/imapc-mail.c
--- a/src/lib-storage/index/imapc/imapc-mail.c Fri Sep 30 18:19:17 2011 +0300
+++ b/src/lib-storage/index/imapc/imapc-mail.c Fri Sep 30 18:53:09 2011 +0300
@@ -20,6 +20,7 @@
pool = pool_alloconly_create("mail", 2048);
mail = p_new(pool, struct imapc_mail, 1);
mail->imail.mail.pool = pool;
+ mail->fd = -1;
index_mail_init(&mail->imail, t, wanted_fields, wanted_headers);
return &mail->imail.mail.mail;
@@ -28,9 +29,27 @@
static void imapc_mail_free(struct mail *_mail)
{
struct imapc_mail *mail = (struct imapc_mail *)_mail;
+ struct imapc_mailbox *mbox = (struct imapc_mailbox *)_mail->box;
+ struct imapc_mail_cache *cache = &mbox->prev_mail_cache;
+ if (mail->body_fetched) {
+ imapc_mail_cache_free(cache);
+ cache->uid = _mail->uid;
+ if (cache->fd != -1) {
+ cache->fd = mail->fd;
+ mail->fd = -1;
+ } else {
+ cache->buf = mail->body;
+ mail->body = NULL;
+ }
+ }
+ if (mail->fd != -1) {
+ if (close(mail->fd) < 0)
+ i_error("close(imapc mail) failed: %m");
+ }
if (mail->body != NULL)
buffer_free(&mail->body);
+
index_mail_free(_mail);
}
diff -r 690f60827f59 -r 5726f89486a0 src/lib-storage/index/imapc/imapc-mail.h
--- a/src/lib-storage/index/imapc/imapc-mail.h Fri Sep 30 18:19:17 2011 +0300
+++ b/src/lib-storage/index/imapc/imapc-mail.h Fri Sep 30 18:53:09 2011 +0300
@@ -12,7 +12,9 @@
enum mail_fetch_field fetching_fields;
unsigned int fetch_count;
+ int fd;
buffer_t *body;
+ bool body_fetched;
};
extern struct mail_vfuncs imapc_mail_vfuncs;
diff -r 690f60827f59 -r 5726f89486a0 src/lib-storage/index/imapc/imapc-mailbox.c
--- a/src/lib-storage/index/imapc/imapc-mailbox.c Fri Sep 30 18:19:17 2011 +0300
+++ b/src/lib-storage/index/imapc/imapc-mailbox.c Fri Sep 30 18:53:09 2011 +0300
@@ -403,7 +403,10 @@
str_to_uint32(reply->resp_text_value, &uid_validity) < 0)
return;
- mbox->sync_uid_validity = uid_validity;
+ if (mbox->sync_uid_validity != uid_validity) {
+ mbox->sync_uid_validity = uid_validity;
+ imapc_mail_cache_free(&mbox->prev_mail_cache);
+ }
}
static void
diff -r 690f60827f59 -r 5726f89486a0 src/lib-storage/index/imapc/imapc-storage.c
--- a/src/lib-storage/index/imapc/imapc-storage.c Fri Sep 30 18:19:17 2011 +0300
+++ b/src/lib-storage/index/imapc/imapc-storage.c Fri Sep 30 18:53:09 2011 +0300
@@ -340,6 +340,7 @@
p_array_init(&mbox->fetch_mails, pool, 16);
p_array_init(&mbox->permanent_keywords, pool, 32);
p_array_init(&mbox->delayed_expunged_uids, pool, 16);
+ mbox->prev_mail_cache.fd = -1;
imapc_mailbox_register_callbacks(mbox);
return &mbox->box;
}
@@ -432,6 +433,18 @@
return 0;
}
+void imapc_mail_cache_free(struct imapc_mail_cache *cache)
+{
+ if (cache->fd != -1) {
+ if (close(cache->fd) < 0)
+ i_error("close(imapc cached mail) failed: %m");
+ cache->fd = -1;
+ }
+ if (cache->buf != NULL)
+ buffer_free(&cache->buf);
+ cache->uid = 0;
+}
+
static void imapc_mailbox_close(struct mailbox *box)
{
struct imapc_mailbox *mbox = (struct imapc_mailbox *)box;
diff -r 690f60827f59 -r 5726f89486a0 src/lib-storage/index/imapc/imapc-storage.h
--- a/src/lib-storage/index/imapc/imapc-storage.h Fri Sep 30 18:19:17 2011 +0300
+++ b/src/lib-storage/index/imapc/imapc-storage.h Fri Sep 30 18:53:09 2011 +0300
@@ -40,6 +40,14 @@
ARRAY_DEFINE(untagged_callbacks, struct imapc_storage_event_callback);
};
+struct imapc_mail_cache {
+ uint32_t uid;
+
+ /* either fd != -1 or buf != NULL */
+ int fd;
+ buffer_t *buf;
+};
+
struct imapc_mailbox {
struct mailbox box;
struct imapc_storage *storage;
@@ -66,6 +74,10 @@
uint32_t exists_count;
uint32_t min_append_uid;
+ /* keep the previous fetched message body cached,
+ mainly for partial IMAP fetches */
+ struct imapc_mail_cache prev_mail_cache;
+
uint32_t prev_skipped_rseq, prev_skipped_uid;
unsigned int selecting:1;
@@ -92,6 +104,7 @@
void imapc_transaction_save_rollback(struct mail_save_context *ctx);
void imapc_storage_run(struct imapc_storage *storage);
+void imapc_mail_cache_free(struct imapc_mail_cache *cache);
void imapc_copy_error_from_reply(struct imapc_storage *storage,
enum mail_error default_error,
More information about the dovecot-cvs
mailing list