[dovecot-cvs] dovecot/src/lib-storage/index/dbox dbox-save.c, 1.16, 1.17 dbox-sync.c, 1.19, 1.20 dbox-uidlist.c, 1.34, 1.35

cras at dovecot.org cras at dovecot.org
Sun Jul 23 18:38:01 EEST 2006


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

Modified Files:
	dbox-save.c dbox-sync.c dbox-uidlist.c 
Log Message:
Fixes for pop3_lock_session=yes. Wasn't as easy as I thought. :)



Index: dbox-save.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-storage/index/dbox/dbox-save.c,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -d -r1.16 -r1.17
--- dbox-save.c	28 Jun 2006 13:10:50 -0000	1.16
+++ dbox-save.c	23 Jul 2006 15:37:56 -0000	1.17
@@ -326,19 +326,7 @@
 
 	i_assert(ctx->finished);
 
-	/* we want the index file to be locked from here until the appends
-	   have been written to transaction log. this is so that the
-	   transaction log gets locked before uidlist, not after */
-	if (mail_index_sync_begin(ctx->mbox->ibox.index, &ctx->index_sync_ctx,
-				  &view, (uint32_t)-1, (uoff_t)-1,
-				  FALSE, FALSE) < 0) {
-		ctx->failed = TRUE;
-		dbox_transaction_save_rollback(ctx);
-		return -1;
-	}
-
-	/* uidlist gets locked here. do it after starting index syncing to
-	   avoid deadlocks */
+	/* uidlist locking is done before index locking. */
 	if (dbox_uidlist_append_get_first_uid(ctx->append_ctx,
 					      &uid, &old_mtime) < 0) {
 		ctx->failed = TRUE;
@@ -370,6 +358,15 @@
 		}
 	}
 
+	/* lock index lock before dropping uidlist lock in _append_commit() */
+	if (mail_index_sync_begin(ctx->mbox->ibox.index, &ctx->index_sync_ctx,
+				  &view, (uint32_t)-1, (uoff_t)-1,
+				  FALSE, FALSE) < 0) {
+		ctx->failed = TRUE;
+		dbox_transaction_save_rollback(ctx);
+		return -1;
+	}
+
 	if (dbox_uidlist_append_commit(ctx->append_ctx, &new_mtime) < 0) {
 		mail_index_sync_rollback(&ctx->index_sync_ctx);
 		i_free(ctx);

Index: dbox-sync.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-storage/index/dbox/dbox-sync.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -d -r1.19 -r1.20
--- dbox-sync.c	28 Jun 2006 13:10:50 -0000	1.19
+++ dbox-sync.c	23 Jul 2006 15:37:56 -0000	1.20
@@ -451,102 +451,139 @@
 	return ret;
 }
 
-int dbox_sync(struct dbox_mailbox *mbox, bool force)
+static int dbox_sync_init(struct dbox_mailbox *mbox,
+			  struct dbox_sync_context *ctx, bool *force)
 {
-	struct dbox_sync_context ctx;
 	const struct mail_index_header *hdr;
-	uint32_t seq, uid_validity, next_uid;
-	uoff_t offset;
 	time_t mtime;
 	int ret;
 
-	memset(&ctx, 0, sizeof(ctx));
-	ctx.mbox = mbox;
+	memset(ctx, 0, sizeof(*ctx));
+	ctx->mbox = mbox;
 
-	/* always start index syncing before uidlist, so we don't get
-	   deadlocks */
-	ret = mail_index_sync_begin(mbox->ibox.index, &ctx.index_sync_ctx,
-				    &ctx.sync_view, (uint32_t)-1, (uoff_t)-1,
+	/* uidlist locking is done before index locking. */
+	if (dbox_uidlist_sync_init(mbox->uidlist, &ctx->uidlist_sync_ctx,
+				   &mtime) < 0)
+		return -1;
+
+	ret = mail_index_sync_begin(mbox->ibox.index, &ctx->index_sync_ctx,
+				    &ctx->sync_view, (uint32_t)-1, (uoff_t)-1,
 				    !mbox->ibox.keep_recent, TRUE);
 	if (ret <= 0) {
 		if (ret < 0)
 			mail_storage_set_index_error(&mbox->ibox);
+		dbox_uidlist_sync_rollback(ctx->uidlist_sync_ctx);
 		return ret;
 	}
-	if (dbox_uidlist_sync_init(mbox->uidlist, &ctx.uidlist_sync_ctx,
-				   &mtime) < 0) {
-		mail_index_sync_rollback(&ctx.index_sync_ctx);
-		return -1;
-	}
 
-	ctx.trans = mail_index_transaction_begin(ctx.sync_view, FALSE, TRUE);
+	ctx->trans = mail_index_transaction_begin(ctx->sync_view, FALSE, TRUE);
 
-	hdr = mail_index_get_header(ctx.sync_view);
+	hdr = mail_index_get_header(ctx->sync_view);
 	if ((uint32_t)mtime != hdr->sync_stamp) {
 		/* indexes aren't synced. we'll do a full sync. */
-		force = TRUE;
+		*force = TRUE;
 	}
+	return 1;
+}
+
+static int dbox_sync_finish(struct dbox_sync_context *ctx, bool force)
+{
+	const struct mail_index_header *hdr;
+	uint32_t seq, uid_validity, next_uid;
+	uoff_t offset;
+	time_t mtime;
+	int ret;
 
 	if (force)
-		ret = dbox_sync_full(&ctx);
+		ret = dbox_sync_full(ctx);
 	else
-		ret = dbox_sync_index(&ctx);
+		ret = dbox_sync_index(ctx);
 
 	if (ret < 0) {
-		mail_index_sync_rollback(&ctx.index_sync_ctx);
-		dbox_uidlist_sync_rollback(ctx.uidlist_sync_ctx);
+		mail_index_sync_rollback(&ctx->index_sync_ctx);
+		dbox_uidlist_sync_rollback(ctx->uidlist_sync_ctx);
 		return -1;
 	}
 
-	uid_validity = dbox_uidlist_sync_get_uid_validity(ctx.uidlist_sync_ctx);
-	next_uid = dbox_uidlist_sync_get_next_uid(ctx.uidlist_sync_ctx);
+	uid_validity = dbox_uidlist_sync_get_uid_validity(ctx->uidlist_sync_ctx);
+	next_uid = dbox_uidlist_sync_get_next_uid(ctx->uidlist_sync_ctx);
 
-	hdr = mail_index_get_header(ctx.sync_view);
+	hdr = mail_index_get_header(ctx->sync_view);
 	if (hdr->uid_validity != uid_validity) {
-		mail_index_update_header(ctx.trans,
+		mail_index_update_header(ctx->trans,
 			offsetof(struct mail_index_header, uid_validity),
 			&uid_validity, sizeof(uid_validity), TRUE);
 	}
 	if (hdr->next_uid != next_uid) {
 		i_assert(next_uid > hdr->next_uid ||
 			 hdr->uid_validity != uid_validity);
-		mail_index_update_header(ctx.trans,
+		mail_index_update_header(ctx->trans,
 			offsetof(struct mail_index_header, next_uid),
 			&next_uid, sizeof(next_uid), FALSE);
 	}
 
-	if (dbox_uidlist_sync_commit(ctx.uidlist_sync_ctx, &mtime) < 0) {
-		mail_index_sync_rollback(&ctx.index_sync_ctx);
+	if (dbox_uidlist_sync_commit(ctx->uidlist_sync_ctx, &mtime) < 0) {
+		mail_index_sync_rollback(&ctx->index_sync_ctx);
 		return -1;
 	}
 
 	if ((uint32_t)mtime != hdr->sync_stamp) {
 		uint32_t sync_stamp = mtime;
 
-		mail_index_update_header(ctx.trans,
+		mail_index_update_header(ctx->trans,
 			offsetof(struct mail_index_header, sync_stamp),
 			&sync_stamp, sizeof(sync_stamp), TRUE);
 	}
 
-	if (mail_index_transaction_commit(&ctx.trans, &seq, &offset) < 0) {
-		mail_storage_set_index_error(&mbox->ibox);
-		mail_index_sync_rollback(&ctx.index_sync_ctx);
+	if (mail_index_transaction_commit(&ctx->trans, &seq, &offset) < 0) {
+		mail_storage_set_index_error(&ctx->mbox->ibox);
+		mail_index_sync_rollback(&ctx->index_sync_ctx);
 		return -1;
 	}
 
 	if (force) {
-		mail_index_sync_rollback(&ctx.index_sync_ctx);
-		/* now that indexes are ok, sync changes from the index */
-		return dbox_sync(mbox, FALSE);
+		mail_index_sync_rollback(&ctx->index_sync_ctx);
 	} else {
-		if (mail_index_sync_commit(&ctx.index_sync_ctx) < 0) {
-			mail_storage_set_index_error(&mbox->ibox);
+		if (mail_index_sync_commit(&ctx->index_sync_ctx) < 0) {
+			mail_storage_set_index_error(&ctx->mbox->ibox);
 			return -1;
 		}
 	}
 	return 0;
 }
 
+int dbox_sync(struct dbox_mailbox *mbox, bool force)
+{
+	struct dbox_sync_context ctx;
+	int ret;
+
+	if ((ret = dbox_sync_init(mbox, &ctx, &force)) <= 0)
+		return ret;
+
+	if ((ret = dbox_sync_finish(&ctx, force)) < 0)
+		return ret;
+
+	if (force) {
+		/* now that indexes are ok, sync changes from the index */
+		force = FALSE;
+		if ((ret = dbox_sync_init(mbox, &ctx, &force)) <= 0)
+			return ret;
+
+		if (force) {
+			mail_storage_set_critical(STORAGE(mbox->storage),
+				"dbox_sync_full(%s) didn't work",
+				mbox->path);
+
+			mail_index_sync_rollback(&ctx.index_sync_ctx);
+			dbox_uidlist_sync_rollback(ctx.uidlist_sync_ctx);
+			return -1;
+		}
+		return dbox_sync_finish(&ctx, FALSE);
+	} else {
+		return 0;
+	}
+}
+
 struct mailbox_sync_context *
 dbox_storage_sync_init(struct mailbox *box, enum mailbox_sync_flags flags)
 {

Index: dbox-uidlist.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-storage/index/dbox/dbox-uidlist.c,v
retrieving revision 1.34
retrieving revision 1.35
diff -u -d -r1.34 -r1.35
--- dbox-uidlist.c	23 Jul 2006 14:20:59 -0000	1.34
+++ dbox-uidlist.c	23 Jul 2006 15:37:56 -0000	1.35
@@ -105,6 +105,8 @@
 	MEMBER(use_excl_lock) FALSE
 };
 
+static int dbox_uidlist_full_rewrite(struct dbox_uidlist *uidlist);
+
 struct dbox_uidlist *dbox_uidlist_init(struct dbox_mailbox *mbox)
 {
 	struct dbox_uidlist *uidlist;
@@ -334,6 +336,11 @@
 	struct stat st;
 	int ret;
 
+	if (uidlist->lock_count > 0 && uidlist->need_full_rewrite) {
+		i_assert(uidlist->mbox->ibox.keep_locked);
+		return 1;
+	}
+
 	if (uidlist->fd != -1) {
 		if (stat(uidlist->path, &st) < 0) {
 			if (errno != ENOENT) {
@@ -475,6 +482,14 @@
 		return;
 	}
 
+	if (uidlist->need_full_rewrite) {
+		i_assert(uidlist->mbox->ibox.keep_locked);
+
+		(void)dbox_uidlist_full_rewrite(uidlist);
+		if (uidlist->lock_fd == -1)
+			return;
+	} 
+
 	(void)file_dotlock_delete(&uidlist->dotlock);
 	uidlist->lock_fd = -1;
 }
@@ -555,6 +570,12 @@
 
 	i_assert(uidlist->lock_fd != -1);
 
+	if (uidlist->lock_count > 1) {
+		i_assert(uidlist->mbox->ibox.keep_locked);
+		uidlist->need_full_rewrite = TRUE;
+		return 0;
+	}
+
 	output = o_stream_create_file(uidlist->lock_fd, default_pool, 0, FALSE);
 
 	t_push();
@@ -645,6 +666,7 @@
 	/* now, finish the uidlist update by renaming the lock file to
 	   uidlist */
 	uidlist->lock_fd = -1;
+	uidlist->lock_count--;
 	if (file_dotlock_replace(&uidlist->dotlock, 0) < 0)
 		return -1;
 



More information about the dovecot-cvs mailing list