dovecot-2.2: imapc: Merge identical FETCH commands together (onl...
dovecot at dovecot.org
dovecot at dovecot.org
Sun Nov 17 17:15:55 EET 2013
details: http://hg.dovecot.org/dovecot-2.2/rev/10462996fa32
changeset: 16975:10462996fa32
user: Timo Sirainen <tss at iki.fi>
date: Sun Nov 17 16:59:33 2013 +0200
description:
imapc: Merge identical FETCH commands together (only updating UID range)
diffstat:
src/lib-storage/index/imapc/imapc-mail-fetch.c | 137 +++++++++++++++++++-----
src/lib-storage/index/imapc/imapc-mail.c | 2 +-
src/lib-storage/index/imapc/imapc-mail.h | 3 +
src/lib-storage/index/imapc/imapc-mailbox.c | 11 +-
src/lib-storage/index/imapc/imapc-save.c | 6 +-
src/lib-storage/index/imapc/imapc-storage.c | 13 +-
src/lib-storage/index/imapc/imapc-storage.h | 14 ++-
src/lib-storage/index/imapc/imapc-sync.c | 2 +-
8 files changed, 140 insertions(+), 48 deletions(-)
diffs (truncated from 399 to 300 lines):
diff -r aec5d4170e74 -r 10462996fa32 src/lib-storage/index/imapc/imapc-mail-fetch.c
--- a/src/lib-storage/index/imapc/imapc-mail-fetch.c Sun Nov 17 16:58:42 2013 +0200
+++ b/src/lib-storage/index/imapc/imapc-mail-fetch.c Sun Nov 17 16:59:33 2013 +0200
@@ -2,6 +2,7 @@
#include "lib.h"
#include "str.h"
+#include "ioloop.h"
#include "istream.h"
#include "istream-header-filter.h"
#include "message-header-parser.h"
@@ -13,29 +14,37 @@
#include "imapc-storage.h"
static void
-imapc_mail_prefetch_callback(const struct imapc_command_reply *reply,
- void *context)
+imapc_mail_fetch_callback(const struct imapc_command_reply *reply,
+ void *context)
{
- struct imapc_mail *mail = context;
- struct imapc_mailbox *mbox =
- (struct imapc_mailbox *)mail->imail.mail.mail.box;
+ struct imapc_fetch_request *request = context;
+ struct imapc_fetch_request *const *requests;
+ struct imapc_mail *const *mailp;
+ struct imapc_mailbox *mbox = NULL;
+ unsigned int i, count;
- i_assert(mail->fetch_count > 0);
+ array_foreach(&request->mails, mailp) {
+ struct imapc_mail *mail = *mailp;
- if (--mail->fetch_count == 0) {
- struct imapc_mail *const *fetch_mails;
- unsigned int i, count;
+ i_assert(mail->fetch_count > 0);
+ if (--mail->fetch_count == 0)
+ mail->fetching_fields = 0;
+ pool_unref(&mail->imail.mail.pool);
+ mbox = (struct imapc_mailbox *)mail->imail.mail.mail.box;
+ }
+ i_assert(mbox != NULL);
- fetch_mails = array_get(&mbox->fetch_mails, &count);
- for (i = 0; i < count; i++) {
- if (fetch_mails[i] == mail) {
- array_delete(&mbox->fetch_mails, i, 1);
- break;
- }
+ requests = array_get(&mbox->fetch_requests, &count);
+ for (i = 0; i < count; i++) {
+ if (requests[i] == request) {
+ array_delete(&mbox->fetch_requests, i, 1);
+ break;
}
- i_assert(i != count);
- mail->fetching_fields = 0;
}
+ i_assert(i < count);
+
+ array_free(&request->mails);
+ i_free(request);
if (reply->state == IMAPC_COMMAND_STATE_OK)
;
@@ -47,9 +56,8 @@
mail_storage_set_internal_error(&mbox->storage->storage);
} else {
mail_storage_set_critical(&mbox->storage->storage,
- "imapc: Mail prefetch failed: %s", reply->text_full);
+ "imapc: Mail FETCH failed: %s", reply->text_full);
}
- pool_unref(&mail->imail.mail.pool);
imapc_client_stop(mbox->storage->client->client);
}
@@ -95,13 +103,61 @@
return array_idx(&headers, 0);
}
+static bool
+imapc_mail_try_merge_fetch(struct imapc_mailbox *mbox, string_t *str)
+{
+ const char *s1 = str_c(str);
+ const char *s2 = str_c(mbox->pending_fetch_cmd);
+ const char *p1, *p2;
+
+ i_assert(strncmp(s1, "UID FETCH ", 10) == 0);
+ i_assert(strncmp(s2, "UID FETCH ", 10) == 0);
+
+ /* skip over UID range */
+ p1 = strchr(s1+10, ' ');
+ p2 = strchr(s2+10, ' ');
+
+ if (null_strcmp(p1, p2) != 0)
+ return FALSE;
+ /* append the new UID to the pending FETCH UID range */
+ str_truncate(str, p1-s1);
+ str_insert(mbox->pending_fetch_cmd, p2-s2, ",");
+ str_insert(mbox->pending_fetch_cmd, p2-s2+1, str_c(str) + 10);
+ return TRUE;
+}
+
+static void
+imapc_mail_delayed_send_or_merge(struct imapc_mail *mail, string_t *str)
+{
+ struct imapc_mailbox *mbox =
+ (struct imapc_mailbox *)mail->imail.mail.mail.box;
+
+ if (mbox->pending_fetch_request != NULL &&
+ !imapc_mail_try_merge_fetch(mbox, str)) {
+ /* send the previous FETCH and create a new one */
+ imapc_mail_fetch_flush(mbox);
+ }
+ if (mbox->pending_fetch_request == NULL) {
+ mbox->pending_fetch_request =
+ i_new(struct imapc_fetch_request, 1);
+ i_array_init(&mbox->pending_fetch_request->mails, 4);
+ i_assert(mbox->pending_fetch_cmd->used == 0);
+ str_append_str(mbox->pending_fetch_cmd, str);
+ }
+ array_append(&mbox->pending_fetch_request->mails, &mail, 1);
+
+ if (mbox->to_pending_fetch_send == NULL) {
+ mbox->to_pending_fetch_send =
+ timeout_add_short(0, imapc_mail_fetch_flush, mbox);
+ }
+}
+
static int
imapc_mail_send_fetch(struct mail *_mail, enum mail_fetch_field fields,
const char *const *headers)
{
struct imapc_mail *mail = (struct imapc_mail *)_mail;
struct imapc_mailbox *mbox = (struct imapc_mailbox *)_mail->box;
- struct imapc_command *cmd;
struct mail_index_view *view;
string_t *str;
uint32_t seq;
@@ -172,15 +228,10 @@
pool_ref(mail->imail.mail.pool);
mail->fetching_fields |= fields;
- if (mail->fetch_count++ == 0)
- array_append(&mbox->fetch_mails, &mail, 1);
+ mail->fetch_count++;
- cmd = imapc_client_mailbox_cmd(mbox->client_box,
- imapc_mail_prefetch_callback, mail);
- imapc_command_set_flags(cmd, IMAPC_COMMAND_FLAG_RETRIABLE);
- imapc_command_send(cmd, str_c(str));
- mail->imail.data.prefetch_sent = TRUE;
- return 0;
+ imapc_mail_delayed_send_or_merge(mail, str);
+ return 1;
}
static void imapc_mail_cache_get(struct imapc_mail *mail,
@@ -252,9 +303,10 @@
fields = imapc_mail_get_wanted_fetch_fields(mail);
if (fields != 0) T_BEGIN {
- (void)imapc_mail_send_fetch(_mail, fields,
- data->wanted_headers == NULL ? NULL :
- data->wanted_headers->name);
+ if (imapc_mail_send_fetch(_mail, fields,
+ data->wanted_headers == NULL ? NULL :
+ data->wanted_headers->name) > 0)
+ mail->imail.data.prefetch_sent = TRUE;
} T_END;
return !mail->imail.data.prefetch_sent;
}
@@ -316,10 +368,31 @@
while (imail->fetch_count > 0 &&
(!imapc_mail_have_fields(imail, fields) ||
!imail->header_list_fetched))
- imapc_storage_run(mbox->storage);
+ imapc_mailbox_run(mbox);
return 0;
}
+void imapc_mail_fetch_flush(struct imapc_mailbox *mbox)
+{
+ struct imapc_command *cmd;
+
+ if (mbox->pending_fetch_request == NULL) {
+ i_assert(mbox->to_pending_fetch_send == NULL);
+ return;
+ }
+
+ cmd = imapc_client_mailbox_cmd(mbox->client_box,
+ imapc_mail_fetch_callback,
+ mbox->pending_fetch_request);
+ imapc_command_set_flags(cmd, IMAPC_COMMAND_FLAG_RETRIABLE);
+ imapc_command_send(cmd, str_c(mbox->pending_fetch_cmd));
+
+ array_append(&mbox->fetch_requests, &mbox->pending_fetch_request, 1);
+ mbox->pending_fetch_request = NULL;
+ timeout_remove(&mbox->to_pending_fetch_send);
+ str_truncate(mbox->pending_fetch_cmd, 0);
+}
+
static bool imapc_find_lfile_arg(const struct imapc_untagged_reply *reply,
const struct imap_arg *arg, int *fd_r)
{
diff -r aec5d4170e74 -r 10462996fa32 src/lib-storage/index/imapc/imapc-mail.c
--- a/src/lib-storage/index/imapc/imapc-mail.c Sun Nov 17 16:58:42 2013 +0200
+++ b/src/lib-storage/index/imapc/imapc-mail.c Sun Nov 17 16:59:33 2013 +0200
@@ -358,7 +358,7 @@
struct imapc_mail_cache *cache = &mbox->prev_mail_cache;
while (mail->fetch_count > 0)
- imapc_storage_run(mbox->storage);
+ imapc_mailbox_run(mbox);
index_mail_close(_mail);
diff -r aec5d4170e74 -r 10462996fa32 src/lib-storage/index/imapc/imapc-mail.h
--- a/src/lib-storage/index/imapc/imapc-mail.h Sun Nov 17 16:58:42 2013 +0200
+++ b/src/lib-storage/index/imapc/imapc-mail.h Sun Nov 17 16:59:33 2013 +0200
@@ -5,6 +5,7 @@
struct imap_arg;
struct imapc_untagged_reply;
+struct imapc_mailbox;
struct imapc_mail {
struct index_mail imail;
@@ -28,11 +29,13 @@
int imapc_mail_fetch(struct mail *mail, enum mail_fetch_field fields,
const char *const *headers);
bool imapc_mail_prefetch(struct mail *mail);
+void imapc_mail_fetch_flush(struct imapc_mailbox *mbox);
void imapc_mail_init_stream(struct imapc_mail *mail, bool have_body);
void imapc_mail_fetch_update(struct imapc_mail *mail,
const struct imapc_untagged_reply *reply,
const struct imap_arg *args);
void imapc_mail_update_access_parts(struct index_mail *mail);
+void imapc_mail_command_flush(struct imapc_mailbox *mbox);
#endif
diff -r aec5d4170e74 -r 10462996fa32 src/lib-storage/index/imapc/imapc-mailbox.c
--- a/src/lib-storage/index/imapc/imapc-mailbox.c Sun Nov 17 16:58:42 2013 +0200
+++ b/src/lib-storage/index/imapc/imapc-mailbox.c Sun Nov 17 16:59:33 2013 +0200
@@ -254,6 +254,7 @@
struct imapc_mailbox *mbox)
{
uint32_t lseq, rseq = reply->num;
+ struct imapc_fetch_request *const *fetch_requestp;
struct imapc_mail *const *mailp;
const struct imap_arg *list, *flags_list;
const char *atom;
@@ -303,11 +304,13 @@
return;
/* if this is a reply to some FETCH request, update the mail's fields */
- array_foreach(&mbox->fetch_mails, mailp) {
- struct imapc_mail *mail = *mailp;
+ array_foreach(&mbox->fetch_requests, fetch_requestp) {
+ array_foreach(&(*fetch_requestp)->mails, mailp) {
+ struct imapc_mail *mail = *mailp;
- if (mail->imail.mail.mail.uid == uid)
- imapc_mail_fetch_update(mail, reply, list);
+ if (mail->imail.mail.mail.uid == uid)
+ imapc_mail_fetch_update(mail, reply, list);
+ }
}
if (lseq == 0) {
diff -r aec5d4170e74 -r 10462996fa32 src/lib-storage/index/imapc/imapc-save.c
--- a/src/lib-storage/index/imapc/imapc-save.c Sun Nov 17 16:58:42 2013 +0200
+++ b/src/lib-storage/index/imapc/imapc-save.c Sun Nov 17 16:59:33 2013 +0200
@@ -246,7 +246,7 @@
ctx->mbox->box.name, flags, internaldate, input);
i_stream_unref(&input);
while (sctx.ret == -2)
- imapc_storage_run(ctx->mbox->storage);
+ imapc_mailbox_run(ctx->mbox);
if (sctx.ret == 0 && ctx->mbox->selected &&
!ctx->mbox->exists_received) {
@@ -259,7 +259,7 @@
imapc_save_noop_callback, &sctx);
imapc_command_send(cmd, "NOOP");
while (sctx.ret == -2)
- imapc_storage_run(ctx->mbox->storage);
+ imapc_mailbox_run(ctx->mbox);
}
return sctx.ret;
}
@@ -421,7 +421,7 @@
imapc_command_sendf(cmd, "UID COPY %u %s",
mail->uid, _t->box->name);
while (sctx.ret == -2)
- imapc_storage_run(src_mbox->storage);
+ imapc_mailbox_run(src_mbox);
ctx->finished = TRUE;
More information about the dovecot-cvs
mailing list