changeset 22457:5de2bae83c93

lib-storage: Fix INBOX notifications to set correct events This fixes IMAP NOTIFY so it doesn't send STATUS notifications to INBOX when it doesn't have to.
author Timo Sirainen <timo.sirainen@dovecot.fi>
date Mon, 04 Sep 2017 17:48:52 +0300
parents d1658f4cb079
children 83f93173dadb
files src/lib-storage/list/mailbox-list-index-notify.c
diffstat 1 files changed, 41 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-storage/list/mailbox-list-index-notify.c	Mon Sep 04 17:37:05 2017 +0300
+++ b/src/lib-storage/list/mailbox-list-index-notify.c	Mon Sep 04 17:48:52 2017 +0300
@@ -60,12 +60,17 @@
 
 	char *list_log_path, *inbox_log_path;
 	struct stat list_last_st, inbox_last_st;
+	struct mailbox *inbox;
 
 	unsigned int initialized:1;
 	unsigned int read_failed:1;
 	unsigned int 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 @@
 	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 @@
 					 &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 @@
 		(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 @@
 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 @@
 	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 @@
 		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;
 	}