From: Timo Sirainen Date: Fri, 21 Mar 2014 15:52:50 +0000 (+0200) Subject: imapc: Cache LIST replies for a while to be able to immediately ask for mailbox flags... X-Git-Tag: 2.2.13.rc1~195 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7586eb9be41bf2de90790ab1c50ba6bfb85402b4;p=thirdparty%2Fdovecot%2Fcore.git imapc: Cache LIST replies for a while to be able to immediately ask for mailbox flags/existence. Besides giving better performance, this will fix bugs in some servers where LISTing a single mailbox doesn't necessarily return it. (In this case a mailbox named "in" wasn't returned, but I think Dovecot has had bugs related to this also.) --- diff --git a/src/lib-storage/index/imapc/imapc-list.c b/src/lib-storage/index/imapc/imapc-list.c index 5e4157eb9a..9ec6febdbe 100644 --- a/src/lib-storage/index/imapc/imapc-list.c +++ b/src/lib-storage/index/imapc/imapc-list.c @@ -1,6 +1,7 @@ /* Copyright (c) 2011-2014 Dovecot authors, see the included COPYING file */ #include "lib.h" +#include "ioloop.h" #include "str.h" #include "imap-arg.h" #include "imap-match.h" @@ -565,6 +566,8 @@ static int imapc_list_refresh(struct imapc_mailbox_list *list) if (ctx.ret == 0) { list->refreshed_mailboxes = TRUE; + list->refreshed_mailboxes_recently = TRUE; + list->last_refreshed_mailboxes = ioloop_time; imapc_list_delete_unused_indexes(list); } return ctx.ret; @@ -867,23 +870,14 @@ int imapc_list_get_mailbox_flags(struct mailbox_list *_list, const char *name, enum mailbox_info_flags *flags_r) { struct imapc_mailbox_list *list = (struct imapc_mailbox_list *)_list; - struct imapc_command *cmd; - struct imapc_simple_context sctx; struct mailbox_node *node; const char *vname; vname = mailbox_list_get_vname(_list, name); - if (!list->refreshed_mailboxes) { - node = mailbox_tree_lookup(list->mailboxes, vname); - if (node != NULL) - node->flags |= MAILBOX_NONEXISTENT; - - /* refresh the mailbox flags */ - cmd = imapc_list_simple_context_init(&sctx, list); - imapc_command_sendf(cmd, "LIST \"\" %s", name); - imapc_simple_run(&sctx); - if (sctx.ret < 0) + if (!list->refreshed_mailboxes_recently) { + if (imapc_list_refresh(list) < 0) return -1; + i_assert(list->refreshed_mailboxes_recently); } node = mailbox_tree_lookup(list->mailboxes, vname); diff --git a/src/lib-storage/index/imapc/imapc-list.h b/src/lib-storage/index/imapc/imapc-list.h index c3338114cc..85af9671ff 100644 --- a/src/lib-storage/index/imapc/imapc-list.h +++ b/src/lib-storage/index/imapc/imapc-list.h @@ -15,11 +15,18 @@ struct imapc_mailbox_list { struct mailbox_tree_context *mailboxes, *tmp_subscriptions; char root_sep; + time_t last_refreshed_mailboxes; unsigned int iter_count; + /* mailboxes/subscriptions are fully refreshed only during + mailbox list iteration. */ unsigned int refreshed_subscriptions:1; unsigned int refreshed_mailboxes:1; + /* mailbox list's "recently refreshed" state is reset by syncing a + mailbox. mainly we use this to cache mailboxes' existence to avoid + issuing a LIST command every time. */ + unsigned int refreshed_mailboxes_recently:1; unsigned int index_list_failed:1; unsigned int root_sep_pending:1; }; diff --git a/src/lib-storage/index/imapc/imapc-sync.c b/src/lib-storage/index/imapc/imapc-sync.c index 4125a7b001..f5d4eb3b63 100644 --- a/src/lib-storage/index/imapc/imapc-sync.c +++ b/src/lib-storage/index/imapc/imapc-sync.c @@ -7,6 +7,7 @@ #include "index-sync-private.h" #include "imapc-client.h" #include "imapc-msgmap.h" +#include "imapc-list.h" #include "imapc-storage.h" #include "imapc-sync.h" @@ -448,10 +449,17 @@ struct mailbox_sync_context * imapc_mailbox_sync_init(struct mailbox *box, enum mailbox_sync_flags flags) { struct imapc_mailbox *mbox = (struct imapc_mailbox *)box; + struct imapc_mailbox_list *list = mbox->storage->client->_list; enum imapc_capability capabilities; bool changes; int ret = 0; + if (list != NULL) { + if (!list->refreshed_mailboxes && + list->last_refreshed_mailboxes < ioloop_time) + list->refreshed_mailboxes_recently = FALSE; + } + if (!box->opened) { if (mailbox_open(box) < 0) ret = -1;