dovecot: When syncing a mailbox, sync the view internally first ...
dovecot at dovecot.org
dovecot at dovecot.org
Sun Jan 6 11:04:12 EET 2008
details: http://hg.dovecot.org/dovecot/rev/98788fdcc3a6
changeset: 7128:98788fdcc3a6
user: Timo Sirainen <tss at iki.fi>
date: Sun Jan 06 11:04:07 2008 +0200
description:
When syncing a mailbox, sync the view internally first completely and just
get a list of messages that have changed. Then just have mailbox_sync_next()
return flag updates from that list. This avoids duplicate notifications and
also fixes some bugs in previous implementation.
MAILBOX_SYNC_TYPE_KEYWORDS no longer exists, keyword changes are included in
MAILBOX_SYNC_TYPE_FLAGS.
diffstat:
9 files changed, 84 insertions(+), 98 deletions(-)
src/imap/imap-sync.c | 1
src/lib-storage/index/index-storage.h | 2
src/lib-storage/index/index-sync-changes.c | 6
src/lib-storage/index/index-sync-changes.h | 2
src/lib-storage/index/index-sync.c | 146 ++++++++------------
src/lib-storage/index/maildir/maildir-sync-index.c | 8 -
src/lib-storage/index/mbox/mbox-sync-update.c | 6
src/lib-storage/index/mbox/mbox-sync.c | 8 -
src/lib-storage/mail-storage.h | 3
diffs (truncated from 344 to 300 lines):
diff -r 010485455f75 -r 98788fdcc3a6 src/imap/imap-sync.c
--- a/src/imap/imap-sync.c Sun Jan 06 11:00:44 2008 +0200
+++ b/src/imap/imap-sync.c Sun Jan 06 11:04:07 2008 +0200
@@ -146,7 +146,6 @@ int imap_sync_more(struct imap_sync_cont
switch (ctx->sync_rec.type) {
case MAILBOX_SYNC_TYPE_FLAGS:
- case MAILBOX_SYNC_TYPE_KEYWORDS:
if (ctx->seq == 0)
ctx->seq = ctx->sync_rec.seq1;
diff -r 010485455f75 -r 98788fdcc3a6 src/lib-storage/index/index-storage.h
--- a/src/lib-storage/index/index-storage.h Sun Jan 06 11:00:44 2008 +0200
+++ b/src/lib-storage/index/index-storage.h Sun Jan 06 11:04:07 2008 +0200
@@ -136,7 +136,7 @@ int index_mailbox_sync_deinit(struct mai
struct mailbox_status *status_r);
int index_storage_sync(struct mailbox *box, enum mailbox_sync_flags flags);
-
+enum mailbox_sync_type index_sync_type_convert(enum mail_index_sync_type type);
void index_storage_get_status(struct mailbox *box,
enum mailbox_status_items items,
struct mailbox_status *status_r);
diff -r 010485455f75 -r 98788fdcc3a6 src/lib-storage/index/index-sync-changes.c
--- a/src/lib-storage/index/index-sync-changes.c Sun Jan 06 11:00:44 2008 +0200
+++ b/src/lib-storage/index/index-sync-changes.c Sun Jan 06 11:04:07 2008 +0200
@@ -163,7 +163,7 @@ void index_sync_changes_apply(struct ind
void index_sync_changes_apply(struct index_sync_changes_context *ctx,
pool_t pool, uint8_t *flags,
ARRAY_TYPE(keyword_indexes) *keywords,
- enum mailbox_sync_type *sync_type_r)
+ enum mail_index_sync_type *sync_type_r)
{
const struct mail_index_sync_rec *syncs;
unsigned int i, count;
@@ -174,7 +174,7 @@ void index_sync_changes_apply(struct ind
switch (syncs[i].type) {
case MAIL_INDEX_SYNC_TYPE_FLAGS:
mail_index_sync_flags_apply(&syncs[i], flags);
- sync_type |= MAILBOX_SYNC_TYPE_FLAGS;
+ sync_type |= MAIL_INDEX_SYNC_TYPE_FLAGS;
break;
case MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD:
case MAIL_INDEX_SYNC_TYPE_KEYWORD_REMOVE:
@@ -190,7 +190,7 @@ void index_sync_changes_apply(struct ind
I_MIN(10, count - i));
}
if (mail_index_sync_keywords_apply(&syncs[i], keywords))
- sync_type |= MAILBOX_SYNC_TYPE_KEYWORDS;
+ sync_type |= syncs[i].type;
break;
default:
break;
diff -r 010485455f75 -r 98788fdcc3a6 src/lib-storage/index/index-sync-changes.h
--- a/src/lib-storage/index/index-sync-changes.h Sun Jan 06 11:00:44 2008 +0200
+++ b/src/lib-storage/index/index-sync-changes.h Sun Jan 06 11:04:07 2008 +0200
@@ -22,6 +22,6 @@ void index_sync_changes_apply(struct ind
void index_sync_changes_apply(struct index_sync_changes_context *ctx,
pool_t pool, uint8_t *flags,
ARRAY_TYPE(keyword_indexes) *keywords,
- enum mailbox_sync_type *sync_type_r);
+ enum mail_index_sync_type *sync_type_r);
#endif
diff -r 010485455f75 -r 98788fdcc3a6 src/lib-storage/index/index-sync.c
--- a/src/lib-storage/index/index-sync.c Sun Jan 06 11:00:44 2008 +0200
+++ b/src/lib-storage/index/index-sync.c Sun Jan 06 11:04:07 2008 +0200
@@ -12,9 +12,9 @@ struct index_mailbox_sync_context {
struct mail_index_view_sync_ctx *sync_ctx;
uint32_t messages_count;
+ ARRAY_TYPE(seq_range) flag_updates;
const ARRAY_TYPE(seq_range) *expunges;
- unsigned int expunge_pos;
- uint32_t last_seq1, last_seq2;
+ unsigned int flag_update_pos, expunge_pos;
bool failed;
};
@@ -93,6 +93,41 @@ static void index_mailbox_expunge_recent
}
}
+static void index_view_sync_recs_get(struct index_mailbox_sync_context *ctx)
+{
+ struct mail_index_view_sync_rec sync;
+ uint32_t seq1, seq2;
+
+ i_array_init(&ctx->flag_updates, 128);
+ while (mail_index_view_sync_next(ctx->sync_ctx, &sync)) {
+ switch (sync.type) {
+ case MAIL_INDEX_SYNC_TYPE_APPEND:
+ /* not interested */
+ break;
+ case MAIL_INDEX_SYNC_TYPE_EXPUNGE:
+ /* later */
+ break;
+ case MAIL_INDEX_SYNC_TYPE_FLAGS:
+ case MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD:
+ case MAIL_INDEX_SYNC_TYPE_KEYWORD_REMOVE:
+ case MAIL_INDEX_SYNC_TYPE_KEYWORD_RESET:
+ if (mail_index_lookup_seq_range(ctx->ibox->view,
+ sync.uid1, sync.uid2,
+ &seq1, &seq2)) {
+ seq_range_array_add_range(&ctx->flag_updates,
+ seq1, seq2);
+ }
+ break;
+ }
+ }
+
+ /* remove expunged messages from flag updates */
+ if (ctx->expunges != NULL) {
+ seq_range_array_remove_seq_range(&ctx->flag_updates,
+ ctx->expunges);
+ }
+}
+
struct mailbox_sync_context *
index_mailbox_sync_init(struct mailbox *box, enum mailbox_sync_flags flags,
bool failed)
@@ -133,56 +168,8 @@ index_mailbox_sync_init(struct mailbox *
&ctx->expunges);
ctx->expunge_pos = array_count(ctx->expunges);
}
+ index_view_sync_recs_get(ctx);
return &ctx->ctx;
-}
-
-static bool sync_rec_check_skips(struct index_mailbox_sync_context *ctx,
- struct mailbox_sync_rec *sync_rec)
-{
- uint32_t seq, new_seq1, new_seq2;
-
- if (sync_rec->seq1 >= ctx->last_seq1 &&
- sync_rec->seq1 <= ctx->last_seq2)
- new_seq1 = ctx->last_seq2 + 1;
- else
- new_seq1 = sync_rec->seq1;
- if (sync_rec->seq2 >= ctx->last_seq1 &&
- sync_rec->seq2 <= ctx->last_seq2)
- new_seq2 = ctx->last_seq1 - 1;
- else
- new_seq2 = sync_rec->seq2;
-
- if (new_seq1 > new_seq2)
- return FALSE;
-
- ctx->last_seq1 = sync_rec->seq1;
- ctx->last_seq2 = sync_rec->seq2;
-
- sync_rec->seq1 = new_seq1;
- sync_rec->seq2 = new_seq2;
-
- /* FIXME: we're only skipping messages from the beginning and from
- the end. we should skip also the middle ones. This takes care of
- the most common repeats though. */
- if (ctx->expunges != NULL) {
- /* skip expunged messages from the beginning and the end */
- for (seq = sync_rec->seq1; seq <= sync_rec->seq2; seq++) {
- if (!seq_range_exists(ctx->expunges, seq))
- break;
- }
- if (seq > sync_rec->seq2) {
- /* everything skipped */
- return FALSE;
- }
- sync_rec->seq1 = seq;
-
- for (seq = sync_rec->seq2; seq >= sync_rec->seq1; seq--) {
- if (!seq_range_exists(ctx->expunges, seq))
- break;
- }
- sync_rec->seq2 = seq;
- }
- return TRUE;
}
static int
@@ -214,41 +201,21 @@ bool index_mailbox_sync_next(struct mail
{
struct index_mailbox_sync_context *ctx =
(struct index_mailbox_sync_context *)_ctx;
- struct mail_index_view_sync_rec sync;
+ const struct seq_range *flag_updates;
+ unsigned int count;
if (ctx->failed)
return FALSE;
- while (mail_index_view_sync_next(ctx->sync_ctx, &sync)) {
- switch (sync.type) {
- case MAIL_INDEX_SYNC_TYPE_APPEND:
- /* not interested */
- break;
- case MAIL_INDEX_SYNC_TYPE_EXPUNGE:
- /* later */
- break;
- case MAIL_INDEX_SYNC_TYPE_FLAGS:
- case MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD:
- case MAIL_INDEX_SYNC_TYPE_KEYWORD_REMOVE:
- case MAIL_INDEX_SYNC_TYPE_KEYWORD_RESET:
- /* FIXME: hide the flag updates for expunged messages */
- mail_index_lookup_seq_range(ctx->ibox->view,
- sync.uid1, sync.uid2,
- &sync_rec_r->seq1,
- &sync_rec_r->seq2);
- if (sync_rec_r->seq1 == 0)
- break;
-
- if (!sync_rec_check_skips(ctx, sync_rec_r))
- break;
-
- sync_rec_r->type =
- sync.type == MAIL_INDEX_SYNC_TYPE_FLAGS ?
- MAILBOX_SYNC_TYPE_FLAGS :
- MAILBOX_SYNC_TYPE_KEYWORDS;
- return 1;
- }
- }
+ flag_updates = array_get(&ctx->flag_updates, &count);
+ if (ctx->flag_update_pos < count) {
+ sync_rec_r->type = MAILBOX_SYNC_TYPE_FLAGS;
+ sync_rec_r->seq1 = flag_updates[ctx->flag_update_pos].seq1;
+ sync_rec_r->seq2 = flag_updates[ctx->flag_update_pos].seq2;
+ ctx->flag_update_pos++;
+ return 1;
+ }
+
return index_mailbox_sync_next_expunge(ctx, sync_rec_r);
}
@@ -353,6 +320,7 @@ int index_mailbox_sync_deinit(struct mai
if (ret == 0 && status_items != 0)
mailbox_get_status(_ctx->box, status_items, status_r);
+ array_free(&ctx->flag_updates);
i_free(ctx);
return ret;
}
@@ -389,3 +357,17 @@ bool index_keyword_array_cmp(const ARRAY
}
return TRUE;
}
+
+enum mailbox_sync_type index_sync_type_convert(enum mail_index_sync_type type)
+{
+ enum mailbox_sync_type ret = 0;
+
+ if ((type & MAIL_INDEX_SYNC_TYPE_EXPUNGE) != 0)
+ ret |= MAILBOX_SYNC_TYPE_EXPUNGE;
+ if ((type & (MAIL_INDEX_SYNC_TYPE_FLAGS |
+ MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD |
+ MAIL_INDEX_SYNC_TYPE_KEYWORD_REMOVE |
+ MAIL_INDEX_SYNC_TYPE_KEYWORD_RESET)) != 0)
+ ret |= MAILBOX_SYNC_TYPE_FLAGS;
+ return ret;
+}
diff -r 010485455f75 -r 98788fdcc3a6 src/lib-storage/index/maildir/maildir-sync-index.c
--- a/src/lib-storage/index/maildir/maildir-sync-index.c Sun Jan 06 11:00:44 2008 +0200
+++ b/src/lib-storage/index/maildir/maildir-sync-index.c Sun Jan 06 11:04:07 2008 +0200
@@ -65,7 +65,7 @@ static int maildir_sync_flags(struct mai
{
struct mailbox *box = &mbox->ibox.box;
const char *dir, *fname, *newfname, *newpath;
- enum mailbox_sync_type sync_type;
+ enum mail_index_sync_type sync_type;
uint8_t flags8;
fname = strrchr(path, '/');
@@ -88,8 +88,10 @@ static int maildir_sync_flags(struct mai
ctx->flags, &ctx->keywords);
newpath = t_strconcat(dir, newfname, NULL);
if (rename(path, newpath) == 0) {
- if (box->v.sync_notify != NULL)
- box->v.sync_notify(box, ctx->uid, sync_type);
+ if (box->v.sync_notify != NULL) {
+ box->v.sync_notify(box, ctx->uid,
+ index_sync_type_convert(sync_type));
+ }
ctx->changed = TRUE;
return 1;
}
diff -r 010485455f75 -r 98788fdcc3a6 src/lib-storage/index/mbox/mbox-sync-update.c
--- a/src/lib-storage/index/mbox/mbox-sync-update.c Sun Jan 06 11:00:44 2008 +0200
+++ b/src/lib-storage/index/mbox/mbox-sync-update.c Sun Jan 06 11:04:07 2008 +0200
@@ -376,7 +376,7 @@ static void mbox_sync_update_header_real
static void mbox_sync_update_header_real(struct mbox_sync_mail_context *ctx)
{
uint8_t old_flags;
- enum mailbox_sync_type sync_type;
+ enum mail_index_sync_type sync_type;
i_assert(ctx->mail.uid != 0 || ctx->mail.pseudo);
@@ -390,7 +390,9 @@ static void mbox_sync_update_header_real
if ((old_flags & XSTATUS_FLAGS_MASK) !=
(ctx->mail.flags & XSTATUS_FLAGS_MASK))
mbox_sync_update_xstatus(ctx);
- if ((sync_type & MAILBOX_SYNC_TYPE_KEYWORDS) != 0)
More information about the dovecot-cvs
mailing list