dovecot-2.2: lib-storage: Mailbox list notifications didn't work...

dovecot at dovecot.org dovecot at dovecot.org
Mon Sep 7 21:09:03 UTC 2015


details:   http://hg.dovecot.org/dovecot-2.2/rev/f600285c3df2
changeset: 19118:f600285c3df2
user:      Timo Sirainen <tss at iki.fi>
date:      Tue Sep 08 00:07:55 2015 +0300
description:
lib-storage: Mailbox list notifications didn't work for INBOX.
Because of some earlier optimizations that changes to INBOX aren't written
to dovecot.list.index.log file.

diffstat:

 src/lib-storage/list/mailbox-list-index-notify.c |  88 ++++++++++++++++++-----
 1 files changed, 69 insertions(+), 19 deletions(-)

diffs (186 lines):

diff -r fa979ccfa34c -r f600285c3df2 src/lib-storage/list/mailbox-list-index-notify.c
--- a/src/lib-storage/list/mailbox-list-index-notify.c	Mon Sep 07 23:55:31 2015 +0300
+++ b/src/lib-storage/list/mailbox-list-index-notify.c	Tue Sep 08 00:07:55 2015 +0300
@@ -5,7 +5,7 @@
 #include "str.h"
 #include "mail-index-private.h"
 #include "mail-transaction-log-private.h"
-#include "mail-storage.h"
+#include "mail-storage-private.h"
 #include "mailbox-list-notify.h"
 #include "mailbox-list-notify-tree.h"
 #include "mailbox-list-index.h"
@@ -44,7 +44,7 @@
 
 	void (*wait_callback)(void *context);
 	void *wait_context;
-	struct io *io_wait;
+	struct io *io_wait, *io_wait_inbox;
 	struct timeout *to_wait, *to_notify;
 
 	ARRAY_TYPE(seq_range) new_uids, expunged_uids, changed_uids;
@@ -58,10 +58,12 @@
 	struct mailbox_list_notify_rec notify_rec;
 	string_t *rec_name;
 
-	struct stat last_st;
+	char *list_log_path, *inbox_log_path;
+	struct stat list_last_st, inbox_last_st;
 
 	unsigned int initialized:1;
 	unsigned int read_failed:1;
+	unsigned int inbox_event_pending:1;
 };
 
 int mailbox_list_index_notify_init(struct mailbox_list *list,
@@ -70,6 +72,7 @@
 {
 	struct mailbox_list_index *ilist = INDEX_LIST_CONTEXT(list);
 	struct mailbox_list_notify_index *inotify;
+	const char *index_dir;
 
 	if (ilist == NULL) {
 		/* can't do this without mailbox list indexes */
@@ -97,6 +100,14 @@
 		mailbox_tree_sort(list->subscriptions);
 		inotify->subscriptions = mailbox_tree_dup(list->subscriptions);
 	}
+	inotify->list_log_path = i_strdup(ilist->index->log->filepath);
+	if ((list->ns->flags & NAMESPACE_FLAG_INBOX_ANY) != 0 &&
+	    mailbox_list_get_path(list, "INBOX", MAILBOX_LIST_PATH_TYPE_INDEX,
+				  &index_dir) > 0) {
+		/* FIXME: annoyingly hardcoded filename. */
+		inotify->inbox_log_path = i_strdup_printf(
+			"%s/"MAIL_INDEX_PREFIX".log", index_dir);
+	}
 
 	*notify_r = &inotify->notify;
 	return 1;
@@ -112,6 +123,8 @@
 		mailbox_tree_deinit(&inotify->subscriptions);
 	if (inotify->io_wait != NULL)
 		io_remove(&inotify->io_wait);
+	if (inotify->io_wait_inbox != NULL)
+		io_remove(&inotify->io_wait_inbox);
 	if (inotify->to_wait != NULL)
 		timeout_remove(&inotify->to_wait);
 	if (inotify->to_notify != NULL)
@@ -128,6 +141,8 @@
 	array_free(&inotify->changed_uids);
 	array_free(&inotify->renames);
 	str_free(&inotify->rec_name);
+	i_free(inotify->list_log_path);
+	i_free(inotify->inbox_log_path);
 	i_free(inotify);
 }
 
@@ -166,14 +181,22 @@
 
 static void notify_update_stat(struct mailbox_list_notify_index *inotify)
 {
-	struct mailbox_list_index *ilist =
-		INDEX_LIST_CONTEXT(inotify->notify.list);
-	const char *path = ilist->index->log->filepath;
+	bool call = FALSE;
 
-	if (stat(path, &inotify->last_st) < 0 && errno != ENOENT) {
-		i_error("stat(%s) failed: %m", path);
+	if (stat(inotify->list_log_path, &inotify->list_last_st) < 0 &&
+	    errno != ENOENT) {
+		i_error("stat(%s) failed: %m", inotify->list_log_path);
+		call = TRUE;
+	}
+	if (inotify->inbox_log_path != NULL) {
+		if (stat(inotify->inbox_log_path, &inotify->inbox_last_st) < 0 &&
+		    errno != ENOENT) {
+			i_error("stat(%s) failed: %m", inotify->inbox_log_path);
+			call = TRUE;
+		}
+	}
+	if (call)
 		mailbox_list_index_notify_wait(&inotify->notify, NULL, NULL);
-	}
 }
 
 static void
@@ -760,6 +783,20 @@
 			/* caller doesn't care about this change */
 		}
 	}
+	if (inotify->inbox_event_pending) {
+		inotify->inbox_event_pending = FALSE;
+		memset(&inotify->notify_rec, 0, sizeof(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;
+		*rec_r = &inotify->notify_rec;
+		return 1;
+	}
 
 	mailbox_list_index_notify_read_deinit(inotify);
 	return inotify->read_failed ? -1 : 0;
@@ -773,13 +810,19 @@
 
 static void notify_callback(struct mailbox_list_notify_index *inotify)
 {
-	struct stat prev_st = inotify->last_st;
-
+#define INOTIFY_ST_CHANGED(last_st, prev_st) \
+	((last_st).st_mtime != (prev_st).st_mtime || \
+	 ST_MTIME_NSEC(last_st) != ST_MTIME_NSEC(prev_st) || \
+	 (last_st).st_size != (prev_st).st_size || \
+	 (last_st).st_ino != (prev_st).st_ino)
+	struct stat list_prev_st = inotify->list_last_st;
+	struct stat inbox_prev_st = inotify->inbox_last_st;
+			 
 	notify_update_stat(inotify);
-	if (inotify->last_st.st_mtime != prev_st.st_mtime ||
-	    ST_MTIME_NSEC(inotify->last_st) != ST_MTIME_NSEC(prev_st) ||
-	    inotify->last_st.st_size != prev_st.st_size ||
-	    inotify->last_st.st_ino != prev_st.st_ino) {
+	if (INOTIFY_ST_CHANGED(inotify->inbox_last_st, inbox_prev_st))
+		inotify->inbox_event_pending = TRUE;
+	if (inotify->inbox_event_pending ||
+	    INOTIFY_ST_CHANGED(inotify->list_last_st, list_prev_st)) {
 		/* log has changed. call the callback with a small delay
 		   to allow bundling multiple changes together */
 		if (inotify->to_notify != NULL) {
@@ -798,7 +841,6 @@
 {
 	struct mailbox_list_notify_index *inotify =
 		(struct mailbox_list_notify_index *)notify;
-	const char *path;
 	unsigned int check_interval;
 
 	inotify->wait_callback = callback;
@@ -807,14 +849,22 @@
 	if (callback == NULL) {
 		if (inotify->io_wait != NULL)
 			io_remove(&inotify->io_wait);
+		if (inotify->io_wait_inbox != NULL)
+			io_remove(&inotify->io_wait_inbox);
 		if (inotify->to_wait != NULL)
 			timeout_remove(&inotify->to_wait);
 		if (inotify->to_notify != NULL)
 			timeout_remove(&inotify->to_notify);
 	} else if (inotify->to_wait == NULL) {
-		path = inotify->view->index->log->filepath;
-		(void)io_add_notify(path, notify_callback, inotify,
-				    &inotify->io_wait);
+		(void)io_add_notify(inotify->list_log_path, notify_callback,
+				    inotify, &inotify->io_wait);
+		/* we need to check for INBOX explicitly, because INBOX changes
+		   don't get added to mailbox.list.index.log */
+		if (inotify->inbox_log_path != NULL) {
+			(void)io_add_notify(inotify->inbox_log_path,
+					    notify_callback, inotify,
+					    &inotify->io_wait_inbox);
+		}
 		/* check with timeout as well, in case io_add_notify()
 		   doesn't work (e.g. NFS) */
 		check_interval = notify->list->mail_set->mailbox_idle_check_interval;


More information about the dovecot-cvs mailing list