bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen#include "lib.h"
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen#include "ioloop.h"
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen#include "str.h"
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen#include "mail-index-private.h"
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen#include "mail-transaction-log-private.h"
9dd7c6f7fc78a26a5d27457ed9415de1f924848bTimo Sirainen#include "mail-storage-private.h"
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen#include "mailbox-list-notify.h"
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen#include "mailbox-list-notify-tree.h"
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen#include "mailbox-list-index.h"
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen#include <sys/stat.h>
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen#define NOTIFY_DELAY_MSECS 500
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainenenum ilist_ext_type {
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen ILIST_EXT_NONE,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen ILIST_EXT_BASE,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen ILIST_EXT_MSGS,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen ILIST_EXT_HIGHESTMODSEQ,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen ILIST_EXT_UNKNOWN
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen};
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainenstruct mailbox_list_notify_rename {
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen uint32_t old_uid, new_uid;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen};
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainenstruct mailbox_list_inotify_entry {
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen uint32_t uid;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen guid_128_t guid;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen bool expunge;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen};
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainenstruct mailbox_list_notify_index {
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen struct mailbox_list_notify notify;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen struct mailbox_tree_context *subscriptions;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen struct mailbox_list_notify_tree *tree;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen struct mail_index_view *view, *old_view;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen struct mail_index_view_sync_ctx *sync_ctx;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen enum ilist_ext_type cur_ext;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen uint32_t cur_ext_id;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen void (*wait_callback)(void *context);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen void *wait_context;
9dd7c6f7fc78a26a5d27457ed9415de1f924848bTimo Sirainen struct io *io_wait, *io_wait_inbox;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen struct timeout *to_wait, *to_notify;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
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 struct seq_range_iter changed_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;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen struct mailbox_list_notify_rec notify_rec;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen string_t *rec_name;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
9dd7c6f7fc78a26a5d27457ed9415de1f924848bTimo Sirainen char *list_log_path, *inbox_log_path;
9dd7c6f7fc78a26a5d27457ed9415de1f924848bTimo Sirainen struct stat list_last_st, inbox_last_st;
838a76b0f4e65e98eeca3c134b8c290bc94eb849Timo Sirainen struct mailbox *inbox;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool initialized:1;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool read_failed:1;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool inbox_event_pending:1;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen};
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
838a76b0f4e65e98eeca3c134b8c290bc94eb849Timo Sirainenstatic const enum mailbox_status_items notify_status_items =
838a76b0f4e65e98eeca3c134b8c290bc94eb849Timo Sirainen STATUS_UIDVALIDITY | STATUS_UIDNEXT | STATUS_MESSAGES |
838a76b0f4e65e98eeca3c134b8c290bc94eb849Timo Sirainen STATUS_UNSEEN | STATUS_HIGHESTMODSEQ;
838a76b0f4e65e98eeca3c134b8c290bc94eb849Timo Sirainen
5b898189915be7054d53d57029fe77af7856cb0cTimo Sirainenstatic enum mailbox_list_notify_event
5b898189915be7054d53d57029fe77af7856cb0cTimo Sirainenmailbox_list_index_get_changed_events(const struct mailbox_notify_node *nnode,
5b898189915be7054d53d57029fe77af7856cb0cTimo Sirainen const struct mailbox_status *status)
5b898189915be7054d53d57029fe77af7856cb0cTimo Sirainen{
5b898189915be7054d53d57029fe77af7856cb0cTimo Sirainen enum mailbox_list_notify_event events = 0;
5b898189915be7054d53d57029fe77af7856cb0cTimo Sirainen
5b898189915be7054d53d57029fe77af7856cb0cTimo Sirainen if (nnode->uidvalidity != status->uidvalidity)
5b898189915be7054d53d57029fe77af7856cb0cTimo Sirainen events |= MAILBOX_LIST_NOTIFY_UIDVALIDITY;
5b898189915be7054d53d57029fe77af7856cb0cTimo Sirainen if (nnode->uidnext != status->uidnext)
5b898189915be7054d53d57029fe77af7856cb0cTimo Sirainen events |= MAILBOX_LIST_NOTIFY_APPENDS;
5b898189915be7054d53d57029fe77af7856cb0cTimo Sirainen if (nnode->messages > status->messages) {
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 events |= MAILBOX_LIST_NOTIFY_EXPUNGES;
5b898189915be7054d53d57029fe77af7856cb0cTimo Sirainen }
5b898189915be7054d53d57029fe77af7856cb0cTimo Sirainen if (nnode->unseen != status->unseen)
5b898189915be7054d53d57029fe77af7856cb0cTimo Sirainen events |= MAILBOX_LIST_NOTIFY_SEEN_CHANGES;
5b898189915be7054d53d57029fe77af7856cb0cTimo Sirainen if (nnode->highest_modseq < status->highest_modseq)
5b898189915be7054d53d57029fe77af7856cb0cTimo Sirainen events |= MAILBOX_LIST_NOTIFY_MODSEQ_CHANGES;
5b898189915be7054d53d57029fe77af7856cb0cTimo Sirainen return events;
5b898189915be7054d53d57029fe77af7856cb0cTimo Sirainen}
5b898189915be7054d53d57029fe77af7856cb0cTimo Sirainen
5b898189915be7054d53d57029fe77af7856cb0cTimo Sirainenstatic void
5b898189915be7054d53d57029fe77af7856cb0cTimo Sirainenmailbox_notify_node_update_status(struct mailbox_notify_node *nnode,
5b898189915be7054d53d57029fe77af7856cb0cTimo Sirainen struct mailbox_status *status)
5b898189915be7054d53d57029fe77af7856cb0cTimo Sirainen{
5b898189915be7054d53d57029fe77af7856cb0cTimo Sirainen nnode->uidvalidity = status->uidvalidity;
5b898189915be7054d53d57029fe77af7856cb0cTimo Sirainen nnode->uidnext = status->uidnext;
5b898189915be7054d53d57029fe77af7856cb0cTimo Sirainen nnode->messages = status->messages;
5b898189915be7054d53d57029fe77af7856cb0cTimo Sirainen nnode->unseen = status->unseen;
5b898189915be7054d53d57029fe77af7856cb0cTimo Sirainen nnode->highest_modseq = status->highest_modseq;
5b898189915be7054d53d57029fe77af7856cb0cTimo Sirainen}
5b898189915be7054d53d57029fe77af7856cb0cTimo Sirainen
838a76b0f4e65e98eeca3c134b8c290bc94eb849Timo Sirainenstatic void
838a76b0f4e65e98eeca3c134b8c290bc94eb849Timo Sirainenmailbox_list_index_notify_init_inbox(struct mailbox_list_notify_index *inotify)
838a76b0f4e65e98eeca3c134b8c290bc94eb849Timo Sirainen{
838a76b0f4e65e98eeca3c134b8c290bc94eb849Timo Sirainen inotify->inbox = mailbox_alloc(inotify->notify.list, "INBOX",
838a76b0f4e65e98eeca3c134b8c290bc94eb849Timo Sirainen MAILBOX_FLAG_READONLY);
838a76b0f4e65e98eeca3c134b8c290bc94eb849Timo Sirainen if (mailbox_open(inotify->inbox) < 0)
838a76b0f4e65e98eeca3c134b8c290bc94eb849Timo Sirainen mailbox_free(&inotify->inbox);
6c17d1adef038b674a9e6f48c6a12aee12ba324bMartti Rannanjärvi else
6c17d1adef038b674a9e6f48c6a12aee12ba324bMartti Rannanjärvi inotify->inbox_log_path =
6c17d1adef038b674a9e6f48c6a12aee12ba324bMartti Rannanjärvi i_strconcat(inotify->inbox->index->filepath,
6c17d1adef038b674a9e6f48c6a12aee12ba324bMartti Rannanjärvi ".log", NULL);
838a76b0f4e65e98eeca3c134b8c290bc94eb849Timo Sirainen}
838a76b0f4e65e98eeca3c134b8c290bc94eb849Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainenint mailbox_list_index_notify_init(struct mailbox_list *list,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen enum mailbox_list_notify_event mask,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen struct mailbox_list_notify **notify_r)
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen{
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen struct mailbox_list_index *ilist = INDEX_LIST_CONTEXT(list);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen struct mailbox_list_notify_index *inotify;
9dd7c6f7fc78a26a5d27457ed9415de1f924848bTimo Sirainen const char *index_dir;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen if (ilist == NULL) {
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen /* can't do this without mailbox list indexes */
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen return -1;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen }
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen (void)mailbox_list_index_refresh(list);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen inotify = i_new(struct mailbox_list_notify_index, 1);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen inotify->notify.list = list;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen inotify->notify.mask = mask;
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);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen i_array_init(&inotify->new_uids, 8);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen i_array_init(&inotify->expunged_uids, 8);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen i_array_init(&inotify->changed_uids, 16);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen i_array_init(&inotify->renames, 16);
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 if ((mask & (MAILBOX_LIST_NOTIFY_SUBSCRIBE |
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen MAILBOX_LIST_NOTIFY_UNSUBSCRIBE)) != 0) {
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen (void)mailbox_list_iter_subscriptions_refresh(list);
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen mailbox_tree_sort(list->subscriptions);
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen inotify->subscriptions = mailbox_tree_dup(list->subscriptions);
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen }
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 &index_dir) <= 0) {
91cec71840dda9bd4c26b8e88e6af18262d6b36aTimo Sirainen /* no indexes for INBOX? can't handle it */
91cec71840dda9bd4c26b8e88e6af18262d6b36aTimo Sirainen } else {
838a76b0f4e65e98eeca3c134b8c290bc94eb849Timo Sirainen mailbox_list_index_notify_init_inbox(inotify);
9dd7c6f7fc78a26a5d27457ed9415de1f924848bTimo Sirainen }
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen *notify_r = &inotify->notify;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen return 1;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen}
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainenvoid mailbox_list_index_notify_deinit(struct mailbox_list_notify *notify)
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen{
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen struct mailbox_list_notify_index *inotify =
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen (struct mailbox_list_notify_index *)notify;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen bool b;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
838a76b0f4e65e98eeca3c134b8c290bc94eb849Timo Sirainen if (inotify->inbox != NULL)
838a76b0f4e65e98eeca3c134b8c290bc94eb849Timo Sirainen mailbox_free(&inotify->inbox);
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen if (inotify->subscriptions != NULL)
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen mailbox_tree_deinit(&inotify->subscriptions);
5f1d689131a75c39f064cbd4202373e7edf78f18Josef 'Jeff' Sipek io_remove(&inotify->io_wait);
5f1d689131a75c39f064cbd4202373e7edf78f18Josef 'Jeff' Sipek io_remove(&inotify->io_wait_inbox);
0d1b8b6bec79746c5d89d57dd8c1688946bd9237Josef 'Jeff' Sipek timeout_remove(&inotify->to_wait);
0d1b8b6bec79746c5d89d57dd8c1688946bd9237Josef 'Jeff' Sipek timeout_remove(&inotify->to_notify);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen if (inotify->sync_ctx != NULL)
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen (void)mail_index_view_sync_commit(&inotify->sync_ctx, &b);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen mail_index_view_close(&inotify->view);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen mail_index_view_close(&inotify->old_view);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen mailbox_list_notify_tree_deinit(&inotify->tree);
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen array_free(&inotify->new_subscriptions);
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen array_free(&inotify->new_unsubscriptions);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen array_free(&inotify->new_uids);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen array_free(&inotify->expunged_uids);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen array_free(&inotify->changed_uids);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen array_free(&inotify->renames);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen str_free(&inotify->rec_name);
9dd7c6f7fc78a26a5d27457ed9415de1f924848bTimo Sirainen i_free(inotify->list_log_path);
9dd7c6f7fc78a26a5d27457ed9415de1f924848bTimo Sirainen i_free(inotify->inbox_log_path);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen i_free(inotify);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen}
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainenstatic struct mailbox_list_index_node *
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainennotify_lookup_guid(struct mailbox_list_notify_index *inotify,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen struct mail_index_view *view,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen uint32_t uid, enum mailbox_status_items items,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen struct mailbox_status *status_r, guid_128_t guid_r)
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen{
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen struct mailbox_list_index *ilist =
43ce61b1d755832186f12b9739d18212b4744d14Aki Tuomi INDEX_LIST_CONTEXT_REQUIRE(inotify->notify.list);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen struct mailbox_list_index_node *index_node;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen uint32_t seq;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen if (!mail_index_lookup_seq(view, uid, &seq))
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen return NULL;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen index_node = mailbox_list_index_lookup_uid(ilist, uid);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen if (index_node == NULL) {
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,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen view, FALSE);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen index_node = mailbox_list_index_lookup_uid(ilist, uid);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen if (index_node == NULL)
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen return NULL;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen }
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen /* get GUID */
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(status_r);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen memset(guid_r, 0, GUID_128_SIZE);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen (void)mailbox_list_index_status(inotify->notify.list, view, seq,
e048e63fec8d21d4af0fd9d27dd3fe5dcedf18e6Timo Sirainen items, status_r, guid_r, NULL);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen return index_node;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen}
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
182724707b7f73a181716d439863fb756d8ad03dTimo Sirainenstatic void notify_update_stat(struct mailbox_list_notify_index *inotify,
182724707b7f73a181716d439863fb756d8ad03dTimo Sirainen bool stat_list, bool stat_inbox)
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen{
9dd7c6f7fc78a26a5d27457ed9415de1f924848bTimo Sirainen bool call = FALSE;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
182724707b7f73a181716d439863fb756d8ad03dTimo Sirainen if (stat_list &&
182724707b7f73a181716d439863fb756d8ad03dTimo Sirainen stat(inotify->list_log_path, &inotify->list_last_st) < 0 &&
9dd7c6f7fc78a26a5d27457ed9415de1f924848bTimo Sirainen errno != ENOENT) {
9dd7c6f7fc78a26a5d27457ed9415de1f924848bTimo Sirainen i_error("stat(%s) failed: %m", inotify->list_log_path);
9dd7c6f7fc78a26a5d27457ed9415de1f924848bTimo Sirainen call = TRUE;
9dd7c6f7fc78a26a5d27457ed9415de1f924848bTimo Sirainen }
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 errno != ENOENT) {
9dd7c6f7fc78a26a5d27457ed9415de1f924848bTimo Sirainen i_error("stat(%s) failed: %m", inotify->inbox_log_path);
9dd7c6f7fc78a26a5d27457ed9415de1f924848bTimo Sirainen call = TRUE;
9dd7c6f7fc78a26a5d27457ed9415de1f924848bTimo Sirainen }
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen }
9dd7c6f7fc78a26a5d27457ed9415de1f924848bTimo Sirainen if (call)
9dd7c6f7fc78a26a5d27457ed9415de1f924848bTimo Sirainen mailbox_list_index_notify_wait(&inotify->notify, NULL, NULL);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen}
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainenstatic void
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainenmailbox_list_index_notify_sync_init(struct mailbox_list_notify_index *inotify)
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen{
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen struct mail_index_view_sync_rec sync_rec;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
182724707b7f73a181716d439863fb756d8ad03dTimo Sirainen notify_update_stat(inotify, TRUE, TRUE);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen (void)mail_index_refresh(inotify->view->index);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
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 Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen inotify->cur_ext = ILIST_EXT_NONE;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen inotify->cur_ext_id = (uint32_t)-1;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen}
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainenstatic bool notify_ext_rec(struct mailbox_list_notify_index *inotify,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen uint32_t uid)
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen{
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen struct mailbox_list_notify *notify = &inotify->notify;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen switch (inotify->cur_ext) {
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen case ILIST_EXT_NONE:
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen i_unreached();
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen case ILIST_EXT_BASE:
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen /* UIDVALIDITY changed */
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen if ((notify->mask & MAILBOX_LIST_NOTIFY_UIDVALIDITY) == 0)
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen return FALSE;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen break;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen case ILIST_EXT_MSGS:
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen /* APPEND, EXPUNGE, \Seen or \Recent flag change */
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen if ((notify->mask & MAILBOX_LIST_NOTIFY_STATUS) == 0)
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen return FALSE;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen break;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen case ILIST_EXT_HIGHESTMODSEQ:
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 return FALSE;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen break;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen case ILIST_EXT_UNKNOWN:
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen return FALSE;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen }
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen seq_range_array_add(&inotify->changed_uids, uid);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen return TRUE;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen}
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainenstatic int
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainenmailbox_list_index_notify_read_next(struct mailbox_list_notify_index *inotify)
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen{
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen struct mailbox_list_notify *notify = &inotify->notify;
43ce61b1d755832186f12b9739d18212b4744d14Aki Tuomi struct mailbox_list_index *ilist = INDEX_LIST_CONTEXT_REQUIRE(notify->list);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen const struct mail_transaction_header *hdr;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen const void *data;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen int ret;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen ret = mail_transaction_log_view_next(inotify->view->log_view,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen &hdr, &data);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen if (ret <= 0)
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen return ret;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen if ((hdr->type & MAIL_TRANSACTION_EXTERNAL) == 0) {
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen /* all mailbox index updates are external */
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen return 1;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen }
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen switch (hdr->type & MAIL_TRANSACTION_TYPE_MASK) {
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen case MAIL_TRANSACTION_APPEND: {
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen /* mailbox added or renamed */
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen const struct mail_index_record *rec, *end;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen if ((notify->mask & (MAILBOX_LIST_NOTIFY_CREATE |
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen MAILBOX_LIST_NOTIFY_RENAME)) == 0)
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen break;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen end = CONST_PTR_OFFSET(data, hdr->size);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen for (rec = data; rec != end; rec++)
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen seq_range_array_add(&inotify->new_uids, rec->uid);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen break;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen }
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen case MAIL_TRANSACTION_EXPUNGE_GUID: {
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen /* mailbox deleted or renamed */
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen const struct mail_transaction_expunge_guid *rec, *end;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen if ((notify->mask & (MAILBOX_LIST_NOTIFY_DELETE |
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen MAILBOX_LIST_NOTIFY_RENAME)) == 0)
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen break;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen end = CONST_PTR_OFFSET(data, hdr->size);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen for (rec = data; rec != end; rec++)
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen seq_range_array_add(&inotify->expunged_uids, rec->uid);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen break;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen }
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen case MAIL_TRANSACTION_EXT_INTRO: {
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen struct mail_index_map *map = inotify->view->map;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen const struct mail_transaction_ext_intro *rec = data;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen const struct mail_index_ext *ext = NULL;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen const char *name;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen uint32_t ext_map_idx;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen if (!array_is_created(&map->extensions))
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen break;
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 if (rec->ext_id != (uint32_t)-1 &&
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 } else if (rec->name_size > 0) {
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen /* by name */
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen name = t_strndup(rec+1, rec->name_size);
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 }
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen if (ext != NULL) {
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen if (ext->index_idx == ilist->ext_id)
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen inotify->cur_ext = ILIST_EXT_BASE;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen else if (ext->index_idx == ilist->msgs_ext_id)
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen inotify->cur_ext = ILIST_EXT_MSGS;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen else if (ext->index_idx == ilist->hmodseq_ext_id)
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen inotify->cur_ext = ILIST_EXT_HIGHESTMODSEQ;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen else
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen inotify->cur_ext = ILIST_EXT_UNKNOWN;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen inotify->cur_ext_id = ext->index_idx;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen }
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen break;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen }
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen case MAIL_TRANSACTION_EXT_REC_UPDATE: {
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen const struct mail_index_registered_ext *ext;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen const struct mail_transaction_ext_rec_update *rec;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen unsigned int i, record_size;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen if (inotify->cur_ext == ILIST_EXT_NONE) {
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen i_error("%s: Missing ext-intro for ext-rec-update",
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen ilist->index->filepath);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen break;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen }
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen /* the record is padded to 32bits in the transaction log */
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen ext = array_idx(&inotify->view->index->extensions,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen inotify->cur_ext_id);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen record_size = (sizeof(*rec) + ext->record_size + 3) & ~3;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen for (i = 0; i < hdr->size; i += record_size) {
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen rec = CONST_PTR_OFFSET(data, i);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen if (i + record_size > hdr->size)
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen break;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen if (!notify_ext_rec(inotify, rec->uid))
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen break;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen }
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen break;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen }
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen }
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen return 1;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen}
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainenstatic int
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainenmailbox_list_inotify_entry_guid_cmp(const struct mailbox_list_inotify_entry *r1,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen const struct mailbox_list_inotify_entry *r2)
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen{
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen int ret;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen ret = memcmp(r1->guid, r2->guid, sizeof(r1->guid));
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen if (ret != 0)
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen return ret;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen if (r1->expunge == r2->expunge) {
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen /* this really shouldn't happen */
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen return 0;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen }
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen return r1->expunge ? -1 : 1;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen}
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainenstatic void
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainenmailbox_list_index_notify_find_renames(struct mailbox_list_notify_index *inotify)
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen{
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainen ARRAY(struct mailbox_list_inotify_entry) entries;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen struct mailbox_status status;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen struct mailbox_list_notify_rename *rename;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen struct mailbox_list_inotify_entry *entry;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen const struct mailbox_list_inotify_entry *e;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen unsigned int i, count;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen guid_128_t guid;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen uint32_t uid;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen /* first get all of the added and expunged GUIDs */
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen t_array_init(&entries, array_count(&inotify->new_uids) +
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen array_count(&inotify->expunged_uids));
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen while (seq_range_array_iter_nth(&inotify->expunged_uids_iter,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen inotify->expunged_uids_n++, &uid)) {
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen if (notify_lookup_guid(inotify, inotify->old_view, uid,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen 0, &status, guid) != NULL &&
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen !guid_128_is_empty(guid)) {
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen entry = array_append_space(&entries);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen entry->uid = uid;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen entry->expunge = TRUE;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen memcpy(entry->guid, guid, sizeof(entry->guid));
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen }
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen }
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen (void)mailbox_list_index_parse(inotify->notify.list,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen inotify->view, TRUE);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen while (seq_range_array_iter_nth(&inotify->new_uids_iter,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen inotify->new_uids_n++, &uid)) {
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen if (notify_lookup_guid(inotify, inotify->view, uid,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen 0, &status, guid) != NULL &&
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen !guid_128_is_empty(guid)) {
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen entry = array_append_space(&entries);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen entry->uid = uid;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen memcpy(entry->guid, guid, sizeof(entry->guid));
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen }
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen }
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
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
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen e = array_get(&entries, &count);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen for (i = 1; i < count; i++) {
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen if (e[i-1].expunge && !e[i].expunge &&
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 rename->old_uid = e[i-1].uid;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen rename->new_uid = e[i].uid;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen seq_range_array_remove(&inotify->expunged_uids,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen rename->old_uid);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen seq_range_array_remove(&inotify->new_uids,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen rename->new_uid);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen }
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen }
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen}
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainenstatic void
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainenmailbox_list_index_notify_find_subscribes(struct mailbox_list_notify_index *inotify)
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen{
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 pool_t pool;
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen int ret;
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen if (mailbox_list_iter_subscriptions_refresh(inotify->notify.list) < 0)
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen return;
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen mailbox_tree_sort(inotify->notify.list->subscriptions);
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen old_tree = inotify->subscriptions;
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen new_tree = mailbox_tree_dup(inotify->notify.list->subscriptions);
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen
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
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen pool = mailbox_tree_get_pool(new_tree);
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen for (;;) {
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen if (old_path == NULL) {
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen if (mailbox_tree_iterate_next(old_iter, &old_path) == NULL)
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen old_path = NULL;
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen }
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen if (new_path == NULL) {
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen if (mailbox_tree_iterate_next(new_iter, &new_path) == NULL)
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen new_path = NULL;
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen }
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen if (old_path == NULL) {
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen if (new_path == NULL)
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen break;
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen ret = 1;
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen } else if (new_path == NULL)
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen ret = -1;
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen else {
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen ret = strcmp(old_path, new_path);
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen }
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen if (ret == 0) {
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen old_path = NULL;
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen new_path = NULL;
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen } else if (ret > 0) {
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen new_path = p_strdup(pool, new_path);
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen array_append(&inotify->new_subscriptions, &new_path, 1);
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen new_path = NULL;
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen } else {
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen old_path = p_strdup(pool, old_path);
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen array_append(&inotify->new_unsubscriptions, &old_path, 1);
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen old_path = NULL;
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen }
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen }
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen mailbox_tree_iterate_deinit(&old_iter);
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen mailbox_tree_iterate_deinit(&new_iter);
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen mailbox_tree_deinit(&inotify->subscriptions);
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen inotify->subscriptions = new_tree;
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen}
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainenstatic void
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainenmailbox_list_index_notify_reset_iters(struct mailbox_list_notify_index *inotify)
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen{
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen seq_range_array_iter_init(&inotify->new_uids_iter,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen &inotify->new_uids);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen seq_range_array_iter_init(&inotify->expunged_uids_iter,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen &inotify->expunged_uids);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen seq_range_array_iter_init(&inotify->changed_uids_iter,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen &inotify->changed_uids);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen inotify->changed_uids_n = 0;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen inotify->new_uids_n = 0;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen inotify->expunged_uids_n = 0;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen inotify->rename_idx = 0;
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen inotify->subscription_idx = 0;
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen inotify->unsubscription_idx = 0;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen}
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainenstatic void
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainenmailbox_list_index_notify_read_init(struct mailbox_list_notify_index *inotify)
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen{
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen bool b;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen int ret;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen mailbox_list_index_notify_sync_init(inotify);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen /* read all changes from .log file */
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen while ((ret = mailbox_list_index_notify_read_next(inotify)) > 0) ;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen inotify->read_failed = ret < 0;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen (void)mail_index_view_sync_commit(&inotify->sync_ctx, &b);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen /* remove changes for already deleted mailboxes */
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen seq_range_array_remove_seq_range(&inotify->new_uids,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen &inotify->expunged_uids);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen seq_range_array_remove_seq_range(&inotify->changed_uids,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen &inotify->expunged_uids);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen mailbox_list_index_notify_reset_iters(inotify);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen if (array_count(&inotify->new_uids) > 0 &&
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen array_count(&inotify->expunged_uids) > 0) {
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen mailbox_list_index_notify_find_renames(inotify);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen mailbox_list_index_notify_reset_iters(inotify);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen }
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen if (inotify->subscriptions != NULL)
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen mailbox_list_index_notify_find_subscribes(inotify);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen inotify->initialized = TRUE;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen}
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainenstatic void
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainenmailbox_list_index_notify_read_deinit(struct mailbox_list_notify_index *inotify)
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen{
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen /* save the old view so we can look up expunged records */
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen mail_index_view_close(&inotify->old_view);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen inotify->old_view = mail_index_view_dup_private(inotify->view);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen array_clear(&inotify->new_subscriptions);
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen array_clear(&inotify->new_unsubscriptions);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen array_clear(&inotify->new_uids);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen array_clear(&inotify->expunged_uids);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen array_clear(&inotify->changed_uids);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen array_clear(&inotify->renames);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen inotify->initialized = FALSE;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen}
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainenstatic bool
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainenmailbox_list_index_notify_lookup(struct mailbox_list_notify_index *inotify,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen struct mail_index_view *view,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen uint32_t uid, enum mailbox_status_items items,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen struct mailbox_status *status_r,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen struct mailbox_list_notify_rec **rec_r)
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen{
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen struct mailbox_list_notify_rec *rec = &inotify->notify_rec;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen struct mailbox_list_index_node *index_node;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen const char *storage_name;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen char ns_sep = mailbox_list_get_hierarchy_sep(inotify->notify.list);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(rec);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen index_node = notify_lookup_guid(inotify, view, uid,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen items, status_r, rec->guid);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen if (index_node == NULL)
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen return FALSE;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen /* get storage_name */
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen str_truncate(inotify->rec_name, 0);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen mailbox_list_index_node_get_path(index_node, ns_sep, inotify->rec_name);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen storage_name = str_c(inotify->rec_name);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen rec->storage_name = storage_name;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen rec->vname = mailbox_list_get_vname(inotify->notify.list,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen rec->storage_name);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen *rec_r = rec;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen return TRUE;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen}
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainenstatic bool
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainenmailbox_list_index_notify_rename(struct mailbox_list_notify_index *inotify,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen unsigned int idx)
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen{
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen const struct mailbox_list_notify_rename *rename;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen struct mailbox_list_notify_rec *rec;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen struct mailbox_status status;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen const char *old_vname;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen rename = array_idx(&inotify->renames, idx);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen /* lookup the old name */
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen if (!mailbox_list_index_notify_lookup(inotify, inotify->old_view,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen rename->old_uid, 0, &status, &rec))
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen return FALSE;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen old_vname = t_strdup(rec->vname);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen /* return using the new name */
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen if (!mailbox_list_index_notify_lookup(inotify, inotify->view,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen rename->new_uid, 0, &status, &rec))
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen return FALSE;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen rec->old_vname = old_vname;
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen rec->events = MAILBOX_LIST_NOTIFY_RENAME;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen return TRUE;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen}
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainenstatic bool
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainenmailbox_list_index_notify_subscribe(struct mailbox_list_notify_index *inotify,
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen unsigned int idx)
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen{
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen struct mailbox_list_notify_rec *rec = &inotify->notify_rec;
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen const char *const *vnamep;
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(rec);
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen vnamep = array_idx(&inotify->new_subscriptions, idx);
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen rec->vname = *vnamep;
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen rec->storage_name = mailbox_list_get_storage_name(inotify->notify.list,
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen rec->vname);
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen rec->events = MAILBOX_LIST_NOTIFY_SUBSCRIBE;
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen return TRUE;
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen}
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainenstatic bool
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainenmailbox_list_index_notify_unsubscribe(struct mailbox_list_notify_index *inotify,
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen unsigned int idx)
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen{
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen struct mailbox_list_notify_rec *rec = &inotify->notify_rec;
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen const char *const *vnamep;
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(rec);
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen vnamep = array_idx(&inotify->new_unsubscriptions, idx);
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen rec->vname = *vnamep;
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen rec->storage_name = mailbox_list_get_storage_name(inotify->notify.list,
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen rec->vname);
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen rec->events = MAILBOX_LIST_NOTIFY_UNSUBSCRIBE;
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen return TRUE;
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen}
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainenstatic bool
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainenmailbox_list_index_notify_expunge(struct mailbox_list_notify_index *inotify,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen uint32_t uid)
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen{
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen struct mailbox_list_notify_rec *rec;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen struct mailbox_status status;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen if (!mailbox_list_index_notify_lookup(inotify, inotify->old_view,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen uid, 0, &status, &rec))
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen return FALSE;
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen rec->events = MAILBOX_LIST_NOTIFY_DELETE;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen return TRUE;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen}
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainenstatic bool
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainenmailbox_list_index_notify_new(struct mailbox_list_notify_index *inotify,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen uint32_t uid)
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen{
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen struct mailbox_list_notify_rec *rec;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen struct mailbox_status status;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen if (!mailbox_list_index_notify_lookup(inotify, inotify->view,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen uid, 0, &status, &rec))
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen i_unreached();
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen rec->events = MAILBOX_LIST_NOTIFY_CREATE;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen return TRUE;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen}
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainenstatic bool
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainenmailbox_list_index_notify_change(struct mailbox_list_notify_index *inotify,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen uint32_t uid)
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen{
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen struct mailbox_list_notify_rec *rec;
ec937f21abdd9500a450a8c16091337672e54488Timo Sirainen struct mailbox_notify_node *nnode, empty_node;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen struct mailbox_status status;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen if (!mailbox_list_index_notify_lookup(inotify, inotify->view,
838a76b0f4e65e98eeca3c134b8c290bc94eb849Timo Sirainen uid, notify_status_items,
2912eac52610bf9463e48f320a966d0b0c51bed0Timo Sirainen &status, &rec)) {
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). */
2912eac52610bf9463e48f320a966d0b0c51bed0Timo Sirainen return FALSE;
2912eac52610bf9463e48f320a966d0b0c51bed0Timo Sirainen }
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen /* get the old status */
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen nnode = mailbox_list_notify_tree_lookup(inotify->tree,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen rec->storage_name);
ec937f21abdd9500a450a8c16091337672e54488Timo Sirainen if (nnode == NULL) {
ec937f21abdd9500a450a8c16091337672e54488Timo Sirainen /* mailbox didn't exist earlier - report all events as new */
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&empty_node);
ec937f21abdd9500a450a8c16091337672e54488Timo Sirainen nnode = &empty_node;
ec937f21abdd9500a450a8c16091337672e54488Timo Sirainen }
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);
3ee009bb150bd1db1c5064c3285afc7573fb4572Timo Sirainen return rec->events != 0;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen}
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainenstatic bool
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainenmailbox_list_index_notify_try_next(struct mailbox_list_notify_index *inotify)
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen{
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen uint32_t uid;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen /* first show mailbox deletes */
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen if (seq_range_array_iter_nth(&inotify->expunged_uids_iter,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen inotify->expunged_uids_n++, &uid))
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen return mailbox_list_index_notify_expunge(inotify, uid);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
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 inotify->rename_idx++);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen }
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen /* next mailbox creates */
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen if (seq_range_array_iter_nth(&inotify->new_uids_iter,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen inotify->new_uids_n++, &uid))
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen return mailbox_list_index_notify_new(inotify, uid);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
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 inotify->subscription_idx++);
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen }
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen if (inotify->unsubscription_idx < array_count(&inotify->new_unsubscriptions)) {
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen return mailbox_list_index_notify_unsubscribe(inotify,
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen inotify->unsubscription_idx++);
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen }
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen /* STATUS updates */
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen while (seq_range_array_iter_nth(&inotify->changed_uids_iter,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen inotify->changed_uids_n++, &uid)) {
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen if (mailbox_list_index_notify_change(inotify, uid))
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen return TRUE;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen }
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen return FALSE;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen}
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
838a76b0f4e65e98eeca3c134b8c290bc94eb849Timo Sirainenstatic enum mailbox_list_notify_event
838a76b0f4e65e98eeca3c134b8c290bc94eb849Timo Sirainenmailbox_list_notify_inbox_get_events(struct mailbox_list_notify_index *inotify)
838a76b0f4e65e98eeca3c134b8c290bc94eb849Timo Sirainen{
838a76b0f4e65e98eeca3c134b8c290bc94eb849Timo Sirainen struct mailbox_status old_status, new_status;
838a76b0f4e65e98eeca3c134b8c290bc94eb849Timo Sirainen struct mailbox_notify_node old_nnode;
838a76b0f4e65e98eeca3c134b8c290bc94eb849Timo Sirainen
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 return 0;
838a76b0f4e65e98eeca3c134b8c290bc94eb849Timo Sirainen }
838a76b0f4e65e98eeca3c134b8c290bc94eb849Timo Sirainen mailbox_get_open_status(inotify->inbox, notify_status_items, &new_status);
838a76b0f4e65e98eeca3c134b8c290bc94eb849Timo Sirainen
838a76b0f4e65e98eeca3c134b8c290bc94eb849Timo Sirainen mailbox_notify_node_update_status(&old_nnode, &old_status);
838a76b0f4e65e98eeca3c134b8c290bc94eb849Timo Sirainen return mailbox_list_index_get_changed_events(&old_nnode, &new_status);
838a76b0f4e65e98eeca3c134b8c290bc94eb849Timo Sirainen}
838a76b0f4e65e98eeca3c134b8c290bc94eb849Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainenint mailbox_list_index_notify_next(struct mailbox_list_notify *notify,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen const struct mailbox_list_notify_rec **rec_r)
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen{
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen struct mailbox_list_notify_index *inotify =
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen (struct mailbox_list_notify_index *)notify;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen if (!inotify->initialized)
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen mailbox_list_index_notify_read_init(inotify);
22436f3cbb7a2c666519a7448cf2d4d20e48f352Timo Sirainen if (mailbox_list_index_handle_corruption(notify->list) < 0)
22436f3cbb7a2c666519a7448cf2d4d20e48f352Timo Sirainen return -1;
22436f3cbb7a2c666519a7448cf2d4d20e48f352Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen while (mailbox_list_index_notify_try_next(inotify)) {
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen if ((inotify->notify_rec.events & inotify->notify.mask) != 0) {
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen *rec_r = &inotify->notify_rec;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen return 1;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen } else {
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen /* caller doesn't care about this change */
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen }
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen }
9dd7c6f7fc78a26a5d27457ed9415de1f924848bTimo Sirainen if (inotify->inbox_event_pending) {
9dd7c6f7fc78a26a5d27457ed9415de1f924848bTimo Sirainen inotify->inbox_event_pending = FALSE;
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&inotify->notify_rec);
9dd7c6f7fc78a26a5d27457ed9415de1f924848bTimo Sirainen inotify->notify_rec.vname = "INBOX";
9dd7c6f7fc78a26a5d27457ed9415de1f924848bTimo Sirainen inotify->notify_rec.storage_name = "INBOX";
838a76b0f4e65e98eeca3c134b8c290bc94eb849Timo Sirainen inotify->notify_rec.events =
838a76b0f4e65e98eeca3c134b8c290bc94eb849Timo Sirainen mailbox_list_notify_inbox_get_events(inotify);
9dd7c6f7fc78a26a5d27457ed9415de1f924848bTimo Sirainen *rec_r = &inotify->notify_rec;
9dd7c6f7fc78a26a5d27457ed9415de1f924848bTimo Sirainen return 1;
9dd7c6f7fc78a26a5d27457ed9415de1f924848bTimo Sirainen }
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen mailbox_list_index_notify_read_deinit(inotify);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen return inotify->read_failed ? -1 : 0;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen}
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainenstatic void notify_now_callback(struct mailbox_list_notify_index *inotify)
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen{
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen timeout_remove(&inotify->to_notify);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen inotify->wait_callback(inotify->wait_context);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen}
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
182724707b7f73a181716d439863fb756d8ad03dTimo Sirainenstatic void list_notify_callback(struct mailbox_list_notify_index *inotify)
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen{
9dd7c6f7fc78a26a5d27457ed9415de1f924848bTimo Sirainen struct stat list_prev_st = inotify->list_last_st;
182724707b7f73a181716d439863fb756d8ad03dTimo Sirainen
182724707b7f73a181716d439863fb756d8ad03dTimo Sirainen if (inotify->to_notify != NULL) {
182724707b7f73a181716d439863fb756d8ad03dTimo Sirainen /* there's a pending notification already -
182724707b7f73a181716d439863fb756d8ad03dTimo Sirainen no need to stat() again */
182724707b7f73a181716d439863fb756d8ad03dTimo Sirainen return;
182724707b7f73a181716d439863fb756d8ad03dTimo Sirainen }
182724707b7f73a181716d439863fb756d8ad03dTimo Sirainen
182724707b7f73a181716d439863fb756d8ad03dTimo Sirainen notify_update_stat(inotify, TRUE, FALSE);
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 Sirainen inotify->to_notify =
182724707b7f73a181716d439863fb756d8ad03dTimo Sirainen timeout_add_short(NOTIFY_DELAY_MSECS,
182724707b7f73a181716d439863fb756d8ad03dTimo Sirainen notify_now_callback, inotify);
182724707b7f73a181716d439863fb756d8ad03dTimo Sirainen }
182724707b7f73a181716d439863fb756d8ad03dTimo Sirainen}
182724707b7f73a181716d439863fb756d8ad03dTimo Sirainen
182724707b7f73a181716d439863fb756d8ad03dTimo Sirainenstatic void inbox_notify_callback(struct mailbox_list_notify_index *inotify)
182724707b7f73a181716d439863fb756d8ad03dTimo Sirainen{
9dd7c6f7fc78a26a5d27457ed9415de1f924848bTimo Sirainen struct stat inbox_prev_st = inotify->inbox_last_st;
182724707b7f73a181716d439863fb756d8ad03dTimo Sirainen
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 */
182724707b7f73a181716d439863fb756d8ad03dTimo Sirainen return;
182724707b7f73a181716d439863fb756d8ad03dTimo Sirainen }
182724707b7f73a181716d439863fb756d8ad03dTimo Sirainen
182724707b7f73a181716d439863fb756d8ad03dTimo Sirainen notify_update_stat(inotify, FALSE, TRUE);
3aff91a1941ea35265f1e80e70853693e8ec8e0bAki Tuomi if (ST_CHANGED(inotify->inbox_last_st, inbox_prev_st))
9dd7c6f7fc78a26a5d27457ed9415de1f924848bTimo Sirainen inotify->inbox_event_pending = TRUE;
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 */
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen inotify->to_notify =
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen timeout_add_short(NOTIFY_DELAY_MSECS,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen notify_now_callback, inotify);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen }
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen}
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
182724707b7f73a181716d439863fb756d8ad03dTimo Sirainenstatic void full_notify_callback(struct mailbox_list_notify_index *inotify)
182724707b7f73a181716d439863fb756d8ad03dTimo Sirainen{
182724707b7f73a181716d439863fb756d8ad03dTimo Sirainen list_notify_callback(inotify);
182724707b7f73a181716d439863fb756d8ad03dTimo Sirainen inbox_notify_callback(inotify);
182724707b7f73a181716d439863fb756d8ad03dTimo Sirainen}
182724707b7f73a181716d439863fb756d8ad03dTimo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainenvoid mailbox_list_index_notify_wait(struct mailbox_list_notify *notify,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen void (*callback)(void *context),
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen void *context)
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen{
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen struct mailbox_list_notify_index *inotify =
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen (struct mailbox_list_notify_index *)notify;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen unsigned int check_interval;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen inotify->wait_callback = callback;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen inotify->wait_context = context;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen if (callback == NULL) {
5f1d689131a75c39f064cbd4202373e7edf78f18Josef 'Jeff' Sipek io_remove(&inotify->io_wait);
5f1d689131a75c39f064cbd4202373e7edf78f18Josef 'Jeff' Sipek io_remove(&inotify->io_wait_inbox);
0d1b8b6bec79746c5d89d57dd8c1688946bd9237Josef 'Jeff' Sipek timeout_remove(&inotify->to_wait);
0d1b8b6bec79746c5d89d57dd8c1688946bd9237Josef 'Jeff' Sipek timeout_remove(&inotify->to_notify);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen } else if (inotify->to_wait == NULL) {
182724707b7f73a181716d439863fb756d8ad03dTimo Sirainen (void)io_add_notify(inotify->list_log_path, list_notify_callback,
9dd7c6f7fc78a26a5d27457ed9415de1f924848bTimo Sirainen inotify, &inotify->io_wait);
9dd7c6f7fc78a26a5d27457ed9415de1f924848bTimo Sirainen /* we need to check for INBOX explicitly, because INBOX changes
9dd7c6f7fc78a26a5d27457ed9415de1f924848bTimo Sirainen don't get added to mailbox.list.index.log */
9dd7c6f7fc78a26a5d27457ed9415de1f924848bTimo Sirainen if (inotify->inbox_log_path != NULL) {
9dd7c6f7fc78a26a5d27457ed9415de1f924848bTimo Sirainen (void)io_add_notify(inotify->inbox_log_path,
182724707b7f73a181716d439863fb756d8ad03dTimo Sirainen inbox_notify_callback, inotify,
9dd7c6f7fc78a26a5d27457ed9415de1f924848bTimo Sirainen &inotify->io_wait_inbox);
9dd7c6f7fc78a26a5d27457ed9415de1f924848bTimo Sirainen }
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 i_assert(check_interval > 0);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen inotify->to_wait = timeout_add(check_interval * 1000,
182724707b7f73a181716d439863fb756d8ad03dTimo Sirainen full_notify_callback, inotify);
182724707b7f73a181716d439863fb756d8ad03dTimo Sirainen notify_update_stat(inotify, TRUE, TRUE);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen }
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen}
58a89627905e3590381cdd5eb931b9537c4b4ea6Timo Sirainen
58a89627905e3590381cdd5eb931b9537c4b4ea6Timo Sirainenvoid mailbox_list_index_notify_flush(struct mailbox_list_notify *notify)
58a89627905e3590381cdd5eb931b9537c4b4ea6Timo Sirainen{
58a89627905e3590381cdd5eb931b9537c4b4ea6Timo Sirainen struct mailbox_list_notify_index *inotify =
58a89627905e3590381cdd5eb931b9537c4b4ea6Timo Sirainen (struct mailbox_list_notify_index *)notify;
58a89627905e3590381cdd5eb931b9537c4b4ea6Timo Sirainen
5ddc694e19875c8e3ad7db77807d6ae4360acdcaTimo Sirainen if (inotify->to_notify == NULL &&
5ddc694e19875c8e3ad7db77807d6ae4360acdcaTimo Sirainen notify->list->mail_set->mailbox_idle_check_interval > 0) {
5ddc694e19875c8e3ad7db77807d6ae4360acdcaTimo Sirainen /* no pending notification - check if anything had changed */
182724707b7f73a181716d439863fb756d8ad03dTimo Sirainen full_notify_callback(inotify);
5ddc694e19875c8e3ad7db77807d6ae4360acdcaTimo Sirainen }
58a89627905e3590381cdd5eb931b9537c4b4ea6Timo Sirainen if (inotify->to_notify != NULL)
58a89627905e3590381cdd5eb931b9537c4b4ea6Timo Sirainen notify_now_callback(inotify);
58a89627905e3590381cdd5eb931b9537c4b4ea6Timo Sirainen}