mbox-transaction.c revision 398d66217c5916b14485714954c14cf8af0c8547
2ronwalf/* Copyright (c) 2004-2009 Dovecot authors, see the included COPYING file */
2ronwalf
2ronwalf#include "lib.h"
2ronwalf#include "array.h"
2ronwalf#include "mbox-storage.h"
2ronwalf#include "mbox-lock.h"
2ronwalf#include "mbox-sync-private.h"
2ronwalf
2ronwalfstatic void (*next_hook_mail_index_transaction_created)
2ronwalf (struct mail_index_transaction *t) = NULL;
2ronwalf
2ronwalfstatic int mbox_transaction_commit(struct mail_index_transaction *t,
2ronwalf uint32_t *log_file_seq_r,
2ronwalf uoff_t *log_file_offset_r)
2ronwalf{
2ronwalf struct mbox_transaction_context *mt = MAIL_STORAGE_CONTEXT(t);
2ronwalf struct mbox_mailbox *mbox = (struct mbox_mailbox *)mt->ictx.ibox;
2ronwalf unsigned int lock_id = mt->mbox_lock_id;
2ronwalf bool mails_saved;
2ronwalf int ret = 0;
2ronwalf
2ronwalf if (mt->save_ctx != NULL)
2ronwalf ret = mbox_transaction_save_commit(mt->save_ctx);
2ronwalf mails_saved = mt->mails_saved;
2ronwalf
2ronwalf if (ret < 0)
2ronwalf index_transaction_finish_rollback(&mt->ictx);
2ronwalf else {
2ronwalf if (index_transaction_finish_commit(&mt->ictx, log_file_seq_r,
2ronwalf log_file_offset_r) < 0)
2ronwalf ret = -1;
2ronwalf }
2ronwalf
2ronwalf /* transaction is destroyed now. */
2ronwalf mt = NULL;
2ronwalf
2ronwalf if (lock_id != 0 && mbox->mbox_lock_type != F_WRLCK) {
2ronwalf /* unlock before writing any changes */
2ronwalf (void)mbox_unlock(mbox, lock_id);
2ronwalf lock_id = 0;
2ronwalf }
2ronwalf
2ronwalf if (ret == 0 && mails_saved) {
2ronwalf /* after saving mails we want to update the last-uid */
2ronwalf if (mbox_sync(mbox, MBOX_SYNC_HEADER | MBOX_SYNC_REWRITE) < 0)
2ronwalf ret = -1;
2ronwalf }
2ronwalf
2ronwalf if (lock_id != 0) {
2ronwalf if (mbox_unlock(mbox, lock_id) < 0)
2ronwalf ret = -1;
2ronwalf }
2ronwalf if (mbox->mbox_global_lock_id == 0) {
i_assert(mbox->ibox.box.transaction_count > 0 ||
mbox->mbox_lock_type == F_UNLCK);
} else {
i_assert(mbox->mbox_lock_type == F_WRLCK);
}
return ret;
}
static void mbox_transaction_rollback(struct mail_index_transaction *t)
{
struct mbox_transaction_context *mt = MAIL_STORAGE_CONTEXT(t);
struct mbox_mailbox *mbox = (struct mbox_mailbox *)mt->ictx.ibox;
if (mt->save_ctx != NULL)
mbox_transaction_save_rollback(mt->save_ctx);
if (mt->mbox_lock_id != 0)
(void)mbox_unlock(mbox, mt->mbox_lock_id);
index_transaction_finish_rollback(&mt->ictx);
i_assert(mbox->ibox.box.transaction_count > 0 ||
mbox->mbox_lock_type == F_UNLCK);
}
static void mbox_transaction_created(struct mail_index_transaction *t)
{
struct mailbox *box = MAIL_STORAGE_CONTEXT(t->view);
/* index can be for mailbox list index, in which case box=NULL */
if (box != NULL && strcmp(box->storage->name, MBOX_STORAGE_NAME) == 0) {
struct mbox_mailbox *mbox = (struct mbox_mailbox *)box;
struct mbox_transaction_context *mt;
mt = i_new(struct mbox_transaction_context, 1);
mt->ictx.trans = t;
index_transaction_init(&mt->ictx, &mbox->ibox);
t->v.commit = mbox_transaction_commit;
t->v.rollback = mbox_transaction_rollback;
MODULE_CONTEXT_SET(t, mail_storage_mail_index_module, mt);
}
if (next_hook_mail_index_transaction_created != NULL)
next_hook_mail_index_transaction_created(t);
}
void mbox_transaction_class_init(void)
{
next_hook_mail_index_transaction_created =
hook_mail_index_transaction_created;
hook_mail_index_transaction_created = mbox_transaction_created;
}
void mbox_transaction_class_deinit(void)
{
i_assert(hook_mail_index_transaction_created ==
mbox_transaction_created);
hook_mail_index_transaction_created =
next_hook_mail_index_transaction_created;
}