[dovecot-cvs] dovecot/src/lib-storage/index/maildir maildir-save.c, 1.56, 1.57 maildir-sync.c, 1.63, 1.64 maildir-uidlist.c, 1.39, 1.40 maildir-uidlist.h, 1.14, 1.15

cras at dovecot.org cras at dovecot.org
Sun Aug 14 22:02:56 EEST 2005


Update of /var/lib/cvs/dovecot/src/lib-storage/index/maildir
In directory talvi:/tmp/cvs-serv9815/lib-storage/index/maildir

Modified Files:
	maildir-save.c maildir-sync.c maildir-uidlist.c 
	maildir-uidlist.h 
Log Message:
Recursive maildir uidlist syncs caused assert crashes. Also did some
cleanups.



Index: maildir-save.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-storage/index/maildir/maildir-save.c,v
retrieving revision 1.56
retrieving revision 1.57
diff -u -d -r1.56 -r1.57
--- maildir-save.c	22 Jul 2005 10:14:58 -0000	1.56
+++ maildir-save.c	14 Aug 2005 19:02:54 -0000	1.57
@@ -361,8 +361,8 @@
 		return -1;
 	}
 
-	ret = maildir_uidlist_lock(ctx->mbox->uidlist);
-	if (ret <= 0) {
+	if (maildir_uidlist_sync_init(ctx->mbox->uidlist, TRUE,
+				      &ctx->uidlist_sync_ctx) <= 0) {
 		/* error or timeout - our transaction is broken */
 		maildir_sync_index_abort(ctx->sync_ctx);
 		maildir_save_commit_abort(ctx, ctx->files);
@@ -378,9 +378,6 @@
 		MAILDIR_UIDLIST_REC_FLAG_RECENT;
 
 	/* move them into new/ */
-	ctx->uidlist_sync_ctx =
-		maildir_uidlist_sync_init(ctx->mbox->uidlist, TRUE);
-
 	ret = 0;
 	for (mf = ctx->files; mf != NULL; mf = mf->next) {
 		t_push();

Index: maildir-sync.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-storage/index/maildir/maildir-sync.c,v
retrieving revision 1.63
retrieving revision 1.64
diff -u -d -r1.63 -r1.64
--- maildir-sync.c	7 Aug 2005 11:41:31 -0000	1.63
+++ maildir-sync.c	14 Aug 2005 19:02:54 -0000	1.64
@@ -1222,17 +1222,16 @@
 			return -1;
 	}
 
-	if ((ret = maildir_uidlist_lock(ctx->mbox->uidlist)) <= 0) {
+	ctx->partial = !cur_changed;
+	ret = maildir_uidlist_sync_init(ctx->mbox->uidlist, ctx->partial,
+					&ctx->uidlist_sync_ctx);
+	if (ret <= 0) {
 		/* failure / timeout. if forced is TRUE, we could still go
 		   forward and check only for renamed files, but is it worth
 		   the trouble? .. */
 		return ret;
 	}
 
-	ctx->partial = !cur_changed;
-	ctx->uidlist_sync_ctx =
-		maildir_uidlist_sync_init(ctx->mbox->uidlist, ctx->partial);
-
 	if (new_changed || cur_changed) {
 		/* if we're going to check cur/ dir our current logic requires
 		   that new/ dir is checked as well. it's a good idea anyway. */
@@ -1254,6 +1253,10 @@
 	}
 
 	if (!ctx->mbox->syncing_commit) {
+		/* NOTE: index syncing here might cause a re-sync due to
+		   files getting lost, so this function might be called
+		   re-entrantly. FIXME: and that breaks in
+		   maildir_uidlist_sync_deinit() */
 		ret = maildir_sync_index_finish(ctx->index_sync_ctx,
 						ctx->partial);
 		if (ret < 0) {

Index: maildir-uidlist.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-storage/index/maildir/maildir-uidlist.c,v
retrieving revision 1.39
retrieving revision 1.40
diff -u -d -r1.39 -r1.40
--- maildir-uidlist.c	12 Jul 2005 12:45:06 -0000	1.39
+++ maildir-uidlist.c	14 Aug 2005 19:02:54 -0000	1.40
@@ -49,6 +49,8 @@
 
 	unsigned int initial_read:1;
 	unsigned int initial_sync:1;
+
+	unsigned int need_rewrite:1;
 };
 
 struct maildir_uidlist_sync_ctx {
@@ -577,20 +579,24 @@
 	}
 }
 
-struct maildir_uidlist_sync_ctx *
-maildir_uidlist_sync_init(struct maildir_uidlist *uidlist, int partial)
+int maildir_uidlist_sync_init(struct maildir_uidlist *uidlist, int partial,
+			      struct maildir_uidlist_sync_ctx **sync_ctx_r)
 {
 	struct maildir_uidlist_sync_ctx *ctx;
 	size_t size;
+	int ret;
 
-	ctx = i_new(struct maildir_uidlist_sync_ctx, 1);
+	if ((ret = maildir_uidlist_lock(uidlist)) <= 0)
+		return ret;
+
+	*sync_ctx_r = ctx = i_new(struct maildir_uidlist_sync_ctx, 1);
 	ctx->uidlist = uidlist;
 	ctx->partial = partial;
 
 	if (partial) {
 		/* initially mark all nonsynced */
                 maildir_uidlist_mark_all(uidlist, TRUE);
-		return ctx;
+		return 1;
 	}
 
 	ctx->record_pool =
@@ -600,7 +606,7 @@
 
 	size = buffer_get_used_size(uidlist->record_buf);
 	ctx->record_buf = buffer_create_dynamic(default_pool, size);
-	return ctx;
+	return 1;
 }
 
 static int
@@ -825,17 +831,26 @@
 	if (!ctx->finished)
 		maildir_uidlist_sync_finish(ctx);
 
-	if (ctx->new_files_count != 0 && !ctx->failed) {
-		t_push();
-		ret = maildir_uidlist_rewrite(ctx->uidlist);
-		t_pop();
-	}
-
 	if (ctx->partial)
 		maildir_uidlist_mark_all(ctx->uidlist, FALSE);
 
-	if (UIDLIST_IS_LOCKED(ctx->uidlist))
-		maildir_uidlist_unlock(ctx->uidlist);
+	if (ctx->uidlist->need_rewrite ||
+	    (ctx->new_files_count != 0 && !ctx->failed)) {
+		if (ctx->uidlist->lock_count > 1) {
+			/* recursive sync. let the root syncing do
+			   the rewrite */
+			ctx->uidlist->need_rewrite = TRUE;
+		} else {
+			t_push();
+			ret = maildir_uidlist_rewrite(ctx->uidlist);
+			t_pop();
+
+			if (ret == 0)
+				ctx->uidlist->need_rewrite = FALSE;
+		}
+	}
+
+	maildir_uidlist_unlock(ctx->uidlist);
 
 	if (ctx->files != NULL)
 		hash_destroy(ctx->files);

Index: maildir-uidlist.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-storage/index/maildir/maildir-uidlist.h,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- maildir-uidlist.h	30 Jun 2005 20:28:20 -0000	1.14
+++ maildir-uidlist.h	14 Aug 2005 19:02:54 -0000	1.15
@@ -3,6 +3,8 @@
 
 #define MAILDIR_UIDLIST_NAME "dovecot-uidlist"
 
+struct maildir_uidlist_sync_ctx;
+
 enum maildir_uidlist_rec_flag {
 	MAILDIR_UIDLIST_REC_FLAG_NEW_DIR	= 0x01,
 	MAILDIR_UIDLIST_REC_FLAG_MOVED		= 0x02,
@@ -37,9 +39,10 @@
 void maildir_uidlist_set_uid_validity(struct maildir_uidlist *uidlist,
 				      uint32_t uid_validity);
 
-/* Sync uidlist with what's actually on maildir. */
-struct maildir_uidlist_sync_ctx *
-maildir_uidlist_sync_init(struct maildir_uidlist *uidlist, int partial);
+/* Sync uidlist with what's actually on maildir. Returns same as
+   maildir_uidlist_lock(). */
+int maildir_uidlist_sync_init(struct maildir_uidlist *uidlist, int partial,
+			      struct maildir_uidlist_sync_ctx **sync_ctx_r);
 /* Returns 1 = ok, -1 = error, 0 = new file and dovecot-uidlist is locked */
 int maildir_uidlist_sync_next_pre(struct maildir_uidlist_sync_ctx *ctx,
 				  const char *filename);



More information about the dovecot-cvs mailing list