dovecot-1.0: If doing a lockless forced sync, track the UID we'r...

dovecot at dovecot.org dovecot at dovecot.org
Sat Dec 1 10:39:21 EET 2007


details:   http://hg.dovecot.org/dovecot-1.0/rev/4b2bfa37041e
changeset: 5476:4b2bfa37041e
user:      Timo Sirainen <tss at iki.fi>
date:      Sat Dec 01 10:39:11 2007 +0200
description:
If doing a lockless forced sync, track the UID we're trying to find. If we
didn't find it, do a locked sync to find out if it's expunged.

diffstat:

5 files changed, 60 insertions(+), 24 deletions(-)
src/lib-storage/index/maildir/maildir-storage.h |    2 
src/lib-storage/index/maildir/maildir-sync.c    |   56 +++++++++++++++++------
src/lib-storage/index/maildir/maildir-uidlist.c |   21 +++++---
src/lib-storage/index/maildir/maildir-uidlist.h |    3 -
src/lib-storage/index/maildir/maildir-util.c    |    2 

diffs (231 lines):

diff -r cb48e59bd6b6 -r 4b2bfa37041e src/lib-storage/index/maildir/maildir-storage.h
--- a/src/lib-storage/index/maildir/maildir-storage.h	Sat Dec 01 10:31:05 2007 +0200
+++ b/src/lib-storage/index/maildir/maildir-storage.h	Sat Dec 01 10:39:11 2007 +0200
@@ -118,7 +118,7 @@ int maildir_sync_is_synced(struct maildi
 
 struct mailbox_sync_context *
 maildir_storage_sync_init(struct mailbox *box, enum mailbox_sync_flags flags);
-int maildir_storage_sync_force(struct maildir_mailbox *mbox);
+int maildir_storage_sync_force(struct maildir_mailbox *mbox, uint32_t uid);
 
 int maildir_sync_index_begin(struct maildir_mailbox *mbox,
 			     struct maildir_index_sync_context **ctx_r);
diff -r cb48e59bd6b6 -r 4b2bfa37041e src/lib-storage/index/maildir/maildir-sync.c
--- a/src/lib-storage/index/maildir/maildir-sync.c	Sat Dec 01 10:31:05 2007 +0200
+++ b/src/lib-storage/index/maildir/maildir-sync.c	Sat Dec 01 10:39:11 2007 +0200
@@ -218,6 +218,7 @@ struct maildir_sync_context {
 
 	unsigned int move_count, check_count;
 	time_t last_touch, last_notify;
+	enum mailbox_sync_flags flags;
 
 	struct maildir_uidlist_sync_ctx *uidlist_sync_ctx;
         struct maildir_index_sync_context *index_sync_ctx;
@@ -682,7 +683,8 @@ static int maildir_sync_index_records(st
 }
 
 static struct maildir_sync_context *
-maildir_sync_context_new(struct maildir_mailbox *mbox)
+maildir_sync_context_new(struct maildir_mailbox *mbox,
+			 enum mailbox_sync_flags flags)
 {
         struct maildir_sync_context *ctx;
 
@@ -692,6 +694,7 @@ maildir_sync_context_new(struct maildir_
 	ctx->cur_dir = t_strconcat(mbox->path, "/cur", NULL);
 	ctx->last_touch = ioloop_time;
 	ctx->last_notify = ioloop_time;
+	ctx->flags = flags;
 	return ctx;
 }
 
@@ -1335,9 +1338,10 @@ int maildir_sync_index(struct maildir_in
 }
 
 static int maildir_sync_context(struct maildir_sync_context *ctx, bool forced,
-				bool sync_last_commit)
+				uint32_t *find_uid, bool sync_last_commit)
 {
 	enum maildir_uidlist_sync_flags sync_flags;
+	enum maildir_uidlist_rec_flag flags;
 	bool new_changed, cur_changed, full_rescan = FALSE;
 	int ret;
 
@@ -1400,14 +1404,16 @@ static int maildir_sync_context(struct m
 	   problem rarely happens except under high amount of modifications.
 	*/
 
-	if (!cur_changed || forced) {
+	if (!cur_changed) {
 		ctx->partial = TRUE;
 		sync_flags = MAILDIR_UIDLIST_SYNC_PARTIAL;
-		if (forced)
-			sync_flags |= MAILDIR_UIDLIST_SYNC_FORCE;
 	} else {
 		ctx->partial = FALSE;
 		sync_flags = 0;
+		if (forced)
+			sync_flags |= MAILDIR_UIDLIST_SYNC_FORCE;
+		if ((ctx->flags & MAILBOX_SYNC_FLAG_FAST) != 0)
+			sync_flags |= MAILDIR_UIDLIST_SYNC_TRYLOCK;
 	}
 	ret = maildir_uidlist_sync_init(ctx->mbox->uidlist, sync_flags,
 					&ctx->uidlist_sync_ctx);
@@ -1472,19 +1478,41 @@ static int maildir_sync_context(struct m
 		i_assert(maildir_uidlist_is_locked(ctx->mbox->uidlist));
 	}
 
+	if (find_uid != NULL && *find_uid != 0) {
+		if (maildir_uidlist_lookup(ctx->mbox->uidlist, *find_uid,
+					   &flags) == NULL) {
+			/* UID is expunged */
+			*find_uid = 0;
+		} else if ((flags & MAILDIR_UIDLIST_REC_FLAG_NONSYNCED) == 0) {
+			/* we didn't find it, possibly expunged? */
+			*find_uid = 0;
+		}
+	}
+
 	ret = maildir_uidlist_sync_deinit(&ctx->uidlist_sync_ctx);
 	return ret < 0 ? -1 : (full_rescan ? 0 : 1);
 }
 
-int maildir_storage_sync_force(struct maildir_mailbox *mbox)
+int maildir_storage_sync_force(struct maildir_mailbox *mbox, uint32_t uid)
 {
         struct maildir_sync_context *ctx;
 	int ret;
 
-	ctx = maildir_sync_context_new(mbox);
-	ret = maildir_sync_context(ctx, TRUE, FALSE);
+	t_push();
+	ctx = maildir_sync_context_new(mbox, MAILBOX_SYNC_FLAG_FAST);
+	ret = maildir_sync_context(ctx, TRUE, &uid, FALSE);
 	maildir_sync_deinit(ctx);
-	return ret < 0 ? -1 : 0;
+	t_pop();
+
+	if (uid != 0) {
+		/* maybe it's expunged. check again. */
+		t_push();
+		ctx = maildir_sync_context_new(mbox, 0);
+		ret = maildir_sync_context(ctx, TRUE, NULL, FALSE);
+		maildir_sync_deinit(ctx);
+		t_pop();
+	}
+	return ret;
 }
 
 int maildir_sync_last_commit(struct maildir_mailbox *mbox)
@@ -1495,8 +1523,8 @@ int maildir_sync_last_commit(struct mail
 	if (mbox->ibox.commit_log_file_seq == 0)
 		return 0;
 
-	ctx = maildir_sync_context_new(mbox);
-	ret = maildir_sync_context(ctx, FALSE, TRUE);
+	ctx = maildir_sync_context_new(mbox, 0);
+	ret = maildir_sync_context(ctx, FALSE, NULL, TRUE);
 	maildir_sync_deinit(ctx);
 	return ret < 0 ? -1 : 0;
 }
@@ -1513,8 +1541,8 @@ maildir_storage_sync_init(struct mailbox
 	    ioloop_time) {
 		mbox->ibox.sync_last_check = ioloop_time;
 
-		ctx = maildir_sync_context_new(mbox);
-		ret = maildir_sync_context(ctx, FALSE, FALSE);
+		ctx = maildir_sync_context_new(mbox, 0);
+		ret = maildir_sync_context(ctx, FALSE, NULL, FALSE);
 		maildir_sync_deinit(ctx);
 
 		i_assert(!maildir_uidlist_is_locked(mbox->uidlist) ||
@@ -1522,7 +1550,7 @@ maildir_storage_sync_init(struct mailbox
 
 		if (ret == 0) {
 			/* lost some files from new/, see if thery're in cur/ */
-			ret = maildir_storage_sync_force(mbox);
+			ret = maildir_storage_sync_force(mbox, 0);
 		}
 	}
 
diff -r cb48e59bd6b6 -r 4b2bfa37041e src/lib-storage/index/maildir/maildir-uidlist.c
--- a/src/lib-storage/index/maildir/maildir-uidlist.c	Sat Dec 01 10:31:05 2007 +0200
+++ b/src/lib-storage/index/maildir/maildir-uidlist.c	Sat Dec 01 10:39:11 2007 +0200
@@ -566,7 +566,7 @@ maildir_uidlist_lookup(struct maildir_ui
 			return NULL;
 
 		/* the uidlist doesn't exist. */
-		if (maildir_storage_sync_force(uidlist->mbox) < 0)
+		if (maildir_storage_sync_force(uidlist->mbox, uid) < 0)
 			return NULL;
 
 		/* try again */
@@ -804,21 +804,30 @@ int maildir_uidlist_sync_init(struct mai
 {
 	struct maildir_uidlist_sync_ctx *ctx;
 	size_t size;
+	bool locked;
 	int ret;
 
-	if ((sync_flags & MAILDIR_UIDLIST_SYNC_FORCE) == 0) {
+	if ((sync_flags & MAILDIR_UIDLIST_SYNC_TRYLOCK) == 0) {
 		if ((ret = maildir_uidlist_lock(uidlist)) <= 0)
 			return ret;
 	} else {
 		if ((ret = maildir_uidlist_try_lock(uidlist)) < 0)
 			return -1;
-	}
+		if (ret == 0) {
+			/* couldn't lock it */
+			if ((sync_flags & MAILDIR_UIDLIST_SYNC_FORCE) == 0)
+				return 0;
+			/* forcing the lock */
+		}
+	}
+	locked = ret > 0;
 
 	*sync_ctx_r = ctx = i_new(struct maildir_uidlist_sync_ctx, 1);
 	ctx->uidlist = uidlist;
 	ctx->sync_flags = sync_flags;
-	ctx->partial = (sync_flags & MAILDIR_UIDLIST_SYNC_PARTIAL) != 0;
-	ctx->locked = ret > 0;
+	ctx->partial = !locked ||
+		(sync_flags & MAILDIR_UIDLIST_SYNC_PARTIAL) != 0;
+	ctx->locked = locked;
 
 	if (ctx->partial) {
 		/* initially mark all nonsynced */
@@ -846,8 +855,6 @@ maildir_uidlist_sync_next_partial(struct
 
 	/* we'll update uidlist directly */
 	rec = hash_lookup(uidlist->files, filename);
-	i_assert(rec != NULL || UIDLIST_IS_LOCKED(uidlist));
-
 	if (rec == NULL) {
 		if (!ctx->locked) {
 			/* we can't add it, so just ignore it */
diff -r cb48e59bd6b6 -r 4b2bfa37041e src/lib-storage/index/maildir/maildir-uidlist.h
--- a/src/lib-storage/index/maildir/maildir-uidlist.h	Sat Dec 01 10:31:05 2007 +0200
+++ b/src/lib-storage/index/maildir/maildir-uidlist.h	Sat Dec 01 10:39:11 2007 +0200
@@ -7,7 +7,8 @@ struct maildir_uidlist_sync_ctx;
 
 enum maildir_uidlist_sync_flags {
 	MAILDIR_UIDLIST_SYNC_PARTIAL	= 0x01,
-	MAILDIR_UIDLIST_SYNC_FORCE	= 0x02
+	MAILDIR_UIDLIST_SYNC_FORCE	= 0x02,
+	MAILDIR_UIDLIST_SYNC_TRYLOCK	= 0x04
 };
 
 enum maildir_uidlist_rec_flag {
diff -r cb48e59bd6b6 -r 4b2bfa37041e src/lib-storage/index/maildir/maildir-util.c
--- a/src/lib-storage/index/maildir/maildir-util.c	Sat Dec 01 10:31:05 2007 +0200
+++ b/src/lib-storage/index/maildir/maildir-util.c	Sat Dec 01 10:39:11 2007 +0200
@@ -71,7 +71,7 @@ int maildir_file_do(struct maildir_mailb
 		/* file is either renamed or deleted. sync the maildir and
 		   see which one. if file appears to be renamed constantly,
 		   don't try to open it more than 10 times. */
-		if (maildir_storage_sync_force(mbox) < 0)
+		if (maildir_storage_sync_force(mbox, uid) < 0)
 			return -1;
 
 		ret = maildir_file_do_try(mbox, uid, func, context);


More information about the dovecot-cvs mailing list