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);