bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen ARRAY_TYPE(seq_range) new_uids, expunged_uids, changed_uids;
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen ARRAY_TYPE(const_string) new_subscriptions, new_unsubscriptions;
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainen ARRAY(struct mailbox_list_notify_rename) renames;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen struct seq_range_iter new_uids_iter, expunged_uids_iter;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen unsigned int new_uids_n, expunged_uids_n, changed_uids_n;
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen unsigned int rename_idx, subscription_idx, unsubscription_idx;
838a76b0f4e65e98eeca3c134b8c290bc94eb849Timo Sirainenstatic const enum mailbox_status_items notify_status_items =
838a76b0f4e65e98eeca3c134b8c290bc94eb849Timo Sirainen STATUS_UIDVALIDITY | STATUS_UIDNEXT | STATUS_MESSAGES |
5b898189915be7054d53d57029fe77af7856cb0cTimo Sirainenmailbox_list_index_get_changed_events(const struct mailbox_notify_node *nnode,
5b898189915be7054d53d57029fe77af7856cb0cTimo Sirainen if (nnode->uidvalidity != status->uidvalidity)
5b898189915be7054d53d57029fe77af7856cb0cTimo Sirainen /* NOTE: not entirely reliable, since there could be both
5b898189915be7054d53d57029fe77af7856cb0cTimo Sirainen expunges and appends.. but it shouldn't make any difference
5b898189915be7054d53d57029fe77af7856cb0cTimo Sirainen in practise, since anybody interested in expunges is most
5b898189915be7054d53d57029fe77af7856cb0cTimo Sirainen likely also interested in appends. */
5b898189915be7054d53d57029fe77af7856cb0cTimo Sirainen if (nnode->highest_modseq < status->highest_modseq)
5b898189915be7054d53d57029fe77af7856cb0cTimo Sirainenmailbox_notify_node_update_status(struct mailbox_notify_node *nnode,
5b898189915be7054d53d57029fe77af7856cb0cTimo Sirainen nnode->highest_modseq = status->highest_modseq;
838a76b0f4e65e98eeca3c134b8c290bc94eb849Timo Sirainenmailbox_list_index_notify_init_inbox(struct mailbox_list_notify_index *inotify)
838a76b0f4e65e98eeca3c134b8c290bc94eb849Timo Sirainen inotify->inbox = mailbox_alloc(inotify->notify.list, "INBOX",
6c17d1adef038b674a9e6f48c6a12aee12ba324bMartti Rannanjärvi i_strconcat(inotify->inbox->index->filepath,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainenint mailbox_list_index_notify_init(struct mailbox_list *list,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen struct mailbox_list_index *ilist = INDEX_LIST_CONTEXT(list);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen /* can't do this without mailbox list indexes */
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen inotify = i_new(struct mailbox_list_notify_index, 1);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen inotify->view = mail_index_view_open(ilist->index);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen inotify->old_view = mail_index_view_dup_private(inotify->view);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen inotify->tree = mailbox_list_notify_tree_init(list);
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen i_array_init(&inotify->new_subscriptions, 16);
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen i_array_init(&inotify->new_unsubscriptions, 16);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen inotify->rec_name = str_new(default_pool, 64);
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen (void)mailbox_list_iter_subscriptions_refresh(list);
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen inotify->subscriptions = mailbox_tree_dup(list->subscriptions);
9dd7c6f7fc78a26a5d27457ed9415de1f924848bTimo Sirainen inotify->list_log_path = i_strdup(ilist->index->log->filepath);
91cec71840dda9bd4c26b8e88e6af18262d6b36aTimo Sirainen if (list->mail_set->mailbox_list_index_include_inbox) {
91cec71840dda9bd4c26b8e88e6af18262d6b36aTimo Sirainen /* INBOX can be handled also using mailbox list index */
91cec71840dda9bd4c26b8e88e6af18262d6b36aTimo Sirainen } else if ((list->ns->flags & NAMESPACE_FLAG_INBOX_ANY) == 0) {
91cec71840dda9bd4c26b8e88e6af18262d6b36aTimo Sirainen /* no INBOX in this namespace */
921a1eac5bd1375b86f5fc423257513c9e94c3cdTimo Sirainen } else if ((mask & MAILBOX_LIST_NOTIFY_STATUS) == 0) {
921a1eac5bd1375b86f5fc423257513c9e94c3cdTimo Sirainen /* not interested in mailbox changes */
91cec71840dda9bd4c26b8e88e6af18262d6b36aTimo Sirainen } else if (mailbox_list_get_path(list, "INBOX", MAILBOX_LIST_PATH_TYPE_INDEX,
91cec71840dda9bd4c26b8e88e6af18262d6b36aTimo Sirainen /* no indexes for INBOX? can't handle it */
838a76b0f4e65e98eeca3c134b8c290bc94eb849Timo Sirainen mailbox_list_index_notify_init_inbox(inotify);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainenvoid mailbox_list_index_notify_deinit(struct mailbox_list_notify *notify)
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen (void)mail_index_view_sync_commit(&inotify->sync_ctx, &b);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen mailbox_list_notify_tree_deinit(&inotify->tree);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainennotify_lookup_guid(struct mailbox_list_notify_index *inotify,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen uint32_t uid, enum mailbox_status_items items,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen struct mailbox_status *status_r, guid_128_t guid_r)
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen index_node = mailbox_list_index_lookup_uid(ilist, uid);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen /* re-parse the index list using the given view. we could be
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen jumping here between old and new view. */
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen (void)mailbox_list_index_parse(inotify->notify.list,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen index_node = mailbox_list_index_lookup_uid(ilist, uid);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen /* get GUID */
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen (void)mailbox_list_index_status(inotify->notify.list, view, seq,
182724707b7f73a181716d439863fb756d8ad03dTimo Sirainenstatic void notify_update_stat(struct mailbox_list_notify_index *inotify,
182724707b7f73a181716d439863fb756d8ad03dTimo Sirainen stat(inotify->list_log_path, &inotify->list_last_st) < 0 &&
9dd7c6f7fc78a26a5d27457ed9415de1f924848bTimo Sirainen i_error("stat(%s) failed: %m", inotify->list_log_path);
182724707b7f73a181716d439863fb756d8ad03dTimo Sirainen if (inotify->inbox_log_path != NULL && stat_inbox) {
9dd7c6f7fc78a26a5d27457ed9415de1f924848bTimo Sirainen if (stat(inotify->inbox_log_path, &inotify->inbox_last_st) < 0 &&
9dd7c6f7fc78a26a5d27457ed9415de1f924848bTimo Sirainen i_error("stat(%s) failed: %m", inotify->inbox_log_path);
9dd7c6f7fc78a26a5d27457ed9415de1f924848bTimo Sirainen mailbox_list_index_notify_wait(&inotify->notify, NULL, NULL);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainenmailbox_list_index_notify_sync_init(struct mailbox_list_notify_index *inotify)
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen (void)mail_index_refresh(inotify->view->index);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen /* sync the view so that map extensions gets updated */
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen inotify->sync_ctx = mail_index_view_sync_begin(inotify->view, 0);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen mail_transaction_log_view_mark(inotify->view->log_view);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen while (mail_index_view_sync_next(inotify->sync_ctx, &sync_rec)) ;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen mail_transaction_log_view_rewind(inotify->view->log_view);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainenstatic bool notify_ext_rec(struct mailbox_list_notify_index *inotify,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen struct mailbox_list_notify *notify = &inotify->notify;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen /* UIDVALIDITY changed */
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen if ((notify->mask & MAILBOX_LIST_NOTIFY_UIDVALIDITY) == 0)
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen /* APPEND, EXPUNGE, \Seen or \Recent flag change */
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen if ((notify->mask & MAILBOX_LIST_NOTIFY_STATUS) == 0)
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen /* when this doesn't come with EXT_MSGS update,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen it can only be a flag change or an explicit
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen modseq change */
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen if ((notify->mask & MAILBOX_LIST_NOTIFY_MODSEQ_CHANGES) == 0)
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen seq_range_array_add(&inotify->changed_uids, uid);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainenmailbox_list_index_notify_read_next(struct mailbox_list_notify_index *inotify)
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen struct mailbox_list_notify *notify = &inotify->notify;
43ce61b1d755832186f12b9739d18212b4744d14Aki Tuomi struct mailbox_list_index *ilist = INDEX_LIST_CONTEXT_REQUIRE(notify->list);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen ret = mail_transaction_log_view_next(inotify->view->log_view,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen if ((hdr->type & MAIL_TRANSACTION_EXTERNAL) == 0) {
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen /* all mailbox index updates are external */
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen switch (hdr->type & MAIL_TRANSACTION_TYPE_MASK) {
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen /* mailbox added or renamed */
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen if ((notify->mask & (MAILBOX_LIST_NOTIFY_CREATE |
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen seq_range_array_add(&inotify->new_uids, rec->uid);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen /* mailbox deleted or renamed */
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen const struct mail_transaction_expunge_guid *rec, *end;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen if ((notify->mask & (MAILBOX_LIST_NOTIFY_DELETE |
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen seq_range_array_add(&inotify->expunged_uids, rec->uid);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen struct mail_index_map *map = inotify->view->map;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen const struct mail_transaction_ext_intro *rec = data;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen /* we want to know what extension the future
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen ext-rec-updates are changing. we're assuming here that
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen there is only one ext-intro record before those,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen which is true at least for now. */
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen rec->ext_id < array_count(&map->extensions)) {
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen /* get extension by id */
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen ext = array_idx(&map->extensions, rec->ext_id);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen /* by name */
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen if (mail_index_map_lookup_ext(map, name, &ext_map_idx))
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen ext = array_idx(&map->extensions, ext_map_idx);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen else if (ext->index_idx == ilist->msgs_ext_id)
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen else if (ext->index_idx == ilist->hmodseq_ext_id)
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen const struct mail_transaction_ext_rec_update *rec;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen i_error("%s: Missing ext-intro for ext-rec-update",
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen /* the record is padded to 32bits in the transaction log */
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen ext = array_idx(&inotify->view->index->extensions,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen record_size = (sizeof(*rec) + ext->record_size + 3) & ~3;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen for (i = 0; i < hdr->size; i += record_size) {
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainenmailbox_list_inotify_entry_guid_cmp(const struct mailbox_list_inotify_entry *r1,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen ret = memcmp(r1->guid, r2->guid, sizeof(r1->guid));
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen /* this really shouldn't happen */
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainenmailbox_list_index_notify_find_renames(struct mailbox_list_notify_index *inotify)
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainen ARRAY(struct mailbox_list_inotify_entry) entries;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen /* first get all of the added and expunged GUIDs */
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen t_array_init(&entries, array_count(&inotify->new_uids) +
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen while (seq_range_array_iter_nth(&inotify->expunged_uids_iter,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen if (notify_lookup_guid(inotify, inotify->old_view, uid,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen memcpy(entry->guid, guid, sizeof(entry->guid));
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen (void)mailbox_list_index_parse(inotify->notify.list,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen while (seq_range_array_iter_nth(&inotify->new_uids_iter,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen if (notify_lookup_guid(inotify, inotify->view, uid,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen memcpy(entry->guid, guid, sizeof(entry->guid));
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen /* now sort the entries by GUID and find those that have been both
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen added and expunged */
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen array_sort(&entries, mailbox_list_inotify_entry_guid_cmp);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen memcmp(e[i-1].guid, e[i].guid, sizeof(e[i].guid)) == 0) {
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen rename = array_append_space(&inotify->renames);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen seq_range_array_remove(&inotify->expunged_uids,
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainenmailbox_list_index_notify_find_subscribes(struct mailbox_list_notify_index *inotify)
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen struct mailbox_tree_iterate_context *old_iter, *new_iter;
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen struct mailbox_tree_context *old_tree, *new_tree;
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen const char *old_path = NULL, *new_path = NULL;
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen if (mailbox_list_iter_subscriptions_refresh(inotify->notify.list) < 0)
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen mailbox_tree_sort(inotify->notify.list->subscriptions);
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen new_tree = mailbox_tree_dup(inotify->notify.list->subscriptions);
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen old_iter = mailbox_tree_iterate_init(old_tree, NULL, MAILBOX_SUBSCRIBED);
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen new_iter = mailbox_tree_iterate_init(new_tree, NULL, MAILBOX_SUBSCRIBED);
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen if (mailbox_tree_iterate_next(old_iter, &old_path) == NULL)
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen if (mailbox_tree_iterate_next(new_iter, &new_path) == NULL)
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen } else if (ret > 0) {
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen array_append(&inotify->new_subscriptions, &new_path, 1);
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen array_append(&inotify->new_unsubscriptions, &old_path, 1);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainenmailbox_list_index_notify_reset_iters(struct mailbox_list_notify_index *inotify)
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen seq_range_array_iter_init(&inotify->new_uids_iter,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen seq_range_array_iter_init(&inotify->expunged_uids_iter,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen seq_range_array_iter_init(&inotify->changed_uids_iter,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainenmailbox_list_index_notify_read_init(struct mailbox_list_notify_index *inotify)
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen /* read all changes from .log file */
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen while ((ret = mailbox_list_index_notify_read_next(inotify)) > 0) ;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen (void)mail_index_view_sync_commit(&inotify->sync_ctx, &b);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen /* remove changes for already deleted mailboxes */
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen seq_range_array_remove_seq_range(&inotify->new_uids,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen seq_range_array_remove_seq_range(&inotify->changed_uids,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen mailbox_list_index_notify_reset_iters(inotify);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen mailbox_list_index_notify_find_renames(inotify);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen mailbox_list_index_notify_reset_iters(inotify);
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen mailbox_list_index_notify_find_subscribes(inotify);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainenmailbox_list_index_notify_read_deinit(struct mailbox_list_notify_index *inotify)
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen /* save the old view so we can look up expunged records */
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen inotify->old_view = mail_index_view_dup_private(inotify->view);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainenmailbox_list_index_notify_lookup(struct mailbox_list_notify_index *inotify,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen uint32_t uid, enum mailbox_status_items items,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen struct mailbox_list_notify_rec *rec = &inotify->notify_rec;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen char ns_sep = mailbox_list_get_hierarchy_sep(inotify->notify.list);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen index_node = notify_lookup_guid(inotify, view, uid,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen /* get storage_name */
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen mailbox_list_index_node_get_path(index_node, ns_sep, inotify->rec_name);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen rec->vname = mailbox_list_get_vname(inotify->notify.list,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainenmailbox_list_index_notify_rename(struct mailbox_list_notify_index *inotify,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen unsigned int idx)
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen const struct mailbox_list_notify_rename *rename;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen /* lookup the old name */
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen if (!mailbox_list_index_notify_lookup(inotify, inotify->old_view,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen /* return using the new name */
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen if (!mailbox_list_index_notify_lookup(inotify, inotify->view,
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainenmailbox_list_index_notify_subscribe(struct mailbox_list_notify_index *inotify,
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen unsigned int idx)
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen struct mailbox_list_notify_rec *rec = &inotify->notify_rec;
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen vnamep = array_idx(&inotify->new_subscriptions, idx);
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen rec->storage_name = mailbox_list_get_storage_name(inotify->notify.list,
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainenmailbox_list_index_notify_unsubscribe(struct mailbox_list_notify_index *inotify,
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen unsigned int idx)
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen struct mailbox_list_notify_rec *rec = &inotify->notify_rec;
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen vnamep = array_idx(&inotify->new_unsubscriptions, idx);
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen rec->storage_name = mailbox_list_get_storage_name(inotify->notify.list,
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen rec->events = MAILBOX_LIST_NOTIFY_UNSUBSCRIBE;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainenmailbox_list_index_notify_expunge(struct mailbox_list_notify_index *inotify,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen if (!mailbox_list_index_notify_lookup(inotify, inotify->old_view,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainenmailbox_list_index_notify_new(struct mailbox_list_notify_index *inotify,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen if (!mailbox_list_index_notify_lookup(inotify, inotify->view,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainenmailbox_list_index_notify_change(struct mailbox_list_notify_index *inotify,
ec937f21abdd9500a450a8c16091337672e54488Timo Sirainen struct mailbox_notify_node *nnode, empty_node;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen if (!mailbox_list_index_notify_lookup(inotify, inotify->view,
2912eac52610bf9463e48f320a966d0b0c51bed0Timo Sirainen /* Mailbox is already deleted. We won't get here if we're
2912eac52610bf9463e48f320a966d0b0c51bed0Timo Sirainen tracking MAILBOX_LIST_NOTIFY_DELETE or _RENAME
2912eac52610bf9463e48f320a966d0b0c51bed0Timo Sirainen (which update expunged_uids). */
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen /* get the old status */
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen nnode = mailbox_list_notify_tree_lookup(inotify->tree,
ec937f21abdd9500a450a8c16091337672e54488Timo Sirainen /* mailbox didn't exist earlier - report all events as new */
5b898189915be7054d53d57029fe77af7856cb0cTimo Sirainen rec->events |= mailbox_list_index_get_changed_events(nnode, &status);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen /* update internal state */
5b898189915be7054d53d57029fe77af7856cb0cTimo Sirainen mailbox_notify_node_update_status(nnode, &status);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainenmailbox_list_index_notify_try_next(struct mailbox_list_notify_index *inotify)
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen /* first show mailbox deletes */
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen if (seq_range_array_iter_nth(&inotify->expunged_uids_iter,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen return mailbox_list_index_notify_expunge(inotify, uid);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen /* mailbox renames */
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen if (inotify->rename_idx < array_count(&inotify->renames)) {
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen return mailbox_list_index_notify_rename(inotify,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen /* next mailbox creates */
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen if (seq_range_array_iter_nth(&inotify->new_uids_iter,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen return mailbox_list_index_notify_new(inotify, uid);
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen /* subscribes */
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen if (inotify->subscription_idx < array_count(&inotify->new_subscriptions)) {
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen return mailbox_list_index_notify_subscribe(inotify,
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen if (inotify->unsubscription_idx < array_count(&inotify->new_unsubscriptions)) {
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen return mailbox_list_index_notify_unsubscribe(inotify,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen /* STATUS updates */
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen while (seq_range_array_iter_nth(&inotify->changed_uids_iter,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen if (mailbox_list_index_notify_change(inotify, uid))
838a76b0f4e65e98eeca3c134b8c290bc94eb849Timo Sirainenmailbox_list_notify_inbox_get_events(struct mailbox_list_notify_index *inotify)
838a76b0f4e65e98eeca3c134b8c290bc94eb849Timo Sirainen mailbox_get_open_status(inotify->inbox, notify_status_items, &old_status);
838a76b0f4e65e98eeca3c134b8c290bc94eb849Timo Sirainen if (mailbox_sync(inotify->inbox, MAILBOX_SYNC_FLAG_FAST) < 0) {
838a76b0f4e65e98eeca3c134b8c290bc94eb849Timo Sirainen i_error("Mailbox list index notify: Failed to sync INBOX: %s",
838a76b0f4e65e98eeca3c134b8c290bc94eb849Timo Sirainen mailbox_get_last_internal_error(inotify->inbox, NULL));
838a76b0f4e65e98eeca3c134b8c290bc94eb849Timo Sirainen mailbox_get_open_status(inotify->inbox, notify_status_items, &new_status);
838a76b0f4e65e98eeca3c134b8c290bc94eb849Timo Sirainen mailbox_notify_node_update_status(&old_nnode, &old_status);
838a76b0f4e65e98eeca3c134b8c290bc94eb849Timo Sirainen return mailbox_list_index_get_changed_events(&old_nnode, &new_status);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainenint mailbox_list_index_notify_next(struct mailbox_list_notify *notify,
22436f3cbb7a2c666519a7448cf2d4d20e48f352Timo Sirainen if (mailbox_list_index_handle_corruption(notify->list) < 0)
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen while (mailbox_list_index_notify_try_next(inotify)) {
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen if ((inotify->notify_rec.events & inotify->notify.mask) != 0) {
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen /* caller doesn't care about this change */
838a76b0f4e65e98eeca3c134b8c290bc94eb849Timo Sirainen mailbox_list_notify_inbox_get_events(inotify);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen mailbox_list_index_notify_read_deinit(inotify);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainenstatic void notify_now_callback(struct mailbox_list_notify_index *inotify)
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen inotify->wait_callback(inotify->wait_context);
182724707b7f73a181716d439863fb756d8ad03dTimo Sirainenstatic void list_notify_callback(struct mailbox_list_notify_index *inotify)
9dd7c6f7fc78a26a5d27457ed9415de1f924848bTimo Sirainen struct stat list_prev_st = inotify->list_last_st;
182724707b7f73a181716d439863fb756d8ad03dTimo Sirainen /* there's a pending notification already -
182724707b7f73a181716d439863fb756d8ad03dTimo Sirainen no need to stat() again */
182724707b7f73a181716d439863fb756d8ad03dTimo Sirainen if (ST_CHANGED(inotify->list_last_st, list_prev_st)) {
182724707b7f73a181716d439863fb756d8ad03dTimo Sirainen /* log has changed. call the callback with a small delay
182724707b7f73a181716d439863fb756d8ad03dTimo Sirainen to allow bundling multiple changes together */
182724707b7f73a181716d439863fb756d8ad03dTimo Sirainenstatic void inbox_notify_callback(struct mailbox_list_notify_index *inotify)
9dd7c6f7fc78a26a5d27457ed9415de1f924848bTimo Sirainen struct stat inbox_prev_st = inotify->inbox_last_st;
182724707b7f73a181716d439863fb756d8ad03dTimo Sirainen if (inotify->to_notify != NULL && inotify->inbox_event_pending) {
182724707b7f73a181716d439863fb756d8ad03dTimo Sirainen /* there's a pending INBOX notification already -
182724707b7f73a181716d439863fb756d8ad03dTimo Sirainen no need to stat() again */
3aff91a1941ea35265f1e80e70853693e8ec8e0bAki Tuomi if (ST_CHANGED(inotify->inbox_last_st, inbox_prev_st))
182724707b7f73a181716d439863fb756d8ad03dTimo Sirainen if (inotify->inbox_event_pending && inotify->to_notify == NULL) {
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen /* log has changed. call the callback with a small delay
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen to allow bundling multiple changes together */
182724707b7f73a181716d439863fb756d8ad03dTimo Sirainenstatic void full_notify_callback(struct mailbox_list_notify_index *inotify)
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainenvoid mailbox_list_index_notify_wait(struct mailbox_list_notify *notify,
182724707b7f73a181716d439863fb756d8ad03dTimo Sirainen (void)io_add_notify(inotify->list_log_path, list_notify_callback,
9dd7c6f7fc78a26a5d27457ed9415de1f924848bTimo Sirainen /* we need to check for INBOX explicitly, because INBOX changes
9dd7c6f7fc78a26a5d27457ed9415de1f924848bTimo Sirainen don't get added to mailbox.list.index.log */
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen /* check with timeout as well, in case io_add_notify()
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen doesn't work (e.g. NFS) */
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen check_interval = notify->list->mail_set->mailbox_idle_check_interval;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen inotify->to_wait = timeout_add(check_interval * 1000,
58a89627905e3590381cdd5eb931b9537c4b4ea6Timo Sirainenvoid mailbox_list_index_notify_flush(struct mailbox_list_notify *notify)
5ddc694e19875c8e3ad7db77807d6ae4360acdcaTimo Sirainen notify->list->mail_set->mailbox_idle_check_interval > 0) {
5ddc694e19875c8e3ad7db77807d6ae4360acdcaTimo Sirainen /* no pending notification - check if anything had changed */