index-transaction.c revision 6d931bbce16786df431e9ae8201a78a95084316d
a8c5a86d183db25a57bf193c06b41e092ec2e151Timo Sirainen/* Copyright (c) 2003-2010 Dovecot authors, see the included COPYING file */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen#include "lib.h"
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen#include "array.h"
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen#include "index-storage.h"
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen#include "index-mail.h"
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenstatic void index_transaction_free(struct index_transaction_context *t)
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen{
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen mail_cache_view_close(t->cache_view);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen mail_index_view_close(&t->trans_view);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen array_free(&t->mailbox_ctx.module_contexts);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen i_free(t);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen}
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenstatic int
0db42260be85e797aa9909a29b20296996f52e75Timo Sirainenindex_transaction_index_commit(struct mail_index_transaction *index_trans,
0db42260be85e797aa9909a29b20296996f52e75Timo Sirainen struct mail_index_transaction_commit_result *result_r)
0db42260be85e797aa9909a29b20296996f52e75Timo Sirainen{
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen struct index_transaction_context *it =
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen MAIL_STORAGE_CONTEXT(index_trans);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen struct mailbox_transaction_context *t = &it->mailbox_ctx;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen struct index_mailbox_context *ibox = INDEX_STORAGE_CONTEXT(t->box);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen int ret = 0;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (t->save_ctx != NULL) {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (ibox->save_commit_pre(t->save_ctx) < 0) {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen t->save_ctx = NULL;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen ret = -1;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen }
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen }
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen i_assert(it->mail_ref_count == 0);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (ret < 0)
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen it->super.rollback(it->trans);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen else {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (it->super.commit(it->trans, result_r) < 0) {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen mail_storage_set_index_error(t->box);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen ret = -1;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen }
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen }
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (t->save_ctx != NULL)
b49aa341d28c0eec1229e30baa2f89d5bae52ff8Phil Carmody ibox->save_commit_post(t->save_ctx, result_r);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen index_transaction_free(it);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen return ret;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen}
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenstatic void index_transaction_index_rollback(struct mail_index_transaction *t)
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen{
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen struct index_transaction_context *it = MAIL_STORAGE_CONTEXT(t);
16cb5d65265dd0b216542803fd80c4b999ae118eTimo Sirainen struct index_mailbox_context *ibox =
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen INDEX_STORAGE_CONTEXT(it->mailbox_ctx.box);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (it->mailbox_ctx.save_ctx != NULL)
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen ibox->save_rollback(it->mailbox_ctx.save_ctx);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen it->super.rollback(it->trans);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen index_transaction_free(it);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen}
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
0ca3b9cb0f2a322a25ce7f229dc3d3a0b46be17bTimo Sirainenvoid index_transaction_init(struct index_transaction_context *it,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen struct mailbox *box,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen enum mailbox_transaction_flags flags)
7a88e726e7300fb0273cb4e55b43c27fbd90bdbdTimo Sirainen{
16cb5d65265dd0b216542803fd80c4b999ae118eTimo Sirainen enum mail_index_transaction_flags trans_flags;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen i_assert(box->opened);
16cb5d65265dd0b216542803fd80c4b999ae118eTimo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen trans_flags = MAIL_INDEX_TRANSACTION_FLAG_AVOID_FLAG_UPDATES;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if ((flags & MAILBOX_TRANSACTION_FLAG_HIDE) != 0)
16cb5d65265dd0b216542803fd80c4b999ae118eTimo Sirainen trans_flags |= MAIL_INDEX_TRANSACTION_FLAG_HIDE;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if ((flags & MAILBOX_TRANSACTION_FLAG_EXTERNAL) != 0)
16cb5d65265dd0b216542803fd80c4b999ae118eTimo Sirainen trans_flags |= MAIL_INDEX_TRANSACTION_FLAG_EXTERNAL;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if ((flags & MAILBOX_TRANSACTION_FLAG_REFRESH) != 0)
16cb5d65265dd0b216542803fd80c4b999ae118eTimo Sirainen (void)mail_index_refresh(box->index);
56d1345c43bbd28c36b7faa85e4163bd9e874290Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen it->trans = mail_index_transaction_begin(box->view, trans_flags);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen it->mailbox_ctx.box = box;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen array_create(&it->mailbox_ctx.module_contexts, default_pool,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen sizeof(void *), 5);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen it->trans_view = mail_index_transaction_open_updated_view(it->trans);
16cb5d65265dd0b216542803fd80c4b999ae118eTimo Sirainen it->cache_view = mail_cache_view_open(box->cache, it->trans_view);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen it->cache_trans = mail_cache_get_transaction(it->cache_view, it->trans);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen /* set up after mail_cache_get_transaction(), so that we'll still
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen have the cache_trans available in _index_commit() */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen it->super = it->trans->v;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen it->trans->v.commit = index_transaction_index_commit;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen it->trans->v.rollback = index_transaction_index_rollback;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen MODULE_CONTEXT_SET(it->trans, mail_storage_mail_index_module, it);
56aa97d74071f3a2987140c2ff1cfd5a59cb35aaTimo Sirainen}
56aa97d74071f3a2987140c2ff1cfd5a59cb35aaTimo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenstruct mailbox_transaction_context *
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenindex_transaction_begin(struct mailbox *box,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen enum mailbox_transaction_flags flags)
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen{
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen struct index_transaction_context *it;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen it = i_new(struct index_transaction_context, 1);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen index_transaction_init(it, box, flags);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen return &it->mailbox_ctx;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen}
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenint index_transaction_commit(struct mailbox_transaction_context *_t,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen struct mail_transaction_commit_changes *changes_r)
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen{
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen struct index_transaction_context *t =
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen (struct index_transaction_context *)_t;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen struct mailbox *box = _t->box;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen struct mail_index_transaction *itrans = t->trans;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen struct mail_index_transaction_commit_result result;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen int ret;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen memset(changes_r, 0, sizeof(*changes_r));
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen changes_r->pool = pool_alloconly_create(MEMPOOL_GROWING
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen "transaction changes", 512);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen p_array_init(&changes_r->saved_uids, changes_r->pool, 32);
8c909e451d14075c05d90382cf8eebc4e354f569Timo Sirainen _t->changes = changes_r;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen ret = mail_index_transaction_commit_full(&itrans, &result);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen _t = NULL;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (ret < 0 && mail_index_is_deleted(box->index))
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen mailbox_set_deleted(box);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen changes_r->ignored_uid_changes = result.ignored_uid_changes;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen changes_r->ignored_modseq_changes = result.ignored_modseq_changes;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen i_assert(box->transaction_count > 0 ||
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen box->view->transactions == 0);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen return ret;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen}
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenvoid index_transaction_rollback(struct mailbox_transaction_context *_t)
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen{
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen struct index_transaction_context *t =
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen (struct index_transaction_context *)_t;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen struct mailbox *box = _t->box;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen struct mail_index_transaction *itrans = t->trans;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen mail_index_transaction_rollback(&itrans);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen i_assert(box->transaction_count > 0 ||
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen box->view->transactions == 0);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen}
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenvoid index_transaction_set_max_modseq(struct mailbox_transaction_context *_t,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen uint64_t max_modseq,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen ARRAY_TYPE(seq_range) *seqs)
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen{
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen struct index_transaction_context *t =
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen (struct index_transaction_context *)_t;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen mail_index_transaction_set_max_modseq(t->trans, max_modseq, seqs);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen}
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen