dovecot-2.2: lib-storage: Mailbox list notifications didn't work...
dovecot at dovecot.org
dovecot at dovecot.org
Mon Sep 7 21:09:03 UTC 2015
details: http://hg.dovecot.org/dovecot-2.2/rev/f600285c3df2
changeset: 19118:f600285c3df2
user: Timo Sirainen <tss at iki.fi>
date: Tue Sep 08 00:07:55 2015 +0300
description:
lib-storage: Mailbox list notifications didn't work for INBOX.
Because of some earlier optimizations that changes to INBOX aren't written
to dovecot.list.index.log file.
diffstat:
src/lib-storage/list/mailbox-list-index-notify.c | 88 ++++++++++++++++++-----
1 files changed, 69 insertions(+), 19 deletions(-)
diffs (186 lines):
diff -r fa979ccfa34c -r f600285c3df2 src/lib-storage/list/mailbox-list-index-notify.c
--- a/src/lib-storage/list/mailbox-list-index-notify.c Mon Sep 07 23:55:31 2015 +0300
+++ b/src/lib-storage/list/mailbox-list-index-notify.c Tue Sep 08 00:07:55 2015 +0300
@@ -5,7 +5,7 @@
#include "str.h"
#include "mail-index-private.h"
#include "mail-transaction-log-private.h"
-#include "mail-storage.h"
+#include "mail-storage-private.h"
#include "mailbox-list-notify.h"
#include "mailbox-list-notify-tree.h"
#include "mailbox-list-index.h"
@@ -44,7 +44,7 @@
void (*wait_callback)(void *context);
void *wait_context;
- struct io *io_wait;
+ struct io *io_wait, *io_wait_inbox;
struct timeout *to_wait, *to_notify;
ARRAY_TYPE(seq_range) new_uids, expunged_uids, changed_uids;
@@ -58,10 +58,12 @@
struct mailbox_list_notify_rec notify_rec;
string_t *rec_name;
- struct stat last_st;
+ char *list_log_path, *inbox_log_path;
+ struct stat list_last_st, inbox_last_st;
unsigned int initialized:1;
unsigned int read_failed:1;
+ unsigned int inbox_event_pending:1;
};
int mailbox_list_index_notify_init(struct mailbox_list *list,
@@ -70,6 +72,7 @@
{
struct mailbox_list_index *ilist = INDEX_LIST_CONTEXT(list);
struct mailbox_list_notify_index *inotify;
+ const char *index_dir;
if (ilist == NULL) {
/* can't do this without mailbox list indexes */
@@ -97,6 +100,14 @@
mailbox_tree_sort(list->subscriptions);
inotify->subscriptions = mailbox_tree_dup(list->subscriptions);
}
+ inotify->list_log_path = i_strdup(ilist->index->log->filepath);
+ if ((list->ns->flags & NAMESPACE_FLAG_INBOX_ANY) != 0 &&
+ mailbox_list_get_path(list, "INBOX", MAILBOX_LIST_PATH_TYPE_INDEX,
+ &index_dir) > 0) {
+ /* FIXME: annoyingly hardcoded filename. */
+ inotify->inbox_log_path = i_strdup_printf(
+ "%s/"MAIL_INDEX_PREFIX".log", index_dir);
+ }
*notify_r = &inotify->notify;
return 1;
@@ -112,6 +123,8 @@
mailbox_tree_deinit(&inotify->subscriptions);
if (inotify->io_wait != NULL)
io_remove(&inotify->io_wait);
+ if (inotify->io_wait_inbox != NULL)
+ io_remove(&inotify->io_wait_inbox);
if (inotify->to_wait != NULL)
timeout_remove(&inotify->to_wait);
if (inotify->to_notify != NULL)
@@ -128,6 +141,8 @@
array_free(&inotify->changed_uids);
array_free(&inotify->renames);
str_free(&inotify->rec_name);
+ i_free(inotify->list_log_path);
+ i_free(inotify->inbox_log_path);
i_free(inotify);
}
@@ -166,14 +181,22 @@
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;
+ bool call = FALSE;
- if (stat(path, &inotify->last_st) < 0 && errno != ENOENT) {
- i_error("stat(%s) failed: %m", path);
+ if (stat(inotify->list_log_path, &inotify->list_last_st) < 0 &&
+ errno != ENOENT) {
+ i_error("stat(%s) failed: %m", inotify->list_log_path);
+ call = TRUE;
+ }
+ if (inotify->inbox_log_path != NULL) {
+ if (stat(inotify->inbox_log_path, &inotify->inbox_last_st) < 0 &&
+ errno != ENOENT) {
+ i_error("stat(%s) failed: %m", inotify->inbox_log_path);
+ call = TRUE;
+ }
+ }
+ if (call)
mailbox_list_index_notify_wait(&inotify->notify, NULL, NULL);
- }
}
static void
@@ -760,6 +783,20 @@
/* caller doesn't care about this change */
}
}
+ if (inotify->inbox_event_pending) {
+ inotify->inbox_event_pending = FALSE;
+ memset(&inotify->notify_rec, 0, sizeof(inotify->notify_rec));
+ inotify->notify_rec.vname = "INBOX";
+ inotify->notify_rec.storage_name = "INBOX";
+ /* Don't bother trying to figure out which event exactly this
+ is. Just send them all and let the caller handle it. */
+ inotify->notify_rec.events = MAILBOX_LIST_NOTIFY_APPENDS |
+ MAILBOX_LIST_NOTIFY_EXPUNGES |
+ MAILBOX_LIST_NOTIFY_SEEN_CHANGES |
+ MAILBOX_LIST_NOTIFY_MODSEQ_CHANGES;
+ *rec_r = &inotify->notify_rec;
+ return 1;
+ }
mailbox_list_index_notify_read_deinit(inotify);
return inotify->read_failed ? -1 : 0;
@@ -773,13 +810,19 @@
static void notify_callback(struct mailbox_list_notify_index *inotify)
{
- struct stat prev_st = inotify->last_st;
-
+#define INOTIFY_ST_CHANGED(last_st, prev_st) \
+ ((last_st).st_mtime != (prev_st).st_mtime || \
+ ST_MTIME_NSEC(last_st) != ST_MTIME_NSEC(prev_st) || \
+ (last_st).st_size != (prev_st).st_size || \
+ (last_st).st_ino != (prev_st).st_ino)
+ struct stat list_prev_st = inotify->list_last_st;
+ struct stat inbox_prev_st = inotify->inbox_last_st;
+
notify_update_stat(inotify);
- if (inotify->last_st.st_mtime != prev_st.st_mtime ||
- ST_MTIME_NSEC(inotify->last_st) != ST_MTIME_NSEC(prev_st) ||
- inotify->last_st.st_size != prev_st.st_size ||
- inotify->last_st.st_ino != prev_st.st_ino) {
+ if (INOTIFY_ST_CHANGED(inotify->inbox_last_st, inbox_prev_st))
+ inotify->inbox_event_pending = TRUE;
+ if (inotify->inbox_event_pending ||
+ INOTIFY_ST_CHANGED(inotify->list_last_st, list_prev_st)) {
/* log has changed. call the callback with a small delay
to allow bundling multiple changes together */
if (inotify->to_notify != NULL) {
@@ -798,7 +841,6 @@
{
struct mailbox_list_notify_index *inotify =
(struct mailbox_list_notify_index *)notify;
- const char *path;
unsigned int check_interval;
inotify->wait_callback = callback;
@@ -807,14 +849,22 @@
if (callback == NULL) {
if (inotify->io_wait != NULL)
io_remove(&inotify->io_wait);
+ if (inotify->io_wait_inbox != NULL)
+ io_remove(&inotify->io_wait_inbox);
if (inotify->to_wait != NULL)
timeout_remove(&inotify->to_wait);
if (inotify->to_notify != NULL)
timeout_remove(&inotify->to_notify);
} else if (inotify->to_wait == NULL) {
- path = inotify->view->index->log->filepath;
- (void)io_add_notify(path, notify_callback, inotify,
- &inotify->io_wait);
+ (void)io_add_notify(inotify->list_log_path, notify_callback,
+ inotify, &inotify->io_wait);
+ /* we need to check for INBOX explicitly, because INBOX changes
+ don't get added to mailbox.list.index.log */
+ if (inotify->inbox_log_path != NULL) {
+ (void)io_add_notify(inotify->inbox_log_path,
+ notify_callback, inotify,
+ &inotify->io_wait_inbox);
+ }
/* check with timeout as well, in case io_add_notify()
doesn't work (e.g. NFS) */
check_interval = notify->list->mail_set->mailbox_idle_check_interval;
More information about the dovecot-cvs
mailing list