Mercurial > dovecot > core-2.2
comparison src/lib-storage/list/mailbox-list-index-notify.c @ 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 | 71589abee915 |
comparison
equal
deleted
inserted
replaced
22456:d1658f4cb079 | 22457:5de2bae83c93 |
---|---|
58 struct mailbox_list_notify_rec notify_rec; | 58 struct mailbox_list_notify_rec notify_rec; |
59 string_t *rec_name; | 59 string_t *rec_name; |
60 | 60 |
61 char *list_log_path, *inbox_log_path; | 61 char *list_log_path, *inbox_log_path; |
62 struct stat list_last_st, inbox_last_st; | 62 struct stat list_last_st, inbox_last_st; |
63 struct mailbox *inbox; | |
63 | 64 |
64 unsigned int initialized:1; | 65 unsigned int initialized:1; |
65 unsigned int read_failed:1; | 66 unsigned int read_failed:1; |
66 unsigned int inbox_event_pending:1; | 67 unsigned int inbox_event_pending:1; |
67 }; | 68 }; |
69 | |
70 static const enum mailbox_status_items notify_status_items = | |
71 STATUS_UIDVALIDITY | STATUS_UIDNEXT | STATUS_MESSAGES | | |
72 STATUS_UNSEEN | STATUS_HIGHESTMODSEQ; | |
68 | 73 |
69 static enum mailbox_list_notify_event | 74 static enum mailbox_list_notify_event |
70 mailbox_list_index_get_changed_events(const struct mailbox_notify_node *nnode, | 75 mailbox_list_index_get_changed_events(const struct mailbox_notify_node *nnode, |
71 const struct mailbox_status *status) | 76 const struct mailbox_status *status) |
72 { | 77 { |
97 nnode->uidvalidity = status->uidvalidity; | 102 nnode->uidvalidity = status->uidvalidity; |
98 nnode->uidnext = status->uidnext; | 103 nnode->uidnext = status->uidnext; |
99 nnode->messages = status->messages; | 104 nnode->messages = status->messages; |
100 nnode->unseen = status->unseen; | 105 nnode->unseen = status->unseen; |
101 nnode->highest_modseq = status->highest_modseq; | 106 nnode->highest_modseq = status->highest_modseq; |
107 } | |
108 | |
109 static void | |
110 mailbox_list_index_notify_init_inbox(struct mailbox_list_notify_index *inotify) | |
111 { | |
112 inotify->inbox = mailbox_alloc(inotify->notify.list, "INBOX", | |
113 MAILBOX_FLAG_READONLY); | |
114 if (mailbox_open(inotify->inbox) < 0) | |
115 mailbox_free(&inotify->inbox); | |
116 inotify->inbox_log_path = | |
117 i_strconcat(inotify->inbox->index->filepath, ".log", NULL); | |
102 } | 118 } |
103 | 119 |
104 int mailbox_list_index_notify_init(struct mailbox_list *list, | 120 int mailbox_list_index_notify_init(struct mailbox_list *list, |
105 enum mailbox_list_notify_event mask, | 121 enum mailbox_list_notify_event mask, |
106 struct mailbox_list_notify **notify_r) | 122 struct mailbox_list_notify **notify_r) |
144 /* not interested in mailbox changes */ | 160 /* not interested in mailbox changes */ |
145 } else if (mailbox_list_get_path(list, "INBOX", MAILBOX_LIST_PATH_TYPE_INDEX, | 161 } else if (mailbox_list_get_path(list, "INBOX", MAILBOX_LIST_PATH_TYPE_INDEX, |
146 &index_dir) <= 0) { | 162 &index_dir) <= 0) { |
147 /* no indexes for INBOX? can't handle it */ | 163 /* no indexes for INBOX? can't handle it */ |
148 } else { | 164 } else { |
149 /* FIXME: annoyingly hardcoded filename. */ | 165 mailbox_list_index_notify_init_inbox(inotify); |
150 inotify->inbox_log_path = i_strdup_printf( | |
151 "%s/"MAIL_INDEX_PREFIX".log", index_dir); | |
152 } | 166 } |
153 | 167 |
154 *notify_r = &inotify->notify; | 168 *notify_r = &inotify->notify; |
155 return 1; | 169 return 1; |
156 } | 170 } |
159 { | 173 { |
160 struct mailbox_list_notify_index *inotify = | 174 struct mailbox_list_notify_index *inotify = |
161 (struct mailbox_list_notify_index *)notify; | 175 (struct mailbox_list_notify_index *)notify; |
162 bool b; | 176 bool b; |
163 | 177 |
178 if (inotify->inbox != NULL) | |
179 mailbox_free(&inotify->inbox); | |
164 if (inotify->subscriptions != NULL) | 180 if (inotify->subscriptions != NULL) |
165 mailbox_tree_deinit(&inotify->subscriptions); | 181 mailbox_tree_deinit(&inotify->subscriptions); |
166 if (inotify->io_wait != NULL) | 182 if (inotify->io_wait != NULL) |
167 io_remove(&inotify->io_wait); | 183 io_remove(&inotify->io_wait); |
168 if (inotify->io_wait_inbox != NULL) | 184 if (inotify->io_wait_inbox != NULL) |
722 | 738 |
723 static bool | 739 static bool |
724 mailbox_list_index_notify_change(struct mailbox_list_notify_index *inotify, | 740 mailbox_list_index_notify_change(struct mailbox_list_notify_index *inotify, |
725 uint32_t uid) | 741 uint32_t uid) |
726 { | 742 { |
727 const enum mailbox_status_items status_items = | |
728 STATUS_UIDVALIDITY | STATUS_UIDNEXT | STATUS_MESSAGES | | |
729 STATUS_UNSEEN | STATUS_HIGHESTMODSEQ; | |
730 struct mailbox_list_notify_rec *rec; | 743 struct mailbox_list_notify_rec *rec; |
731 struct mailbox_notify_node *nnode, empty_node; | 744 struct mailbox_notify_node *nnode, empty_node; |
732 struct mailbox_status status; | 745 struct mailbox_status status; |
733 | 746 |
734 if (!mailbox_list_index_notify_lookup(inotify, inotify->view, | 747 if (!mailbox_list_index_notify_lookup(inotify, inotify->view, |
735 uid, status_items, &status, &rec)) | 748 uid, notify_status_items, |
749 &status, &rec)) | |
736 i_unreached(); | 750 i_unreached(); |
737 | 751 |
738 /* get the old status */ | 752 /* get the old status */ |
739 nnode = mailbox_list_notify_tree_lookup(inotify->tree, | 753 nnode = mailbox_list_notify_tree_lookup(inotify->tree, |
740 rec->storage_name); | 754 rec->storage_name); |
787 return TRUE; | 801 return TRUE; |
788 } | 802 } |
789 return FALSE; | 803 return FALSE; |
790 } | 804 } |
791 | 805 |
806 static enum mailbox_list_notify_event | |
807 mailbox_list_notify_inbox_get_events(struct mailbox_list_notify_index *inotify) | |
808 { | |
809 struct mailbox_status old_status, new_status; | |
810 struct mailbox_notify_node old_nnode; | |
811 | |
812 mailbox_get_open_status(inotify->inbox, notify_status_items, &old_status); | |
813 if (mailbox_sync(inotify->inbox, MAILBOX_SYNC_FLAG_FAST) < 0) { | |
814 i_error("Mailbox list index notify: Failed to sync INBOX: %s", | |
815 mailbox_get_last_internal_error(inotify->inbox, NULL)); | |
816 return 0; | |
817 } | |
818 mailbox_get_open_status(inotify->inbox, notify_status_items, &new_status); | |
819 | |
820 mailbox_notify_node_update_status(&old_nnode, &old_status); | |
821 return mailbox_list_index_get_changed_events(&old_nnode, &new_status); | |
822 } | |
823 | |
792 int mailbox_list_index_notify_next(struct mailbox_list_notify *notify, | 824 int mailbox_list_index_notify_next(struct mailbox_list_notify *notify, |
793 const struct mailbox_list_notify_rec **rec_r) | 825 const struct mailbox_list_notify_rec **rec_r) |
794 { | 826 { |
795 struct mailbox_list_notify_index *inotify = | 827 struct mailbox_list_notify_index *inotify = |
796 (struct mailbox_list_notify_index *)notify; | 828 (struct mailbox_list_notify_index *)notify; |
811 if (inotify->inbox_event_pending) { | 843 if (inotify->inbox_event_pending) { |
812 inotify->inbox_event_pending = FALSE; | 844 inotify->inbox_event_pending = FALSE; |
813 i_zero(&inotify->notify_rec); | 845 i_zero(&inotify->notify_rec); |
814 inotify->notify_rec.vname = "INBOX"; | 846 inotify->notify_rec.vname = "INBOX"; |
815 inotify->notify_rec.storage_name = "INBOX"; | 847 inotify->notify_rec.storage_name = "INBOX"; |
816 /* Don't bother trying to figure out which event exactly this | 848 inotify->notify_rec.events = |
817 is. Just send them all and let the caller handle it. */ | 849 mailbox_list_notify_inbox_get_events(inotify); |
818 inotify->notify_rec.events = MAILBOX_LIST_NOTIFY_APPENDS | | |
819 MAILBOX_LIST_NOTIFY_EXPUNGES | | |
820 MAILBOX_LIST_NOTIFY_SEEN_CHANGES | | |
821 MAILBOX_LIST_NOTIFY_MODSEQ_CHANGES; | |
822 *rec_r = &inotify->notify_rec; | 850 *rec_r = &inotify->notify_rec; |
823 return 1; | 851 return 1; |
824 } | 852 } |
825 | 853 |
826 mailbox_list_index_notify_read_deinit(inotify); | 854 mailbox_list_index_notify_read_deinit(inotify); |