]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
imapc: Cache LIST replies for a while to be able to immediately ask for mailbox flags...
authorTimo Sirainen <tss@iki.fi>
Fri, 21 Mar 2014 15:52:50 +0000 (17:52 +0200)
committerTimo Sirainen <tss@iki.fi>
Fri, 21 Mar 2014 15:52:50 +0000 (17:52 +0200)
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.)

src/lib-storage/index/imapc/imapc-list.c
src/lib-storage/index/imapc/imapc-list.h
src/lib-storage/index/imapc/imapc-sync.c

index 5e4157eb9ab3a1762d3968808ca3270317b16f2c..9ec6febdbe1f23bb6472e4b2a788a61cbea04b9e 100644 (file)
@@ -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);
index c3338114cc2c7c86fd499291004c148712e6c7f3..85af9671ffb71acdd070346309d77a71d1e7f6f6 100644 (file)
@@ -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;
 };
index 4125a7b00149a86ed1e25bec5013ddff3392a94c..f5d4eb3b6310355bccadac52c94b4fd5e8b3139c 100644 (file)
@@ -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;