Mercurial > dovecot > original-hg > dovecot-1.2
changeset 7128:98788fdcc3a6 HEAD
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.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sun, 06 Jan 2008 11:04:07 +0200 |
parents | 010485455f75 |
children | 0c1859ca8ee9 |
files | src/imap/imap-sync.c src/lib-storage/index/index-storage.h src/lib-storage/index/index-sync-changes.c src/lib-storage/index/index-sync-changes.h src/lib-storage/index/index-sync.c src/lib-storage/index/maildir/maildir-sync-index.c src/lib-storage/index/mbox/mbox-sync-update.c src/lib-storage/index/mbox/mbox-sync.c src/lib-storage/mail-storage.h |
diffstat | 9 files changed, 83 insertions(+), 97 deletions(-) [+] |
line wrap: on
line diff
--- 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 @@ 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;
--- 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 @@ 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);
--- 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 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 @@ 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 @@ 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;
--- 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 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
--- 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 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_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,58 +168,10 @@ &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 index_mailbox_sync_next_expunge(struct index_mailbox_sync_context *ctx, struct mailbox_sync_rec *sync_rec_r) @@ -214,41 +201,21 @@ { 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; + 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; + } - 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; - } - } return index_mailbox_sync_next_expunge(ctx, sync_rec_r); } @@ -353,6 +320,7 @@ 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 @@ } 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; +}
--- 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 @@ { 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 @@ 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; }
--- 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(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 @@ 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) + if ((sync_type & (MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD | + MAIL_INDEX_SYNC_TYPE_KEYWORD_REMOVE | + MAIL_INDEX_SYNC_TYPE_KEYWORD_RESET)) != 0) mbox_sync_update_xkeywords(ctx); if (!ctx->sync_ctx->mbox->ibox.keep_recent)
--- a/src/lib-storage/index/mbox/mbox-sync.c Sun Jan 06 11:00:44 2008 +0200 +++ b/src/lib-storage/index/mbox/mbox-sync.c Sun Jan 06 11:04:07 2008 +0200 @@ -347,7 +347,7 @@ sync records are automatically applied to rec->flags at the end of index syncing, so calculate those new flags first */ struct mbox_sync_mail idx_mail; - enum mailbox_sync_type sync_type; + enum mail_index_sync_type sync_type; memset(&idx_mail, 0, sizeof(idx_mail)); idx_mail.flags = rec->flags & ~MAIL_RECENT; @@ -361,8 +361,10 @@ sync_ctx->mail_keyword_pool, &idx_mail.flags, &idx_mail.keywords, &sync_type); - if (sync_type != 0 && box->v.sync_notify != NULL) - box->v.sync_notify(box, rec->uid, sync_type); + if (sync_type != 0 && box->v.sync_notify != NULL) { + box->v.sync_notify(box, rec->uid, + index_sync_type_convert(sync_type)); + } if ((idx_mail.flags & MAIL_INDEX_MAIL_FLAG_DIRTY) != 0) { /* flags are dirty. ignore whatever was in the mbox,
--- a/src/lib-storage/mail-storage.h Sun Jan 06 11:00:44 2008 +0200 +++ b/src/lib-storage/mail-storage.h Sun Jan 06 11:04:07 2008 +0200 @@ -140,8 +140,7 @@ enum mailbox_sync_type { MAILBOX_SYNC_TYPE_EXPUNGE = 0x01, - MAILBOX_SYNC_TYPE_FLAGS = 0x02, - MAILBOX_SYNC_TYPE_KEYWORDS = 0x04 + MAILBOX_SYNC_TYPE_FLAGS = 0x02 }; struct message_part;