From: Timo Sirainen Date: Mon, 7 Sep 2015 20:55:31 +0000 (+0300) Subject: Mailbox list notify API changed to return multiple events at once. X-Git-Tag: 2.2.19.rc1~77 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e27db67b4549773e5015643e776bda9e7025719f;p=thirdparty%2Fdovecot%2Fcore.git 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. --- diff --git a/src/imap/imap-notify.c b/src/imap/imap-notify.c index 34d8b0e610..f5b001e45b 100644 --- a/src/imap/imap-notify.c +++ b/src/imap/imap-notify.c @@ -57,27 +57,17 @@ static int imap_notify_status(struct imap_notify_namespace *notify_ns, 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 @@ imap_notify_next(struct imap_notify_namespace *notify_ns, 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 @@ imap_notify_match_event(struct imap_notify_namespace *notify_ns, { 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; + } + if ((wanted_events & IMAP_NOTIFY_EVENT_MESSAGE_NEW) != 0) { + if ((rec->events & MAILBOX_LIST_NOTIFY_APPENDS) != 0) + return TRUE; } - 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 --git a/src/lib-storage/list/mailbox-list-index-notify.c b/src/lib-storage/list/mailbox-list-index-notify.c index 88c4ab6aa0..868253df8f 100644 --- a/src/lib-storage/list/mailbox-list-index-notify.c +++ b/src/lib-storage/list/mailbox-list-index-notify.c @@ -591,7 +591,7 @@ mailbox_list_index_notify_rename(struct mailbox_list_notify_index *inotify, 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 @@ mailbox_list_index_notify_subscribe(struct mailbox_list_notify_index *inotify, 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 @@ mailbox_list_index_notify_unsubscribe(struct mailbox_list_notify_index *inotify, 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 @@ mailbox_list_index_notify_expunge(struct mailbox_list_notify_index *inotify, 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 @@ mailbox_list_index_notify_new(struct mailbox_list_notify_index *inotify, 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 @@ mailbox_list_index_notify_change(struct mailbox_list_notify_index *inotify, 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 @@ int mailbox_list_index_notify_next(struct mailbox_list_notify *notify, 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 --git a/src/lib-storage/mailbox-list-notify.h b/src/lib-storage/mailbox-list-notify.h index 5f15b94616..7e63909e65 100644 --- a/src/lib-storage/mailbox-list-notify.h +++ b/src/lib-storage/mailbox-list-notify.h @@ -30,7 +30,8 @@ struct mailbox_list_notify { }; struct mailbox_list_notify_rec { - enum mailbox_list_notify_event event; + /* Each record can contain multiple events */ + enum mailbox_list_notify_event events; /* For all events: */ const char *storage_name, *vname;