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