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