dovecot-2.2: lib-storage: Added mailbox-list-notify API for trac...
dovecot at dovecot.org
dovecot at dovecot.org
Mon Aug 13 15:23:46 EEST 2012
details: http://hg.dovecot.org/dovecot-2.2/rev/a16d77a075bb
changeset: 14898:a16d77a075bb
user: Timo Sirainen <tss at iki.fi>
date: Mon Aug 13 15:20:33 2012 +0300
description:
lib-storage: Added mailbox-list-notify API for tracking changes in all mailboxes.
Requires mailbox_list_index=yes to work.
diffstat:
src/lib-storage/Makefile.am | 2 +
src/lib-storage/index/imapc/imapc-list.c | 3 +-
src/lib-storage/index/shared/shared-list.c | 3 +-
src/lib-storage/list/Makefile.am | 3 +
src/lib-storage/list/mailbox-list-fs.c | 3 +-
src/lib-storage/list/mailbox-list-index-notify.c | 699 +++++++++++++++++++++++
src/lib-storage/list/mailbox-list-index-status.c | 52 +-
src/lib-storage/list/mailbox-list-index-sync.c | 32 +
src/lib-storage/list/mailbox-list-index.c | 49 +-
src/lib-storage/list/mailbox-list-index.h | 25 +-
src/lib-storage/list/mailbox-list-maildir.c | 6 +-
src/lib-storage/list/mailbox-list-none.c | 3 +-
src/lib-storage/list/mailbox-list-notify-tree.c | 129 ++++
src/lib-storage/list/mailbox-list-notify-tree.h | 27 +
src/lib-storage/mailbox-list-notify.c | 35 +
src/lib-storage/mailbox-list-notify.h | 58 +
src/lib-storage/mailbox-list-private.h | 12 +
17 files changed, 1111 insertions(+), 30 deletions(-)
diffs (truncated from 1506 to 300 lines):
diff -r 026b688b379f -r a16d77a075bb src/lib-storage/Makefile.am
--- a/src/lib-storage/Makefile.am Mon Aug 13 15:15:07 2012 +0300
+++ b/src/lib-storage/Makefile.am Mon Aug 13 15:20:33 2012 +0300
@@ -43,6 +43,7 @@
mailbox-keywords.c \
mailbox-list.c \
mailbox-list-iter.c \
+ mailbox-list-notify.c \
mailbox-search-result.c \
mailbox-tree.c \
mailbox-uidvalidity.c
@@ -70,6 +71,7 @@
mailbox-guid-cache.h \
mailbox-list.h \
mailbox-list-private.h \
+ mailbox-list-notify.h \
mailbox-search-result-private.h \
mailbox-tree.h \
mailbox-uidvalidity.h
diff -r 026b688b379f -r a16d77a075bb src/lib-storage/index/imapc/imapc-list.c
--- a/src/lib-storage/index/imapc/imapc-list.c Mon Aug 13 15:15:07 2012 +0300
+++ b/src/lib-storage/index/imapc/imapc-list.c Mon Aug 13 15:20:33 2012 +0300
@@ -720,6 +720,7 @@
imapc_list_delete_mailbox,
imapc_list_delete_dir,
imapc_list_delete_symlink,
- imapc_list_rename_mailbox
+ imapc_list_rename_mailbox,
+ NULL, NULL, NULL, NULL
}
};
diff -r 026b688b379f -r a16d77a075bb src/lib-storage/index/shared/shared-list.c
--- a/src/lib-storage/index/shared/shared-list.c Mon Aug 13 15:15:07 2012 +0300
+++ b/src/lib-storage/index/shared/shared-list.c Mon Aug 13 15:20:33 2012 +0300
@@ -359,6 +359,7 @@
shared_list_delete_mailbox,
shared_list_delete_dir,
shared_list_delete_symlink,
- shared_list_rename_mailbox
+ shared_list_rename_mailbox,
+ NULL, NULL, NULL, NULL
}
};
diff -r 026b688b379f -r a16d77a075bb src/lib-storage/list/Makefile.am
--- a/src/lib-storage/list/Makefile.am Mon Aug 13 15:15:07 2012 +0300
+++ b/src/lib-storage/list/Makefile.am Mon Aug 13 15:20:33 2012 +0300
@@ -15,11 +15,13 @@
mailbox-list-fs-iter.c \
mailbox-list-index.c \
mailbox-list-index-iter.c \
+ mailbox-list-index-notify.c \
mailbox-list-index-status.c \
mailbox-list-index-sync.c \
mailbox-list-maildir.c \
mailbox-list-maildir-iter.c \
mailbox-list-none.c \
+ mailbox-list-notify-tree.c \
mailbox-list-subscriptions.c \
subscription-file.c
@@ -28,6 +30,7 @@
mailbox-list-fs.h \
mailbox-list-index.h \
mailbox-list-maildir.h \
+ mailbox-list-notify-tree.h \
mailbox-list-subscriptions.h \
subscription-file.h
diff -r 026b688b379f -r a16d77a075bb src/lib-storage/list/mailbox-list-fs.c
--- a/src/lib-storage/list/mailbox-list-fs.c Mon Aug 13 15:15:07 2012 +0300
+++ b/src/lib-storage/list/mailbox-list-fs.c Mon Aug 13 15:20:33 2012 +0300
@@ -651,6 +651,7 @@
fs_list_delete_mailbox,
fs_list_delete_dir,
mailbox_list_delete_symlink_default,
- fs_list_rename_mailbox
+ fs_list_rename_mailbox,
+ NULL, NULL, NULL, NULL
}
};
diff -r 026b688b379f -r a16d77a075bb src/lib-storage/list/mailbox-list-index-notify.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-storage/list/mailbox-list-index-notify.c Mon Aug 13 15:20:33 2012 +0300
@@ -0,0 +1,699 @@
+/* Copyright (c) 2012 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "ioloop.h"
+#include "str.h"
+#include "mail-index-private.h"
+#include "mail-transaction-log-private.h"
+#include "mail-storage.h"
+#include "mailbox-list-notify.h"
+#include "mailbox-list-notify-tree.h"
+#include "mailbox-list-index.h"
+
+#include <sys/stat.h>
+
+#define NOTIFY_DELAY_MSECS 500
+
+enum ilist_ext_type {
+ ILIST_EXT_NONE,
+ ILIST_EXT_BASE,
+ ILIST_EXT_MSGS,
+ ILIST_EXT_HIGHESTMODSEQ,
+ ILIST_EXT_UNKNOWN
+};
+
+struct mailbox_list_notify_rename {
+ uint32_t old_uid, new_uid;
+};
+
+struct mailbox_list_inotify_entry {
+ uint32_t uid;
+ guid_128_t guid;
+ bool expunge;
+};
+
+struct mailbox_list_notify_index {
+ struct mailbox_list_notify notify;
+
+ struct mailbox_list_notify_tree *tree;
+ struct mail_index_view *view, *old_view;
+ struct mail_index_view_sync_ctx *sync_ctx;
+ enum ilist_ext_type cur_ext;
+ uint32_t cur_ext_id;
+
+ void (*wait_callback)(void *context);
+ void *wait_context;
+ struct io *io_wait;
+ struct timeout *to_wait, *to_notify;
+
+ ARRAY_TYPE(seq_range) new_uids, expunged_uids, changed_uids;
+ ARRAY_DEFINE(renames, struct mailbox_list_notify_rename);
+ struct seq_range_iter new_uids_iter, expunged_uids_iter;
+ struct seq_range_iter changed_uids_iter;
+ unsigned int new_uids_n, expunged_uids_n, changed_uids_n;
+ unsigned int rename_idx;
+
+ struct mailbox_list_notify_rec notify_rec;
+ string_t *rec_name;
+
+ struct stat last_st;
+
+ unsigned int initialized:1;
+ unsigned int read_failed:1;
+};
+
+int mailbox_list_index_notify_init(struct mailbox_list *list,
+ enum mailbox_list_notify_event mask,
+ struct mailbox_list_notify **notify_r)
+{
+ struct mailbox_list_index *ilist = INDEX_LIST_CONTEXT(list);
+ struct mailbox_list_notify_index *inotify;
+
+ if (ilist == NULL) {
+ /* can't do this without mailbox list indexes */
+ return -1;
+ }
+
+ (void)mailbox_list_index_refresh(list);
+
+ inotify = i_new(struct mailbox_list_notify_index, 1);
+ inotify->notify.list = list;
+ inotify->notify.mask = mask;
+ inotify->view = mail_index_view_open(ilist->index);
+ inotify->old_view = mail_index_view_dup_private(inotify->view);
+ inotify->tree = mailbox_list_notify_tree_init(list);
+ i_array_init(&inotify->new_uids, 8);
+ i_array_init(&inotify->expunged_uids, 8);
+ i_array_init(&inotify->changed_uids, 16);
+ i_array_init(&inotify->renames, 16);
+ inotify->rec_name = str_new(default_pool, 64);
+
+ *notify_r = &inotify->notify;
+ return 1;
+}
+
+void mailbox_list_index_notify_deinit(struct mailbox_list_notify *notify)
+{
+ struct mailbox_list_notify_index *inotify =
+ (struct mailbox_list_notify_index *)notify;
+ bool b;
+
+ if (inotify->io_wait != NULL)
+ io_remove(&inotify->io_wait);
+ if (inotify->to_wait != NULL)
+ timeout_remove(&inotify->to_wait);
+ if (inotify->to_notify != NULL)
+ timeout_remove(&inotify->to_notify);
+ if (inotify->sync_ctx != NULL)
+ (void)mail_index_view_sync_commit(&inotify->sync_ctx, &b);
+ mail_index_view_close(&inotify->view);
+ mail_index_view_close(&inotify->old_view);
+ mailbox_list_notify_tree_deinit(&inotify->tree);
+ array_free(&inotify->new_uids);
+ array_free(&inotify->expunged_uids);
+ array_free(&inotify->changed_uids);
+ array_free(&inotify->renames);
+ str_free(&inotify->rec_name);
+ i_free(inotify);
+}
+
+static struct mailbox_list_index_node *
+notify_lookup_guid(struct mailbox_list_notify_index *inotify,
+ struct mail_index_view *view,
+ uint32_t uid, enum mailbox_status_items items,
+ struct mailbox_status *status_r, guid_128_t guid_r)
+{
+ struct mailbox_list_index *ilist =
+ INDEX_LIST_CONTEXT(inotify->notify.list);
+ struct mailbox_list_index_node *index_node;
+ uint32_t seq;
+
+ if (!mail_index_lookup_seq(view, uid, &seq))
+ return NULL;
+
+ index_node = mailbox_list_index_lookup_uid(ilist, uid);
+ if (index_node == NULL) {
+ /* re-parse the index list using the given view. we could be
+ jumping here between old and new view. */
+ (void)mailbox_list_index_parse(ilist, view, FALSE);
+ index_node = mailbox_list_index_lookup_uid(ilist, uid);
+ if (index_node == NULL)
+ return NULL;
+ }
+
+ /* get GUID */
+ memset(status_r, 0, sizeof(*status_r));
+ memset(guid_r, 0, GUID_128_SIZE);
+ (void)mailbox_list_index_status(inotify->notify.list, view, seq,
+ items, status_r, guid_r);
+ return index_node;
+}
+
+static void notify_update_stat(struct mailbox_list_notify_index *inotify)
+{
+ struct mailbox_list_index *ilist =
+ INDEX_LIST_CONTEXT(inotify->notify.list);
+ const char *path = ilist->index->log->filepath;
+
+ if (stat(path, &inotify->last_st) < 0 && errno != ENOENT) {
+ i_error("stat(%s) failed: %m", path);
+ mailbox_list_index_notify_wait(&inotify->notify, NULL, NULL);
+ }
+}
+
+static void
+mailbox_list_index_notify_sync_init(struct mailbox_list_notify_index *inotify)
+{
+ struct mail_index_view_sync_rec sync_rec;
+
+ notify_update_stat(inotify);
+ (void)mail_index_refresh(inotify->view->index);
+
+ /* sync the view so that map extensions gets updated */
+ inotify->sync_ctx = mail_index_view_sync_begin(inotify->view, 0);
+ mail_transaction_log_view_mark(inotify->view->log_view);
+ while (mail_index_view_sync_next(inotify->sync_ctx, &sync_rec)) ;
+ mail_transaction_log_view_rewind(inotify->view->log_view);
+
+ inotify->cur_ext = ILIST_EXT_NONE;
+ inotify->cur_ext_id = (uint32_t)-1;
+}
+
+static bool notify_ext_rec(struct mailbox_list_notify_index *inotify,
+ uint32_t uid)
+{
+ struct mailbox_list_notify *notify = &inotify->notify;
+
+ switch (inotify->cur_ext) {
+ case ILIST_EXT_NONE:
+ i_unreached();
+ case ILIST_EXT_BASE:
+ /* UIDVALIDITY changed */
+ if ((notify->mask & MAILBOX_LIST_NOTIFY_UIDVALIDITY) == 0)
+ return FALSE;
+ break;
+ case ILIST_EXT_MSGS:
+ /* APPEND, EXPUNGE, \Seen or \Recent flag change */
+ if ((notify->mask & MAILBOX_LIST_NOTIFY_STATUS) == 0)
+ return FALSE;
+ break;
+ case ILIST_EXT_HIGHESTMODSEQ:
+ /* when this doesn't come with EXT_MSGS update,
+ it can only be a flag change or an explicit
+ modseq change */
+ if ((notify->mask & MAILBOX_LIST_NOTIFY_MODSEQ_CHANGES) == 0)
+ return FALSE;
+ break;
+ case ILIST_EXT_UNKNOWN:
+ return FALSE;
+ }
+ seq_range_array_add(&inotify->changed_uids, uid);
+ return TRUE;
+}
+
+static int
+mailbox_list_index_notify_read_next(struct mailbox_list_notify_index *inotify)
+{
More information about the dovecot-cvs
mailing list