dovecot-2.2: mbox: Added support for copy/move/catenate within s...

dovecot at dovecot.org dovecot at dovecot.org
Sun Sep 2 16:48:48 EEST 2012


details:   http://hg.dovecot.org/dovecot-2.2/rev/9e4257061225
changeset: 15008:9e4257061225
user:      Timo Sirainen <tss at iki.fi>
date:      Sun Sep 02 16:48:25 2012 +0300
description:
mbox: Added support for copy/move/catenate within same mailbox.

diffstat:

 src/lib-storage/index/mbox/mbox-lock.c    |  14 +++++++++++
 src/lib-storage/index/mbox/mbox-lock.h    |   2 +
 src/lib-storage/index/mbox/mbox-mail.c    |  13 +++++----
 src/lib-storage/index/mbox/mbox-save.c    |  13 +--------
 src/lib-storage/index/mbox/mbox-storage.c |  39 +++++++++++++++++++++++++-----
 src/lib-storage/index/mbox/mbox-storage.h |   4 ++-
 6 files changed, 60 insertions(+), 25 deletions(-)

diffs (212 lines):

diff -r 96716652b364 -r 9e4257061225 src/lib-storage/index/mbox/mbox-lock.c
--- a/src/lib-storage/index/mbox/mbox-lock.c	Fri Aug 31 15:25:20 2012 +0300
+++ b/src/lib-storage/index/mbox/mbox-lock.c	Sun Sep 02 16:48:25 2012 +0300
@@ -784,6 +784,14 @@
 	bool fcntl_locked;
 	int ret;
 
+	if (lock_type == F_RDLCK && mbox->external_transactions > 0) {
+		/* we have a transaction open that is going to save mails
+		   and apparently also wants to read from the same mailbox
+		   (copy, move, catenate). we need to write lock the mailbox,
+		   since we can't later upgrade a read lock to write lock. */
+		lock_type = F_WRLCK;
+	}
+
 	/* allow only unlock -> shared/exclusive or exclusive -> shared */
 	i_assert(lock_type == F_RDLCK || lock_type == F_WRLCK);
 	i_assert(lock_type == F_RDLCK || mbox->mbox_lock_type != F_RDLCK);
@@ -878,6 +886,12 @@
 	return mbox_unlock_files(&ctx);
 }
 
+unsigned int mbox_get_cur_lock_id(struct mbox_mailbox *mbox)
+{
+	return mbox->mbox_lock_id +
+		(mbox->mbox_excl_locks > 0 ? 1 : 0);
+}
+
 void mbox_dotlock_touch(struct mbox_mailbox *mbox)
 {
 	if (mbox->mbox_dotlock == NULL)
diff -r 96716652b364 -r 9e4257061225 src/lib-storage/index/mbox/mbox-lock.h
--- a/src/lib-storage/index/mbox/mbox-lock.h	Fri Aug 31 15:25:20 2012 +0300
+++ b/src/lib-storage/index/mbox/mbox-lock.h	Sun Sep 02 16:48:25 2012 +0300
@@ -8,6 +8,8 @@
 int ATTR_NOWARN_UNUSED_RESULT
 mbox_unlock(struct mbox_mailbox *mbox, unsigned int lock_id);
 
+unsigned int mbox_get_cur_lock_id(struct mbox_mailbox *mbox);
+
 void mbox_dotlock_touch(struct mbox_mailbox *mbox);
 
 #endif
diff -r 96716652b364 -r 9e4257061225 src/lib-storage/index/mbox/mbox-mail.c
--- a/src/lib-storage/index/mbox/mbox-mail.c	Fri Aug 31 15:25:20 2012 +0300
+++ b/src/lib-storage/index/mbox/mbox-mail.c	Sun Sep 02 16:48:25 2012 +0300
@@ -23,8 +23,8 @@
 	struct mbox_mailbox *mbox = (struct mbox_mailbox *)mail->box;
 
 	if (mbox->mbox_lock_type == F_RDLCK) {
-		if (mbox->mbox_lock_id == t->mbox_lock_id)
-			t->mbox_lock_id = 0;
+		if (mbox->mbox_lock_id == t->read_lock_id)
+			t->read_lock_id = 0;
 		mbox_unlock(mbox, mbox->mbox_lock_id);
 		i_assert(mbox->mbox_lock_type == F_UNLCK);
 	}
@@ -60,11 +60,12 @@
 			mbox_prepare_resync(_mail);
 		}
 		if (mbox->mbox_lock_type == F_UNLCK) {
+			i_assert(t->read_lock_id == 0);
 			sync_flags |= MBOX_SYNC_LOCK_READING;
 			if (mbox_sync(mbox, sync_flags) < 0)
 				return -1;
-			t->mbox_lock_id = mbox->mbox_lock_id;
-			i_assert(t->mbox_lock_id != 0);
+			t->read_lock_id = mbox_get_cur_lock_id(mbox);
+			i_assert(t->read_lock_id != 0);
 
 			/* refresh index file after mbox has been locked to
 			   make sure we get only up-to-date mbox offsets. */
@@ -74,12 +75,12 @@
 			}
 
 			i_assert(mbox->mbox_lock_type != F_UNLCK);
-		} else if (t->mbox_lock_id == 0) {
+		} else if (t->read_lock_id == 0) {
 			/* file is already locked by another transaction, but
 			   we must keep it locked for the entire transaction,
 			   so increase the lock counter. */
 			if (mbox_lock(mbox, mbox->mbox_lock_type,
-				      &t->mbox_lock_id) < 0)
+				      &t->read_lock_id) < 0)
 				i_unreached();
 		}
 
diff -r 96716652b364 -r 9e4257061225 src/lib-storage/index/mbox/mbox-save.c
--- a/src/lib-storage/index/mbox/mbox-save.c	Fri Aug 31 15:25:20 2012 +0300
+++ b/src/lib-storage/index/mbox/mbox-save.c	Sun Sep 02 16:48:25 2012 +0300
@@ -290,17 +290,8 @@
 
 	if (ctx->append_offset == (uoff_t)-1) {
 		/* first appended mail in this transaction */
-		if (mbox->mbox_lock_type != F_WRLCK) {
-			if (mbox->mbox_lock_type == F_RDLCK) {
-				/* FIXME: we shouldn't fail here. it's just
-				   a locking issue that should be possible to
-				   fix.. */
-				mail_storage_set_error(storage,
-					MAIL_ERROR_NOTPOSSIBLE,
-					"Can't copy mails inside same mailbox");
-				return -1;
-			}
-			if (mbox_lock(mbox, F_WRLCK, &t->mbox_lock_id) <= 0)
+		if (t->write_lock_id == 0) {
+			if (mbox_lock(mbox, F_WRLCK, &t->write_lock_id) <= 0)
 				return -1;
 		}
 
diff -r 96716652b364 -r 9e4257061225 src/lib-storage/index/mbox/mbox-storage.c
--- a/src/lib-storage/index/mbox/mbox-storage.c	Fri Aug 31 15:25:20 2012 +0300
+++ b/src/lib-storage/index/mbox/mbox-storage.c	Sun Sep 02 16:48:25 2012 +0300
@@ -691,22 +691,33 @@
 mbox_transaction_begin(struct mailbox *box,
 		       enum mailbox_transaction_flags flags)
 {
+	struct mbox_mailbox *mbox = (struct mbox_mailbox *)box;
 	struct mbox_transaction_context *mt;
 
+	if ((flags & MAILBOX_TRANSACTION_FLAG_EXTERNAL) != 0)
+		mbox->external_transactions++;
+
 	mt = i_new(struct mbox_transaction_context, 1);
 	index_transaction_init(&mt->t, box, flags);
 	return &mt->t;
 }
 
-static void mbox_transaction_unlock(struct mailbox *box, unsigned int lock_id)
+static void
+mbox_transaction_unlock(struct mailbox *box, unsigned int lock_id1,
+			unsigned int lock_id2)
 {
 	struct mbox_mailbox *mbox = (struct mbox_mailbox *)box;
 
-	if (lock_id != 0)
-		mbox_unlock(mbox, lock_id);
+	if (lock_id1 != 0)
+		mbox_unlock(mbox, lock_id1);
+	if (lock_id2 != 0)
+		mbox_unlock(mbox, lock_id2);
 	if (mbox->mbox_global_lock_id == 0) {
 		i_assert(mbox->box.transaction_count > 0 ||
+			 mbox->external_transactions > 0 ||
 			 mbox->mbox_lock_type == F_UNLCK);
+		i_assert(mbox->external_transactions == 0 ||
+			 mbox->mbox_lock_type == F_WRLCK);
 	} else {
 		/* mailbox opened with MAILBOX_FLAG_KEEP_LOCKED */
 		i_assert(mbox->mbox_lock_type == F_WRLCK);
@@ -720,11 +731,18 @@
 	struct mbox_transaction_context *mt =
 		(struct mbox_transaction_context *)t;
 	struct mailbox *box = t->box;
-	unsigned int lock_id = mt->mbox_lock_id;
+	struct mbox_mailbox *mbox = (struct mbox_mailbox *)box;
+	unsigned int read_lock_id = mt->read_lock_id;
+	unsigned int write_lock_id = mt->write_lock_id;
 	int ret;
 
+	if ((t->flags & MAILBOX_TRANSACTION_FLAG_EXTERNAL) != 0) {
+		i_assert(mbox->external_transactions > 0);
+		mbox->external_transactions--;
+	}
+
 	ret = index_transaction_commit(t, changes_r);
-	mbox_transaction_unlock(box, lock_id);
+	mbox_transaction_unlock(box, read_lock_id, write_lock_id);
 	return ret;
 }
 
@@ -734,10 +752,17 @@
 	struct mbox_transaction_context *mt =
 		(struct mbox_transaction_context *)t;
 	struct mailbox *box = t->box;
-	unsigned int lock_id = mt->mbox_lock_id;
+	struct mbox_mailbox *mbox = (struct mbox_mailbox *)box;
+	unsigned int read_lock_id = mt->read_lock_id;
+	unsigned int write_lock_id = mt->write_lock_id;
+
+	if ((t->flags & MAILBOX_TRANSACTION_FLAG_EXTERNAL) != 0) {
+		i_assert(mbox->external_transactions > 0);
+		mbox->external_transactions--;
+	}
 
 	index_transaction_rollback(t);
-	mbox_transaction_unlock(box, lock_id);
+	mbox_transaction_unlock(box, read_lock_id, write_lock_id);
 }
 
 bool mbox_is_backend_readonly(struct mbox_mailbox *mbox)
diff -r 96716652b364 -r 9e4257061225 src/lib-storage/index/mbox/mbox-storage.h
--- a/src/lib-storage/index/mbox/mbox-storage.h	Fri Aug 31 15:25:20 2012 +0300
+++ b/src/lib-storage/index/mbox/mbox-storage.h	Sun Sep 02 16:48:25 2012 +0300
@@ -46,6 +46,7 @@
 	unsigned int mbox_lock_id, mbox_global_lock_id;
 	struct timeout *keep_lock_to;
 	bool mbox_writeonly;
+	unsigned int external_transactions;
 
 	uint32_t mbox_ext_idx, md5hdr_ext_idx;
 	struct mbox_index_header mbox_hdr;
@@ -69,7 +70,8 @@
 	struct mailbox_transaction_context t;
 	union mail_index_transaction_module_context module_ctx;
 
-	unsigned int mbox_lock_id;
+	unsigned int read_lock_id;
+	unsigned int write_lock_id;
 };
 
 extern struct mail_vfuncs mbox_mail_vfuncs;


More information about the dovecot-cvs mailing list