index-transaction.c revision 900bb5e316d030cdebff7ee128ce65881dfb27f7
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen/* Copyright (c) 2003-2012 Dovecot authors, see the included COPYING file */
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen#include "lib.h"
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen#include "array.h"
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen#include "index-storage.h"
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen#include "index-mail.h"
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainenstatic void index_transaction_free(struct mailbox_transaction_context *t)
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen{
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen mail_cache_view_close(&t->cache_view);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen mail_index_view_close(&t->view);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen array_free(&t->module_contexts);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen i_free(t);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen}
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainenstatic int
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainenindex_transaction_index_commit(struct mail_index_transaction *index_trans,
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen struct mail_index_transaction_commit_result *result_r)
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen{
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen struct mailbox_transaction_context *t =
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen MAIL_STORAGE_CONTEXT(index_trans);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen int ret = 0;
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen if (t->nontransactional_changes)
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen t->changes->changed = TRUE;
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen if (t->save_ctx != NULL) {
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen if (t->box->v.transaction_save_commit_pre(t->save_ctx) < 0) {
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen t->save_ctx = NULL;
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen ret = -1;
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen } else {
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen t->changes->changed = TRUE;
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen }
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen }
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen i_assert(t->mail_ref_count == 0);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen if (ret < 0)
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen t->super.rollback(index_trans);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen else {
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen if (t->super.commit(index_trans, result_r) < 0) {
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen mail_storage_set_index_error(t->box);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen ret = -1;
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen } else if (result_r->commit_size > 0) {
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen /* something was written to the transaction log */
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen t->changes->changed = TRUE;
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen }
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen }
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen if (t->save_ctx != NULL)
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen t->box->v.transaction_save_commit_post(t->save_ctx, result_r);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen index_transaction_free(t);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen return ret;
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen}
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainenstatic void
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainenindex_transaction_index_rollback(struct mail_index_transaction *index_trans)
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen{
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen struct mailbox_transaction_context *t =
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen MAIL_STORAGE_CONTEXT(index_trans);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen if (t->save_ctx != NULL)
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen t->box->v.transaction_save_rollback(t->save_ctx);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen i_assert(t->mail_ref_count == 0);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen t->super.rollback(index_trans);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen index_transaction_free(t);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen}
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainenvoid index_transaction_init(struct mailbox_transaction_context *t,
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen struct mailbox *box,
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen enum mailbox_transaction_flags flags)
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen{
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen enum mail_index_transaction_flags trans_flags;
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen i_assert(box->opened);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen trans_flags = MAIL_INDEX_TRANSACTION_FLAG_AVOID_FLAG_UPDATES;
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen if ((flags & MAILBOX_TRANSACTION_FLAG_HIDE) != 0)
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen trans_flags |= MAIL_INDEX_TRANSACTION_FLAG_HIDE;
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen if ((flags & MAILBOX_TRANSACTION_FLAG_EXTERNAL) != 0)
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen trans_flags |= MAIL_INDEX_TRANSACTION_FLAG_EXTERNAL;
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen if ((flags & MAILBOX_TRANSACTION_FLAG_REFRESH) != 0)
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen (void)mail_index_refresh(box->index);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen t->box = box;
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen t->itrans = mail_index_transaction_begin(box->view, trans_flags);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen t->view = mail_index_transaction_open_updated_view(t->itrans);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen array_create(&t->module_contexts, default_pool,
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen sizeof(void *), 5);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen t->cache_view = mail_cache_view_open(box->cache, t->view);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen t->cache_trans = mail_cache_get_transaction(t->cache_view, t->itrans);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen if ((flags & MAILBOX_TRANSACTION_FLAG_NO_CACHE_DEC) != 0)
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen mail_cache_view_update_cache_decisions(t->cache_view, FALSE);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen /* set up after mail_cache_get_transaction(), so that we'll still
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen have the cache_trans available in _index_commit() */
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen t->super = t->itrans->v;
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen t->itrans->v.commit = index_transaction_index_commit;
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen t->itrans->v.rollback = index_transaction_index_rollback;
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen MODULE_CONTEXT_SET(t->itrans, mail_storage_mail_index_module, t);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen}
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainenstruct mailbox_transaction_context *
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainenindex_transaction_begin(struct mailbox *box,
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen enum mailbox_transaction_flags flags)
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen{
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen struct mailbox_transaction_context *t;
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen t = i_new(struct mailbox_transaction_context, 1);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen index_transaction_init(t, box, flags);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen return t;
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen}
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainenint index_transaction_commit(struct mailbox_transaction_context *t,
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen struct mail_transaction_commit_changes *changes_r)
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen{
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen struct mailbox *box = t->box;
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen struct mail_index_transaction *itrans = t->itrans;
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen struct mail_index_transaction_commit_result result;
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen int ret;
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen memset(changes_r, 0, sizeof(*changes_r));
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen changes_r->pool = pool_alloconly_create(MEMPOOL_GROWING
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen "transaction changes", 512);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen p_array_init(&changes_r->saved_uids, changes_r->pool, 32);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen t->changes = changes_r;
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen ret = mail_index_transaction_commit_full(&itrans, &result);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen t = NULL;
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen if (ret < 0 && mail_index_is_deleted(box->index))
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen mailbox_set_deleted(box);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen changes_r->ignored_modseq_changes = result.ignored_modseq_changes;
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen return ret;
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen}
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainenvoid index_transaction_rollback(struct mailbox_transaction_context *t)
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen{
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen struct mail_index_transaction *itrans = t->itrans;
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen mail_index_transaction_rollback(&itrans);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen}
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen