]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
virtual: Use mailbox_notify_list API when mailbox_list_index is enabled
authorAki Tuomi <aki.tuomi@dovecot.fi>
Tue, 27 Jun 2017 09:51:51 +0000 (12:51 +0300)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Tue, 18 Jul 2017 10:42:18 +0000 (13:42 +0300)
src/plugins/virtual/virtual-storage.c
src/plugins/virtual/virtual-storage.h

index 8e9d6cf329221d4998d63eee672810e7cab01893..5cffb460a665e505f5571fbc67291c68838d496d 100644 (file)
@@ -14,6 +14,7 @@
 #include "virtual-plugin.h"
 #include "virtual-transaction.h"
 #include "virtual-storage.h"
+#include "mailbox-list-notify.h"
 
 #include <stdio.h>
 #include <unistd.h>
@@ -286,9 +287,10 @@ void virtual_backend_box_sync_mail_unset(struct virtual_backend_box *bbox)
 static bool virtual_backend_box_can_close(struct virtual_backend_box *bbox)
 {
        if (bbox->box->notify_callback != NULL) {
-               /* FIXME: IMAP IDLE running - we should support closing this
-                  also if mailbox_list_index=yes */
-               return FALSE;
+               /* we can close it if notify is set
+                  because we have no need to keep it open
+                  for tracking changes */
+               return bbox->notify != NULL;
        }
        if (array_count(&bbox->sync_pending_removes) > 0) {
                /* FIXME: we could probably close this by making
@@ -340,6 +342,9 @@ static void virtual_backend_mailbox_close(struct mailbox *box)
        struct virtual_backend_box *bbox = VIRTUAL_CONTEXT(box);
        struct virtual_backend_mailbox *vbox = VIRTUAL_BACKEND_CONTEXT(box);
 
+       if (bbox != NULL && bbox->notify != NULL)
+               mailbox_list_notify_deinit(&bbox->notify);
+
        if (bbox != NULL && bbox->open_tracked) {
                /* we could have gotten here from e.g. mailbox_autocreate()
                   without going through virtual_mailbox_close() */
@@ -664,21 +669,45 @@ virtual_notify_callback(struct mailbox *bbox ATTR_UNUSED, struct mailbox *box)
        box->notify_callback(box, box->notify_context);
 }
 
+static void virtual_backend_box_changed(struct virtual_backend_box *bbox)
+{
+       virtual_notify_callback(bbox->box, &bbox->virtual_mbox->box);
+}
+
+static int virtual_notify_start(struct virtual_backend_box *bbox)
+{
+       i_assert(bbox->notify == NULL);
+       if (mailbox_list_notify_init(bbox->box->list, MAILBOX_LIST_NOTIFY_STATUS,
+                                    &bbox->notify) < 0)
+               /* did not support notifications */
+               return -1;
+       mailbox_list_notify_wait(bbox->notify, virtual_backend_box_changed, bbox);
+       return 0;
+}
+
 static void virtual_notify_changes(struct mailbox *box)
 {
        struct virtual_mailbox *mbox = (struct virtual_mailbox *)box;
-       struct virtual_backend_box *const *bboxp;
+       struct virtual_backend_box **bboxp;
 
        if (box->notify_callback == NULL) {
-               array_foreach(&mbox->backend_boxes, bboxp)
+               array_foreach_modifiable(&mbox->backend_boxes, bboxp) {
                        mailbox_notify_changes_stop((*bboxp)->box);
+                       if ((*bboxp)->notify != NULL)
+                               mailbox_list_notify_deinit(&(*bboxp)->notify);
+               }
                return;
        }
 
-       /* FIXME: if mailbox_list_index=yes, use mailbox-list-notify.h API
-          to wait for changes and avoid opening all mailboxes here. */
-
-       array_foreach(&mbox->backend_boxes, bboxp) {
+       array_foreach_modifiable(&mbox->backend_boxes, bboxp) {
+               /* we are already waiting for notifications */
+               if ((*bboxp)->notify != NULL)
+                       continue;
+               /* wait for notifications */
+               if (virtual_notify_start(*bboxp) == 0)
+                       continue;
+               /* it did not work, so open the mailbox and use
+                  alternative method */
                if (!(*bboxp)->box->opened &&
                    virtual_backend_box_open(mbox, *bboxp) < 0) {
                        /* we can't report error in here, so do it later */
index 7f36cc6c08744984a732637427f71af5579823b8..3cd455c84a73ebabde0def499c95a0f88fc89f54 100644 (file)
@@ -102,6 +102,9 @@ struct virtual_backend_box {
        /* mailbox metadata matching */
        const char *metadata_entry, *metadata_value;
 
+       /* notify context */
+       struct mailbox_list_notify *notify;
+
        unsigned int open_tracked:1;
        unsigned int open_failed:1;
        unsigned int sync_seen:1;