index-transaction.c revision 5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (c) 2003-2012 Dovecot authors, see the included COPYING file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "lib.h"
e05a4c4136fec723f019bee8383103080203f127Timo Sirainen#include "array.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "index-storage.h"
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen#include "index-mail.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainenstatic void index_transaction_free(struct mailbox_transaction_context *t)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen if (t->view_pvt != NULL)
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen mail_index_view_close(&t->view_pvt);
128ea07dab8d67124ea74bcc085a478784b6358aTimo Sirainen mail_cache_view_close(&t->cache_view);
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen mail_index_view_close(&t->view);
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen array_free(&t->module_contexts);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_free(t);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainenstatic int
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainenindex_transaction_index_commit(struct mail_index_transaction *index_trans,
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen struct mail_index_transaction_commit_result *result_r)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen struct mailbox_transaction_context *t =
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen MAIL_STORAGE_CONTEXT(index_trans);
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen int ret = 0;
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen
900bb5e316d030cdebff7ee128ce65881dfb27f7Timo Sirainen if (t->nontransactional_changes)
900bb5e316d030cdebff7ee128ce65881dfb27f7Timo Sirainen t->changes->changed = TRUE;
900bb5e316d030cdebff7ee128ce65881dfb27f7Timo Sirainen
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen if (t->save_ctx != NULL) {
1460ef7a18c53216ddb4a94bb62fba96076aae8eTimo Sirainen if (t->box->v.transaction_save_commit_pre(t->save_ctx) < 0) {
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen t->save_ctx = NULL;
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen ret = -1;
900bb5e316d030cdebff7ee128ce65881dfb27f7Timo Sirainen } else {
900bb5e316d030cdebff7ee128ce65881dfb27f7Timo Sirainen t->changes->changed = TRUE;
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen }
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen }
01937f71b3ae0d5b30b813372f44a3e7e86c89dcTimo Sirainen
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen i_assert(t->mail_ref_count == 0);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (ret < 0)
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen t->super.rollback(index_trans);
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen else {
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen if (t->super.commit(index_trans, result_r) < 0) {
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen mail_storage_set_index_error(t->box);
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen ret = -1;
900bb5e316d030cdebff7ee128ce65881dfb27f7Timo Sirainen } else if (result_r->commit_size > 0) {
900bb5e316d030cdebff7ee128ce65881dfb27f7Timo Sirainen /* something was written to the transaction log */
900bb5e316d030cdebff7ee128ce65881dfb27f7Timo Sirainen t->changes->changed = TRUE;
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen }
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen if (t->save_ctx != NULL)
1460ef7a18c53216ddb4a94bb62fba96076aae8eTimo Sirainen t->box->v.transaction_save_commit_post(t->save_ctx, result_r);
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen index_transaction_free(t);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return ret;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainenstatic void
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainenindex_transaction_index_rollback(struct mail_index_transaction *index_trans)
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen{
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen struct mailbox_transaction_context *t =
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen MAIL_STORAGE_CONTEXT(index_trans);
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen if (t->save_ctx != NULL)
1460ef7a18c53216ddb4a94bb62fba96076aae8eTimo Sirainen t->box->v.transaction_save_rollback(t->save_ctx);
01937f71b3ae0d5b30b813372f44a3e7e86c89dcTimo Sirainen
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen i_assert(t->mail_ref_count == 0);
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen t->super.rollback(index_trans);
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen index_transaction_free(t);
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen}
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainenstatic enum mail_index_transaction_flags
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainenindex_transaction_flags_get(enum mailbox_transaction_flags flags)
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen{
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen enum mail_index_transaction_flags itrans_flags;
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen itrans_flags = MAIL_INDEX_TRANSACTION_FLAG_AVOID_FLAG_UPDATES;
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen if ((flags & MAILBOX_TRANSACTION_FLAG_HIDE) != 0)
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen itrans_flags |= MAIL_INDEX_TRANSACTION_FLAG_HIDE;
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen if ((flags & MAILBOX_TRANSACTION_FLAG_EXTERNAL) != 0)
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen itrans_flags |= MAIL_INDEX_TRANSACTION_FLAG_EXTERNAL;
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen if ((flags & MAILBOX_TRANSACTION_FLAG_SYNC) != 0)
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen itrans_flags |= MAIL_INDEX_TRANSACTION_FLAG_SYNC;
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen return itrans_flags;
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen}
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainenvoid index_transaction_init_pvt(struct mailbox_transaction_context *t)
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen{
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen enum mail_index_transaction_flags itrans_flags;
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen if (t->box->view_pvt == NULL || t->itrans_pvt != NULL)
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen return;
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen itrans_flags = index_transaction_flags_get(t->flags);
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen t->itrans_pvt = mail_index_transaction_begin(t->box->view_pvt,
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen itrans_flags);
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen t->view_pvt = mail_index_transaction_open_updated_view(t->itrans_pvt);
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen}
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainenvoid index_transaction_init(struct mailbox_transaction_context *t,
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen struct mailbox *box,
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen enum mailbox_transaction_flags flags)
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen{
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen enum mail_index_transaction_flags itrans_flags;
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen
a341c4cdbd4b93ba479f465ad3f569dc82f57312Timo Sirainen i_assert(box->opened);
013e3b3942e9550fde619a0b3ce6bdd04edc4268Timo Sirainen
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen itrans_flags = index_transaction_flags_get(flags);
9293bf90039454f47e94e4ba3722a775cfa7d25cTimo Sirainen if ((flags & MAILBOX_TRANSACTION_FLAG_REFRESH) != 0)
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen (void)mail_index_refresh(box->index);
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen t->box = box;
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen t->itrans = mail_index_transaction_begin(box->view, itrans_flags);
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen t->view = mail_index_transaction_open_updated_view(t->itrans);
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen array_create(&t->module_contexts, default_pool,
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen sizeof(void *), 5);
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen t->cache_view = mail_cache_view_open(box->cache, t->view);
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen t->cache_trans = mail_cache_get_transaction(t->cache_view, t->itrans);
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen
ab9a91eb05a54f7675e0bf861aca53f417e1980dTimo Sirainen if ((flags & MAILBOX_TRANSACTION_FLAG_NO_CACHE_DEC) != 0)
ab9a91eb05a54f7675e0bf861aca53f417e1980dTimo Sirainen mail_cache_view_update_cache_decisions(t->cache_view, FALSE);
ab9a91eb05a54f7675e0bf861aca53f417e1980dTimo Sirainen
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen /* set up after mail_cache_get_transaction(), so that we'll still
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen have the cache_trans available in _index_commit() */
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen t->super = t->itrans->v;
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen t->itrans->v.commit = index_transaction_index_commit;
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen t->itrans->v.rollback = index_transaction_index_rollback;
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen MODULE_CONTEXT_SET(t->itrans, mail_storage_mail_index_module, t);
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen}
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainenstruct mailbox_transaction_context *
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainenindex_transaction_begin(struct mailbox *box,
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen enum mailbox_transaction_flags flags)
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen{
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen struct mailbox_transaction_context *t;
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen t = i_new(struct mailbox_transaction_context, 1);
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen index_transaction_init(t, box, flags);
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen return t;
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen}
4d2211dac61c615c5bdfd501ea54d46c89d41b0fTimo Sirainen
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainenint index_transaction_commit(struct mailbox_transaction_context *t,
96308127e006bb3b1108093bcf4cc1fd9481cb7aTimo Sirainen struct mail_transaction_commit_changes *changes_r)
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen{
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen struct mailbox *box = t->box;
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen struct mail_index_transaction *itrans = t->itrans;
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen struct mail_index_transaction_commit_result result;
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen int ret = 0;
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen
96308127e006bb3b1108093bcf4cc1fd9481cb7aTimo Sirainen memset(changes_r, 0, sizeof(*changes_r));
6d931bbce16786df431e9ae8201a78a95084316dTimo Sirainen changes_r->pool = pool_alloconly_create(MEMPOOL_GROWING
6d931bbce16786df431e9ae8201a78a95084316dTimo Sirainen "transaction changes", 512);
96308127e006bb3b1108093bcf4cc1fd9481cb7aTimo Sirainen p_array_init(&changes_r->saved_uids, changes_r->pool, 32);
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen t->changes = changes_r;
4d2211dac61c615c5bdfd501ea54d46c89d41b0fTimo Sirainen
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen if (t->itrans_pvt != NULL)
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen ret = mail_index_transaction_commit(&t->itrans_pvt);
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen if (mail_index_transaction_commit_full(&itrans, &result) < 0)
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen ret = -1;
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen t = NULL;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen if (ret < 0 && mail_index_is_deleted(box->index))
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen mailbox_set_deleted(box);
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen changes_r->ignored_modseq_changes = result.ignored_modseq_changes;
741d705983e10046f07ef372b760bcdd169b068aTimo Sirainen return ret;
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen}
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainenvoid index_transaction_rollback(struct mailbox_transaction_context *t)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen struct mail_index_transaction *itrans = t->itrans;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen if (t->itrans_pvt != NULL)
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen mail_index_transaction_rollback(&t->itrans_pvt);
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen mail_index_transaction_rollback(&itrans);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}