]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-storage: Fix INBOX notifications to set correct events
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Mon, 4 Sep 2017 14:48:52 +0000 (17:48 +0300)
committerAki Tuomi <aki.tuomi@dovecot.fi>
Tue, 5 Sep 2017 07:47:28 +0000 (10:47 +0300)
This fixes IMAP NOTIFY so it doesn't send STATUS notifications to INBOX when
it doesn't have to.

src/lib-storage/list/mailbox-list-index-notify.c

index 48a4366a5bf5f0ed27afdec41df1dfd4d2e89d5a..64b0123e1c6a58a1b73330c8224ac1b71e4ab4b8 100644 (file)
@@ -60,12 +60,17 @@ struct mailbox_list_notify_index {
 
        char *list_log_path, *inbox_log_path;
        struct stat list_last_st, inbox_last_st;
+       struct mailbox *inbox;
 
        bool initialized:1;
        bool read_failed:1;
        bool inbox_event_pending:1;
 };
 
+static const enum mailbox_status_items notify_status_items =
+       STATUS_UIDVALIDITY | STATUS_UIDNEXT | STATUS_MESSAGES |
+       STATUS_UNSEEN | STATUS_HIGHESTMODSEQ;
+
 static enum mailbox_list_notify_event
 mailbox_list_index_get_changed_events(const struct mailbox_notify_node *nnode,
                                      const struct mailbox_status *status)
@@ -101,6 +106,17 @@ mailbox_notify_node_update_status(struct mailbox_notify_node *nnode,
        nnode->highest_modseq = status->highest_modseq;
 }
 
+static void
+mailbox_list_index_notify_init_inbox(struct mailbox_list_notify_index *inotify)
+{
+       inotify->inbox = mailbox_alloc(inotify->notify.list, "INBOX",
+                                      MAILBOX_FLAG_READONLY);
+       if (mailbox_open(inotify->inbox) < 0)
+               mailbox_free(&inotify->inbox);
+       inotify->inbox_log_path =
+               i_strconcat(inotify->inbox->index->filepath, ".log", NULL);
+}
+
 int mailbox_list_index_notify_init(struct mailbox_list *list,
                                   enum mailbox_list_notify_event mask,
                                   struct mailbox_list_notify **notify_r)
@@ -146,9 +162,7 @@ int mailbox_list_index_notify_init(struct mailbox_list *list,
                                         &index_dir) <= 0) {
                /* no indexes for INBOX? can't handle it */
        } else {
-               /* FIXME: annoyingly hardcoded filename. */
-               inotify->inbox_log_path = i_strdup_printf(
-                       "%s/"MAIL_INDEX_PREFIX".log", index_dir);
+               mailbox_list_index_notify_init_inbox(inotify);
        }
 
        *notify_r = &inotify->notify;
@@ -161,6 +175,8 @@ void mailbox_list_index_notify_deinit(struct mailbox_list_notify *notify)
                (struct mailbox_list_notify_index *)notify;
        bool b;
 
+       if (inotify->inbox != NULL)
+               mailbox_free(&inotify->inbox);
        if (inotify->subscriptions != NULL)
                mailbox_tree_deinit(&inotify->subscriptions);
        if (inotify->io_wait != NULL)
@@ -724,15 +740,13 @@ static bool
 mailbox_list_index_notify_change(struct mailbox_list_notify_index *inotify,
                                 uint32_t uid)
 {
-       const enum mailbox_status_items status_items =
-               STATUS_UIDVALIDITY | STATUS_UIDNEXT | STATUS_MESSAGES |
-               STATUS_UNSEEN | STATUS_HIGHESTMODSEQ;
        struct mailbox_list_notify_rec *rec;
        struct mailbox_notify_node *nnode, empty_node;
        struct mailbox_status status;
 
        if (!mailbox_list_index_notify_lookup(inotify, inotify->view,
-                                             uid, status_items, &status, &rec))
+                                             uid, notify_status_items,
+                                             &status, &rec))
                i_unreached();
 
        /* get the old status */
@@ -789,6 +803,24 @@ mailbox_list_index_notify_try_next(struct mailbox_list_notify_index *inotify)
        return FALSE;
 }
 
+static enum mailbox_list_notify_event
+mailbox_list_notify_inbox_get_events(struct mailbox_list_notify_index *inotify)
+{
+       struct mailbox_status old_status, new_status;
+       struct mailbox_notify_node old_nnode;
+
+       mailbox_get_open_status(inotify->inbox, notify_status_items, &old_status);
+       if (mailbox_sync(inotify->inbox, MAILBOX_SYNC_FLAG_FAST) < 0) {
+               i_error("Mailbox list index notify: Failed to sync INBOX: %s",
+                       mailbox_get_last_internal_error(inotify->inbox, NULL));
+               return 0;
+       }
+       mailbox_get_open_status(inotify->inbox, notify_status_items, &new_status);
+
+       mailbox_notify_node_update_status(&old_nnode, &old_status);
+       return mailbox_list_index_get_changed_events(&old_nnode, &new_status);
+}
+
 int mailbox_list_index_notify_next(struct mailbox_list_notify *notify,
                                   const struct mailbox_list_notify_rec **rec_r)
 {
@@ -813,12 +845,8 @@ int mailbox_list_index_notify_next(struct mailbox_list_notify *notify,
                i_zero(&inotify->notify_rec);
                inotify->notify_rec.vname = "INBOX";
                inotify->notify_rec.storage_name = "INBOX";
-               /* Don't bother trying to figure out which event exactly this
-                  is. Just send them all and let the caller handle it. */
-               inotify->notify_rec.events = MAILBOX_LIST_NOTIFY_APPENDS |
-                       MAILBOX_LIST_NOTIFY_EXPUNGES |
-                       MAILBOX_LIST_NOTIFY_SEEN_CHANGES |
-                       MAILBOX_LIST_NOTIFY_MODSEQ_CHANGES;
+               inotify->notify_rec.events =
+                       mailbox_list_notify_inbox_get_events(inotify);
                *rec_r = &inotify->notify_rec;
                return 1;
        }