dovecot: Sync index changes while iterating through uidlist entr...

dovecot at dovecot.org dovecot at dovecot.org
Mon Jul 9 05:44:41 EEST 2007


details:   http://hg.dovecot.org/dovecot/rev/ae731dbf3a6f
changeset: 5914:ae731dbf3a6f
user:      Timo Sirainen <tss at iki.fi>
date:      Sun Jul 08 22:54:55 2007 +0300
description:
Sync index changes while iterating through uidlist entries. This avoids
unnecessary (and broken) flag updates.

diffstat:

1 file changed, 107 insertions(+), 260 deletions(-)
src/lib-storage/index/maildir/maildir-sync.c |  367 +++++++-------------------

diffs (truncated from 624 to 300 lines):

diff -r 699356ffe549 -r ae731dbf3a6f src/lib-storage/index/maildir/maildir-sync.c
--- a/src/lib-storage/index/maildir/maildir-sync.c	Sun Jul 08 22:53:31 2007 +0300
+++ b/src/lib-storage/index/maildir/maildir-sync.c	Sun Jul 08 22:54:55 2007 +0300
@@ -177,6 +177,7 @@
 #include "hash.h"
 #include "str.h"
 #include "maildir-storage.h"
+#include "index-sync-changes.h"
 #include "maildir-uidlist.h"
 #include "maildir-keywords.h"
 #include "maildir-filename.h"
@@ -217,7 +218,6 @@ struct maildir_sync_context {
 	const char *new_dir, *cur_dir;
 	bool partial;
 
-	unsigned int move_count, check_count;
 	time_t last_touch, last_notify;
 
 	struct maildir_uidlist_sync_ctx *uidlist_sync_ctx;
@@ -233,9 +233,13 @@ struct maildir_index_sync_context {
         struct maildir_keywords_sync_ctx *keywords_sync_ctx;
 	struct mail_index_transaction *trans;
 
-	ARRAY_DEFINE(sync_recs, struct mail_index_sync_rec);
+	struct index_sync_changes_context *sync_changes;
+	enum mail_flags flags;
+	ARRAY_TYPE(keyword_indexes) keywords;
+
 	uint32_t seq, uid;
-	int dirty_state;
+
+	bool changed;
 };
 
 struct maildir_keywords_sync_ctx *
@@ -255,7 +259,7 @@ static int maildir_expunge(struct maildi
 					   MAILBOX_SYNC_TYPE_EXPUNGE);
 		}
 		mail_index_expunge(ctx->trans, ctx->seq);
-		mbox->dirty_cur_time = ioloop_time;
+		ctx->changed = TRUE;
 		return 1;
 	}
 	if (errno == ENOENT)
@@ -270,79 +274,47 @@ static int maildir_sync_flags(struct mai
 			      struct maildir_index_sync_context *ctx)
 {
 	struct mailbox *box = &mbox->ibox.box;
-	const struct mail_index_sync_rec *recs;
 	const char *dir, *fname, *newfname, *newpath;
-	enum mail_flags flags;
 	enum mailbox_sync_type sync_type = 0;
-	ARRAY_TYPE(keyword_indexes) keywords;
-	unsigned int i, count;
 	uint8_t flags8;
-
-	ctx->dirty_state = 0;
 
 	fname = strrchr(path, '/');
 	i_assert(fname != NULL);
 	fname++;
 	dir = t_strdup_until(path, fname);
 
-	t_array_init(&keywords, 16);
+	/* get the current flags and keywords */
 	maildir_filename_get_flags(ctx->keywords_sync_ctx,
-				   fname, &flags, &keywords);
-	flags8 = flags;
-
-	recs = array_get_modifiable(&ctx->sync_recs, &count);
-	for (i = 0; i < count; i++) {
-		if (recs[i].uid1 != ctx->seq)
-			break;
-
-		switch (recs[i].type) {
-		case MAIL_INDEX_SYNC_TYPE_FLAGS:
-			mail_index_sync_flags_apply(&recs[i], &flags8);
-			sync_type |= MAILBOX_SYNC_TYPE_FLAGS;
-			break;
-		case MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD:
-		case MAIL_INDEX_SYNC_TYPE_KEYWORD_REMOVE:
-		case MAIL_INDEX_SYNC_TYPE_KEYWORD_RESET:
-			mail_index_sync_keywords_apply(&recs[i], &keywords);
-			sync_type |= MAILBOX_SYNC_TYPE_KEYWORDS;
-			break;
-		case MAIL_INDEX_SYNC_TYPE_APPEND:
-		case MAIL_INDEX_SYNC_TYPE_EXPUNGE:
-			i_unreached();
-			break;
-		}
-	}
-	i_assert(sync_type != 0);
-
-	newfname = maildir_filename_set_flags(ctx->keywords_sync_ctx,
-					      fname, flags8, &keywords);
+				   fname, &ctx->flags, &ctx->keywords);
+
+	/* apply changes */
+	flags8 = ctx->flags;
+	index_sync_changes_apply(ctx->sync_changes, NULL,
+				 &flags8, &ctx->keywords, &sync_type);
+	ctx->flags = flags8;
+
+	/* and try renaming with the new name */
+	newfname = maildir_filename_set_flags(ctx->keywords_sync_ctx, fname,
+					      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 ((flags8 & MAIL_INDEX_MAIL_FLAG_DIRTY) != 0)
-			ctx->dirty_state = -1;
-		mbox->dirty_cur_time = ioloop_time;
+		ctx->changed = TRUE;
 		return 1;
 	}
 	if (errno == ENOENT)
 		return 0;
 
-	if (ENOSPACE(errno) || errno == EACCES) {
-		mail_index_update_flags(ctx->trans, ctx->seq, MODIFY_ADD,
-			(enum mail_flags)MAIL_INDEX_MAIL_FLAG_DIRTY);
-		ctx->dirty_state = 1;
-		return 1;
-	}
-
-	mail_storage_set_critical(&mbox->storage->storage,
-				  "rename(%s, %s) failed: %m", path, newpath);
+	if (!ENOSPACE(errno) && errno != EACCES) {
+		mail_storage_set_critical(&mbox->storage->storage,
+			"rename(%s, %s) failed: %m", path, newpath);
+	}
 	return -1;
 }
 
-static void
-maildir_sync_check_timeouts(struct maildir_sync_context *ctx, bool move)
+static void maildir_sync_notify(struct maildir_sync_context *ctx)
 {
 	time_t now;
 
@@ -352,16 +324,6 @@ maildir_sync_check_timeouts(struct maild
 		return;
 	}
 
-	if (move) {
-		ctx->move_count++;
-		if ((ctx->move_count % MAILDIR_SLOW_MOVE_COUNT) != 0)
-			return;
-	} else {
-		ctx->check_count++;
-		if ((ctx->check_count % MAILDIR_SLOW_CHECK_COUNT) != 0)
-			return;
-	}
-
 	now = time(NULL);
 	if (now - ctx->last_touch > MAILDIR_LOCK_TOUCH_SECS) {
 		(void)maildir_uidlist_lock_touch(ctx->mbox->uidlist);
@@ -377,152 +339,6 @@ maildir_sync_check_timeouts(struct maild
 		}
 		ctx->last_notify = now;
 	}
-}
-
-static int
-maildir_sync_record_commit_until(struct maildir_index_sync_context *ctx,
-				 uint32_t last_seq)
-{
-	struct mail_index_sync_rec *recs;
-	unsigned int i, count;
-	uint32_t seq, uid;
-	bool expunged, flag_changed;
-
-	recs = array_get_modifiable(&ctx->sync_recs, &count);
-	for (seq = recs[0].uid1; seq <= last_seq; seq++) {
-		expunged = flag_changed = FALSE;
-		for (i = 0; i < count; i++) {
-			if (recs[i].uid1 > seq)
-				break;
-
-			i_assert(recs[i].uid1 == seq);
-			switch (recs[i].type) {
-			case MAIL_INDEX_SYNC_TYPE_EXPUNGE:
-				expunged = TRUE;
-				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:
-				flag_changed = TRUE;
-				break;
-			case MAIL_INDEX_SYNC_TYPE_APPEND:
-				i_unreached();
-				break;
-			}
-		}
-
-		if (mail_index_lookup_uid(ctx->view, seq, &uid) < 0) {
-			mail_storage_set_index_error(&ctx->mbox->ibox);
-			return -1;
-		}
-
-		ctx->seq = seq;
-		ctx->uid = uid;
-		if (expunged) {
-			maildir_sync_check_timeouts(ctx->maildir_sync_ctx,
-						    TRUE);
-			(void)maildir_file_do(ctx->mbox, uid,
-					      maildir_expunge, ctx);
-		} else if (flag_changed) {
-			maildir_sync_check_timeouts(ctx->maildir_sync_ctx,
-						    TRUE);
-			(void)maildir_file_do(ctx->mbox, uid,
-					      maildir_sync_flags, ctx);
-		}
-
-		for (i = count; i > 0; i--) {
-			if (++recs[i-1].uid1 > recs[i-1].uid2) {
-				array_delete(&ctx->sync_recs, i-1, 1);
-				recs = array_get_modifiable(&ctx->sync_recs,
-							    &count);
-				if (count == 0) {
-					/* all sync_recs committed */
-					return 0;
-				}
-			}
-		}
-	}
-	return 0;
-}
-
-static int maildir_sync_record(struct maildir_index_sync_context *ctx,
-			       const struct mail_index_sync_rec *sync_rec)
-{
-	struct mail_index_view *view = ctx->view;
-        struct mail_index_sync_rec sync_copy;
-
-	if (sync_rec == NULL) {
-		/* deinit */
-		while (array_count(&ctx->sync_recs) > 0) {
-			if (maildir_sync_record_commit_until(ctx,
-							     (uint32_t)-1) < 0)
-				return -1;
-		}
-		return 0;
-	}
-
-	if (sync_rec->type == MAIL_INDEX_SYNC_TYPE_APPEND)
-		return 0; /* ignore */
-
-	/* convert to sequences to avoid looping through huge holes in
-	   UID range */
-        sync_copy = *sync_rec;
-	if (mail_index_lookup_uid_range(view, sync_rec->uid1,
-					sync_rec->uid2,
-					&sync_copy.uid1,
-					&sync_copy.uid2) < 0) {
-		mail_storage_set_index_error(&ctx->mbox->ibox);
-		return -1;
-	}
-
-	if (sync_copy.uid1 == 0) {
-		/* UIDs were expunged */
-		return 0;
-	}
-
-	while (array_count(&ctx->sync_recs) > 0) {
-		const struct mail_index_sync_rec *rec =
-			array_idx(&ctx->sync_recs, 0);
-
-		i_assert(rec->uid1 <= sync_copy.uid1);
-		if (rec->uid1 == sync_copy.uid1)
-			break;
-
-		if (maildir_sync_record_commit_until(ctx, sync_copy.uid1-1) < 0)
-			return -1;
-	}
-
-	array_append(&ctx->sync_recs, &sync_copy, 1);
-	return 0;
-}
-
-static int maildir_sync_index_records(struct maildir_index_sync_context *ctx)
-{
-	struct mail_index_sync_rec sync_rec;
-	int ret;
-
-	ret = mail_index_sync_next(ctx->sync_ctx, &sync_rec);
-	if (ret <= 0) {
-		if (ret < 0)
-			mail_storage_set_index_error(&ctx->mbox->ibox);
-		return ret;
-	}
-
-	t_array_init(&ctx->sync_recs, 32);
-	do {
-		if (maildir_sync_record(ctx, &sync_rec) < 0)
-			return -1;
-


More information about the dovecot-cvs mailing list