dovecot-2.2: Mailbox list notify API changed to return multiple ...

dovecot at dovecot.org dovecot at dovecot.org
Mon Sep 7 20:56:38 UTC 2015


details:   http://hg.dovecot.org/dovecot-2.2/rev/fa979ccfa34c
changeset: 19117:fa979ccfa34c
user:      Timo Sirainen <tss at iki.fi>
date:      Mon Sep 07 23:55:31 2015 +0300
description:
Mailbox list notify API changed to return multiple events at once.
This fixes some issues where a single event could actually trigger multiple
different kinds of events.

diffstat:

 src/imap/imap-notify.c                           |  156 ++++++++++------------
 src/lib-storage/list/mailbox-list-index-notify.c |   35 ++--
 src/lib-storage/mailbox-list-notify.h            |    3 +-
 3 files changed, 93 insertions(+), 101 deletions(-)

diffs (truncated from 303 to 300 lines):

diff -r 73acc7075146 -r fa979ccfa34c src/imap/imap-notify.c
--- a/src/imap/imap-notify.c	Mon Sep 07 23:08:44 2015 +0300
+++ b/src/imap/imap-notify.c	Mon Sep 07 23:55:31 2015 +0300
@@ -57,27 +57,17 @@
 		items.status |= STATUS_HIGHESTMODSEQ;
 
 	box = mailbox_alloc(notify_ns->ns->list, rec->vname, 0);
-	switch (rec->event) {
-	case MAILBOX_LIST_NOTIFY_UIDVALIDITY:
+	if ((rec->events & MAILBOX_LIST_NOTIFY_UIDVALIDITY) != 0) {
 		items.status |= STATUS_UIDVALIDITY | STATUS_UIDNEXT |
 			STATUS_MESSAGES | STATUS_UNSEEN;
-		break;
-	case MAILBOX_LIST_NOTIFY_APPENDS:
-	case MAILBOX_LIST_NOTIFY_EXPUNGES:
+	}
+	if ((rec->events & (MAILBOX_LIST_NOTIFY_APPENDS |
+			    MAILBOX_LIST_NOTIFY_EXPUNGES)) != 0)
 		items.status |= STATUS_UIDNEXT | STATUS_MESSAGES | STATUS_UNSEEN;
-		break;
-	case MAILBOX_LIST_NOTIFY_SEEN_CHANGES:
+	if ((rec->events & MAILBOX_LIST_NOTIFY_SEEN_CHANGES) != 0)
 		items.status |= STATUS_UNSEEN;
-		break;
-	case MAILBOX_LIST_NOTIFY_MODSEQ_CHANGES:
+	if ((rec->events & MAILBOX_LIST_NOTIFY_MODSEQ_CHANGES) != 0) {
 		/* if HIGHESTMODSEQ isn't being sent, don't send anything */
-		break;
-	case MAILBOX_LIST_NOTIFY_CREATE:
-	case MAILBOX_LIST_NOTIFY_DELETE:
-	case MAILBOX_LIST_NOTIFY_RENAME:
-	case MAILBOX_LIST_NOTIFY_SUBSCRIBE:
-	case MAILBOX_LIST_NOTIFY_UNSUBSCRIBE:
-		i_unreached();
 	}
 	if (items.status == 0) {
 		/* don't send anything */
@@ -100,46 +90,50 @@
 		 const struct mailbox_list_notify_rec *rec)
 {
 	enum mailbox_info_flags mailbox_flags;
-	int ret = 1;
+	int ret;
 
-	switch (rec->event) {
-	case MAILBOX_LIST_NOTIFY_CREATE:
+	if ((rec->events & MAILBOX_LIST_NOTIFY_CREATE) != 0) {
 		if (mailbox_list_mailbox(notify_ns->ns->list, rec->storage_name,
 					 &mailbox_flags) < 0)
 			mailbox_flags = 0;
-		ret = imap_notify_list(notify_ns, rec, mailbox_flags);
-		break;
-	case MAILBOX_LIST_NOTIFY_DELETE:
-		ret = imap_notify_list(notify_ns, rec, MAILBOX_NONEXISTENT);
-		break;
-	case MAILBOX_LIST_NOTIFY_RENAME:
+		if ((ret = imap_notify_list(notify_ns, rec, mailbox_flags)) <= 0)
+			return ret;
+	}
+	if ((rec->events & MAILBOX_LIST_NOTIFY_DELETE) != 0) {
+		if ((ret = imap_notify_list(notify_ns, rec, MAILBOX_NONEXISTENT)) < 0)
+			return ret;
+	}
+	if ((rec->events & MAILBOX_LIST_NOTIFY_RENAME) != 0) {
 		if (mailbox_list_mailbox(notify_ns->ns->list, rec->storage_name,
 					 &mailbox_flags) < 0)
 			mailbox_flags = 0;
-		ret = imap_notify_list(notify_ns, rec, mailbox_flags);
-		break;
-	case MAILBOX_LIST_NOTIFY_SUBSCRIBE:
+		if ((ret = imap_notify_list(notify_ns, rec, mailbox_flags)) < 0)
+			return ret;
+	}
+	if ((rec->events & MAILBOX_LIST_NOTIFY_SUBSCRIBE) != 0) {
 		if (mailbox_list_mailbox(notify_ns->ns->list, rec->storage_name,
 					 &mailbox_flags) < 0)
 			mailbox_flags = 0;
-		ret = imap_notify_list(notify_ns, rec,
-				       mailbox_flags | MAILBOX_SUBSCRIBED);
-		break;
-	case MAILBOX_LIST_NOTIFY_UNSUBSCRIBE:
+		if ((ret = imap_notify_list(notify_ns, rec,
+				     mailbox_flags | MAILBOX_SUBSCRIBED)) < 0)
+			return ret;
+	}
+	if ((rec->events & MAILBOX_LIST_NOTIFY_UNSUBSCRIBE) != 0) {
 		if (mailbox_list_mailbox(notify_ns->ns->list, rec->storage_name,
 					 &mailbox_flags) < 0)
 			mailbox_flags = 0;
-		ret = imap_notify_list(notify_ns, rec, mailbox_flags);
-		break;
-	case MAILBOX_LIST_NOTIFY_UIDVALIDITY:
-	case MAILBOX_LIST_NOTIFY_APPENDS:
-	case MAILBOX_LIST_NOTIFY_EXPUNGES:
-	case MAILBOX_LIST_NOTIFY_SEEN_CHANGES:
-	case MAILBOX_LIST_NOTIFY_MODSEQ_CHANGES:
-		ret = imap_notify_status(notify_ns, rec);
-		break;
+		if ((ret = imap_notify_list(notify_ns, rec, mailbox_flags)) < 0)
+			return ret;
 	}
-	return ret;
+	if ((rec->events & (MAILBOX_LIST_NOTIFY_UIDVALIDITY |
+			    MAILBOX_LIST_NOTIFY_APPENDS |
+			    MAILBOX_LIST_NOTIFY_EXPUNGES |
+			    MAILBOX_LIST_NOTIFY_SEEN_CHANGES |
+			    MAILBOX_LIST_NOTIFY_MODSEQ_CHANGES)) != 0) {
+		if ((ret = imap_notify_status(notify_ns, rec)) < 0)
+			return ret;
+	}
+	return 1;
 }
 
 static bool
@@ -149,53 +143,45 @@
 {
 	enum imap_notify_event wanted_events = notify_boxes->events;
 	struct mailbox *box;
-	bool mailbox_event = FALSE;
 
-	switch (rec->event) {
-	case MAILBOX_LIST_NOTIFY_CREATE:
-	case MAILBOX_LIST_NOTIFY_DELETE:
-	case MAILBOX_LIST_NOTIFY_RENAME:
-		if ((wanted_events & IMAP_NOTIFY_EVENT_MAILBOX_NAME) == 0)
-			return FALSE;
-		break;
-	case MAILBOX_LIST_NOTIFY_SUBSCRIBE:
-	case MAILBOX_LIST_NOTIFY_UNSUBSCRIBE:
-		if ((wanted_events & IMAP_NOTIFY_EVENT_SUBSCRIPTION_CHANGE) == 0)
-			return FALSE;
-		break;
-	case MAILBOX_LIST_NOTIFY_UIDVALIDITY:
-		if ((wanted_events & (IMAP_NOTIFY_EVENT_MESSAGE_NEW |
-				      IMAP_NOTIFY_EVENT_MESSAGE_EXPUNGE |
-				      IMAP_NOTIFY_EVENT_FLAG_CHANGE)) == 0)
-			return FALSE;
-		mailbox_event = TRUE;
-		break;
-	case MAILBOX_LIST_NOTIFY_APPENDS:
-		if ((wanted_events & IMAP_NOTIFY_EVENT_MESSAGE_NEW) == 0)
-			return FALSE;
-		mailbox_event = TRUE;
-		break;
-	case MAILBOX_LIST_NOTIFY_EXPUNGES:
-		if ((wanted_events & IMAP_NOTIFY_EVENT_MESSAGE_EXPUNGE) == 0)
-			return FALSE;
-		mailbox_event = TRUE;
-		break;
-	case MAILBOX_LIST_NOTIFY_SEEN_CHANGES:
-	case MAILBOX_LIST_NOTIFY_MODSEQ_CHANGES:
-		if ((wanted_events & IMAP_NOTIFY_EVENT_FLAG_CHANGE) == 0)
-			return FALSE;
-		mailbox_event = TRUE;
-		break;
+	/* check for mailbox list events first */
+	if ((wanted_events & IMAP_NOTIFY_EVENT_MAILBOX_NAME) != 0) {
+		if ((rec->events & (MAILBOX_LIST_NOTIFY_CREATE |
+				    MAILBOX_LIST_NOTIFY_DELETE |
+				    MAILBOX_LIST_NOTIFY_RENAME)) != 0)
+			return TRUE;
+	}
+	if ((wanted_events & IMAP_NOTIFY_EVENT_SUBSCRIPTION_CHANGE) != 0) {
+		if ((rec->events & (MAILBOX_LIST_NOTIFY_SUBSCRIBE |
+				    MAILBOX_LIST_NOTIFY_UNSUBSCRIBE)) != 0)
+			return TRUE;
 	}
 
-	if (mailbox_event) {
-		/* if this is an even for selected mailbox, ignore it */
-		box = notify_ns->ctx->client->mailbox;
-		if (box != NULL &&
-		    mailbox_equals(box, notify_ns->ns, rec->vname))
-			return FALSE;
+	/* if this is an event for the selected mailbox, ignore it */
+	box = notify_ns->ctx->client->mailbox;
+	if (box != NULL && mailbox_equals(box, notify_ns->ns, rec->vname))
+		return FALSE;
+
+	if ((wanted_events & (IMAP_NOTIFY_EVENT_MESSAGE_NEW |
+			      IMAP_NOTIFY_EVENT_MESSAGE_EXPUNGE |
+			      IMAP_NOTIFY_EVENT_FLAG_CHANGE)) != 0) {
+		if ((rec->events & MAILBOX_LIST_NOTIFY_UIDVALIDITY) != 0)
+			return TRUE;
 	}
-	return TRUE;
+	if ((wanted_events & IMAP_NOTIFY_EVENT_MESSAGE_NEW) != 0) {
+		if ((rec->events & MAILBOX_LIST_NOTIFY_APPENDS) != 0)
+			return TRUE;
+	}
+	if ((wanted_events & IMAP_NOTIFY_EVENT_MESSAGE_EXPUNGE) != 0) {
+		if ((rec->events & MAILBOX_LIST_NOTIFY_EXPUNGES) != 0)
+			return TRUE;
+	}
+	if ((wanted_events & IMAP_NOTIFY_EVENT_FLAG_CHANGE) != 0) {
+		if ((rec->events & (MAILBOX_LIST_NOTIFY_SEEN_CHANGES |
+				    MAILBOX_LIST_NOTIFY_MODSEQ_CHANGES)) != 0)
+			return TRUE;
+	}
+	return FALSE;
 }
 
 bool imap_notify_match_mailbox(struct imap_notify_namespace *notify_ns,
diff -r 73acc7075146 -r fa979ccfa34c src/lib-storage/list/mailbox-list-index-notify.c
--- a/src/lib-storage/list/mailbox-list-index-notify.c	Mon Sep 07 23:08:44 2015 +0300
+++ b/src/lib-storage/list/mailbox-list-index-notify.c	Mon Sep 07 23:55:31 2015 +0300
@@ -591,7 +591,7 @@
 		return FALSE;
 
 	rec->old_vname = old_vname;
-	rec->event = MAILBOX_LIST_NOTIFY_RENAME;
+	rec->events = MAILBOX_LIST_NOTIFY_RENAME;
 	return TRUE;
 }
 
@@ -607,7 +607,7 @@
 	rec->vname = *vnamep;
 	rec->storage_name = mailbox_list_get_storage_name(inotify->notify.list,
 							  rec->vname);
-	rec->event = MAILBOX_LIST_NOTIFY_SUBSCRIBE;
+	rec->events = MAILBOX_LIST_NOTIFY_SUBSCRIBE;
 	return TRUE;
 }
 
@@ -623,7 +623,7 @@
 	rec->vname = *vnamep;
 	rec->storage_name = mailbox_list_get_storage_name(inotify->notify.list,
 							  rec->vname);
-	rec->event = MAILBOX_LIST_NOTIFY_UNSUBSCRIBE;
+	rec->events = MAILBOX_LIST_NOTIFY_UNSUBSCRIBE;
 	return TRUE;
 }
 
@@ -637,7 +637,7 @@
 	if (!mailbox_list_index_notify_lookup(inotify, inotify->old_view,
 					      uid, 0, &status, &rec))
 		return FALSE;
-	rec->event = MAILBOX_LIST_NOTIFY_DELETE;
+	rec->events = MAILBOX_LIST_NOTIFY_DELETE;
 	return TRUE;
 }
 
@@ -651,7 +651,7 @@
 	if (!mailbox_list_index_notify_lookup(inotify, inotify->view,
 					      uid, 0, &status, &rec))
 		i_unreached();
-	rec->event = MAILBOX_LIST_NOTIFY_CREATE;
+	rec->events = MAILBOX_LIST_NOTIFY_CREATE;
 	return TRUE;
 }
 
@@ -674,15 +674,20 @@
 	nnode = mailbox_list_notify_tree_lookup(inotify->tree,
 						rec->storage_name);
 	if (nnode == NULL || nnode->uidvalidity != status.uidvalidity)
-		rec->event = MAILBOX_LIST_NOTIFY_UIDVALIDITY;
-	else if (nnode->uidnext != status.uidnext)
-		rec->event = MAILBOX_LIST_NOTIFY_APPENDS;
-	else if (nnode->messages > status.messages)
-		rec->event = MAILBOX_LIST_NOTIFY_EXPUNGES;
-	else if (nnode->unseen != status.unseen)
-		rec->event = MAILBOX_LIST_NOTIFY_SEEN_CHANGES;
-	else if (nnode->highest_modseq < status.highest_modseq)
-		rec->event = MAILBOX_LIST_NOTIFY_MODSEQ_CHANGES;
+		rec->events |= MAILBOX_LIST_NOTIFY_UIDVALIDITY;
+	if (nnode->uidnext != status.uidnext)
+		rec->events |= MAILBOX_LIST_NOTIFY_APPENDS;
+	if (nnode->messages > status.messages) {
+		/* NOTE: not entirely reliable, since there could be both
+		   expunges and appends.. but it shouldn't make any difference
+		   in practise, since anybody interested in expunges is most
+		   likely also interested in appends. */
+		rec->events |= MAILBOX_LIST_NOTIFY_EXPUNGES;
+	}
+	if (nnode->unseen != status.unseen)
+		rec->events |= MAILBOX_LIST_NOTIFY_SEEN_CHANGES;
+	if (nnode->highest_modseq < status.highest_modseq)
+		rec->events |= MAILBOX_LIST_NOTIFY_MODSEQ_CHANGES;
 	else {
 		/* nothing changed */
 		return FALSE;
@@ -748,7 +753,7 @@
 	if (!inotify->initialized)
 		mailbox_list_index_notify_read_init(inotify);
 	while (mailbox_list_index_notify_try_next(inotify)) {
-		if ((inotify->notify_rec.event & inotify->notify.mask) != 0) {
+		if ((inotify->notify_rec.events & inotify->notify.mask) != 0) {
 			*rec_r = &inotify->notify_rec;
 			return 1;
 		} else {
diff -r 73acc7075146 -r fa979ccfa34c src/lib-storage/mailbox-list-notify.h
--- a/src/lib-storage/mailbox-list-notify.h	Mon Sep 07 23:08:44 2015 +0300
+++ b/src/lib-storage/mailbox-list-notify.h	Mon Sep 07 23:55:31 2015 +0300
@@ -30,7 +30,8 @@
 };
 
 struct mailbox_list_notify_rec {
-	enum mailbox_list_notify_event event;
+	/* Each record can contain multiple events */
+	enum mailbox_list_notify_event events;


More information about the dovecot-cvs mailing list