mail-index-transaction.c revision 5e88e4624aa6d482b5b195acd2f4e02aeb385f20
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen/* Copyright (c) 2003-2010 Dovecot authors, see the included COPYING file */
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen#include "lib.h"
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen#include "ioloop.h"
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen#include "array.h"
e074ffeaee1ce283bd42f167c6810e3d013f8218Timo Sirainen#include "bsearch-insert-pos.h"
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen#include "mail-index-private.h"
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen#include "mail-transaction-log-private.h"
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen#include "mail-index-transaction-private.h"
08f24237ccc177f5b3a09b24d8a725fa47e1ee32Timo Sirainen
08f24237ccc177f5b3a09b24d8a725fa47e1ee32Timo Sirainen#include <stdlib.h>
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainenvoid (*hook_mail_index_transaction_created)
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen (struct mail_index_transaction *t) = NULL;
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainenstruct mail_index_view *
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainenmail_index_transaction_get_view(struct mail_index_transaction *t)
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen{
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen return t->view;
797de45dcf6e24642ab347d5033beb92034b779dTimo Sirainen}
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainenbool mail_index_transaction_is_expunged(struct mail_index_transaction *t,
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen uint32_t seq)
dba5754de32284b3149ddd5c9bb1701b05707752Timo Sirainen{
dba5754de32284b3149ddd5c9bb1701b05707752Timo Sirainen struct mail_transaction_expunge_guid key;
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen if (!array_is_created(&t->expunges))
dac0b2e5e0f38c6d95ef1a842d891480db580236Timo Sirainen return FALSE;
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen
797de45dcf6e24642ab347d5033beb92034b779dTimo Sirainen if (t->expunges_nonsorted)
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen mail_index_transaction_sort_expunges(t);
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen key.uid = seq;
dac0b2e5e0f38c6d95ef1a842d891480db580236Timo Sirainen return array_bsearch(&t->expunges, &key,
dac0b2e5e0f38c6d95ef1a842d891480db580236Timo Sirainen mail_transaction_expunge_guid_cmp) != NULL;
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen}
dac0b2e5e0f38c6d95ef1a842d891480db580236Timo Sirainen
797de45dcf6e24642ab347d5033beb92034b779dTimo Sirainenvoid mail_index_transaction_ref(struct mail_index_transaction *t)
8afe3f0e832b8b3483b692205bbd59c0110a20fdTimo Sirainen{
08f24237ccc177f5b3a09b24d8a725fa47e1ee32Timo Sirainen t->refcount++;
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen}
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainenvoid mail_index_transaction_unref(struct mail_index_transaction **_t)
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen{
797de45dcf6e24642ab347d5033beb92034b779dTimo Sirainen struct mail_index_transaction *t = *_t;
720692523ece4a549f7c589508d5693ee310f6b3Timo Sirainen
720692523ece4a549f7c589508d5693ee310f6b3Timo Sirainen *_t = NULL;
720692523ece4a549f7c589508d5693ee310f6b3Timo Sirainen if (--t->refcount > 0)
4b8459c6c24b79d4ed5974ab6e3289a3f2b701c0Timo Sirainen return;
720692523ece4a549f7c589508d5693ee310f6b3Timo Sirainen
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen mail_index_transaction_reset_v(t);
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen
08f24237ccc177f5b3a09b24d8a725fa47e1ee32Timo Sirainen array_free(&t->module_contexts);
08f24237ccc177f5b3a09b24d8a725fa47e1ee32Timo Sirainen mail_index_view_transaction_unref(t->view);
08f24237ccc177f5b3a09b24d8a725fa47e1ee32Timo Sirainen mail_index_view_close(&t->view);
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen i_free(t);
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen}
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainenuint32_t mail_index_transaction_get_next_uid(struct mail_index_transaction *t)
8d59f06c9422fa49b538e23ffb06eddb23c6add2Timo Sirainen{
8d59f06c9422fa49b538e23ffb06eddb23c6add2Timo Sirainen const struct mail_index_header *head_hdr, *hdr;
8d59f06c9422fa49b538e23ffb06eddb23c6add2Timo Sirainen unsigned int offset;
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen uint32_t next_uid;
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen head_hdr = &t->view->index->map->hdr;
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen hdr = &t->view->map->hdr;
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen next_uid = t->reset || head_hdr->uid_validity != hdr->uid_validity ?
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen 1 : hdr->next_uid;
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen if (array_is_created(&t->appends) && t->highest_append_uid != 0) {
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen /* get next_uid from appends if they have UIDs. it's possible
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen that some appends have too low UIDs, they'll be caught
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen later. */
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen if (next_uid <= t->highest_append_uid)
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen next_uid = t->highest_append_uid + 1;
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen }
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen /* see if it's been updated in pre/post header changes */
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen offset = offsetof(struct mail_index_header, next_uid);
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen if (t->post_hdr_mask[offset] != 0) {
8d59f06c9422fa49b538e23ffb06eddb23c6add2Timo Sirainen hdr = (const void *)t->post_hdr_change;
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen if (hdr->next_uid > next_uid)
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen next_uid = hdr->next_uid;
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen }
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen if (t->pre_hdr_mask[offset] != 0) {
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen hdr = (const void *)t->pre_hdr_change;
193f5296d2a6b847970c222d8a261b89aae46331Timo Sirainen if (hdr->next_uid > next_uid)
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen next_uid = hdr->next_uid;
193f5296d2a6b847970c222d8a261b89aae46331Timo Sirainen }
08f24237ccc177f5b3a09b24d8a725fa47e1ee32Timo Sirainen return next_uid;
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen}
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainenstatic int
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainenmail_transaction_log_file_refresh(struct mail_index_transaction *t,
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen struct mail_transaction_log_append_ctx *ctx)
08f24237ccc177f5b3a09b24d8a725fa47e1ee32Timo Sirainen{
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen struct mail_transaction_log_file *file;
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen if (t->reset) {
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen /* Reset the whole index, preserving only indexid. Begin by
965e13eea8dc7f1da3769ab0c4667e36d0f33192Timo Sirainen rotating the log. We don't care if we skip some non-synced
08f24237ccc177f5b3a09b24d8a725fa47e1ee32Timo Sirainen transactions. */
08f24237ccc177f5b3a09b24d8a725fa47e1ee32Timo Sirainen if (mail_transaction_log_rotate(t->view->index->log, TRUE) < 0)
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen return -1;
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen if (!MAIL_INDEX_TRANSACTION_HAS_CHANGES(t)) {
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen /* we only wanted to reset */
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen return 0;
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen }
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen }
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen file = t->view->index->log->head;
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen /* make sure we have everything mapped */
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen if (mail_index_map(t->view->index, MAIL_INDEX_SYNC_HANDLER_HEAD) <= 0)
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen return -1;
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen i_assert(file->sync_offset >= file->buffer_offset);
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen ctx->new_highest_modseq = file->sync_highest_modseq;
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen return 1;
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen}
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen
193f5296d2a6b847970c222d8a261b89aae46331Timo Sirainenstatic int
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainenmail_index_transaction_commit_real(struct mail_index_transaction *t,
193f5296d2a6b847970c222d8a261b89aae46331Timo Sirainen uoff_t *commit_size_r)
08f24237ccc177f5b3a09b24d8a725fa47e1ee32Timo Sirainen{
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen struct mail_transaction_log *log = t->view->index->log;
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen bool external = (t->flags & MAIL_INDEX_TRANSACTION_FLAG_EXTERNAL) != 0;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen struct mail_transaction_log_append_ctx *ctx;
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen uint32_t log_seq1, log_seq2;
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen uoff_t log_offset1, log_offset2;
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen int ret;
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen
745f2c7424d88e368eff0a3a7650b352a9d1f0ddTimo Sirainen if (mail_transaction_log_append_begin(log->index, external, &ctx) < 0)
745f2c7424d88e368eff0a3a7650b352a9d1f0ddTimo Sirainen return -1;
745f2c7424d88e368eff0a3a7650b352a9d1f0ddTimo Sirainen ret = mail_transaction_log_file_refresh(t, ctx);
745f2c7424d88e368eff0a3a7650b352a9d1f0ddTimo Sirainen if (ret > 0) {
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen mail_index_transaction_finish(t);
745f2c7424d88e368eff0a3a7650b352a9d1f0ddTimo Sirainen mail_index_transaction_export(t, ctx);
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen }
745f2c7424d88e368eff0a3a7650b352a9d1f0ddTimo Sirainen
745f2c7424d88e368eff0a3a7650b352a9d1f0ddTimo Sirainen mail_transaction_log_get_head(log, &log_seq1, &log_offset1);
745f2c7424d88e368eff0a3a7650b352a9d1f0ddTimo Sirainen if (mail_transaction_log_append_commit(&ctx) < 0 || ret < 0)
745f2c7424d88e368eff0a3a7650b352a9d1f0ddTimo Sirainen return -1;
f05b9dd37f830576ca7d32ec7071bf87906df3d2Timo Sirainen mail_transaction_log_get_head(log, &log_seq2, &log_offset2);
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen i_assert(log_seq1 == log_seq2);
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen if (t->reset) {
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen /* get rid of the old index. it might just confuse readers,
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen especially if it's broken. */
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen if (unlink(log->index->filepath) < 0 && errno != ENOENT)
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen i_error("unlink(%s) failed: %m", log->index->filepath);
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen }
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen *commit_size_r = log_offset2 - log_offset1;
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen
797de45dcf6e24642ab347d5033beb92034b779dTimo Sirainen if ((t->flags & MAIL_INDEX_TRANSACTION_FLAG_HIDE) != 0 &&
dba5754de32284b3149ddd5c9bb1701b05707752Timo Sirainen log_offset1 != log_offset2) {
dba5754de32284b3149ddd5c9bb1701b05707752Timo Sirainen /* mark the area covered by this transaction hidden */
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen mail_index_view_add_hidden_transaction(t->view, log_seq1,
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen log_offset1, log_offset2 - log_offset1);
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen }
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen return 0;
dba5754de32284b3149ddd5c9bb1701b05707752Timo Sirainen}
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainenstatic int mail_index_transaction_commit_v(struct mail_index_transaction *t,
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen struct mail_index_transaction_commit_result *result_r)
20a3870db4f78717574ee94bca1512994391b2abTimo Sirainen{
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen struct mail_index *index = t->view->index;
dba5754de32284b3149ddd5c9bb1701b05707752Timo Sirainen bool changed;
dba5754de32284b3149ddd5c9bb1701b05707752Timo Sirainen int ret;
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen i_assert(t->first_new_seq >
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen mail_index_view_get_messages_count(t->view));
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen
20a3870db4f78717574ee94bca1512994391b2abTimo Sirainen changed = MAIL_INDEX_TRANSACTION_HAS_CHANGES(t) || t->reset;
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen ret = !changed ? 0 :
dba5754de32284b3149ddd5c9bb1701b05707752Timo Sirainen mail_index_transaction_commit_real(t, &result_r->commit_size);
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen mail_transaction_log_get_head(index->log, &result_r->log_file_seq,
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen &result_r->log_file_offset);
dba5754de32284b3149ddd5c9bb1701b05707752Timo Sirainen
dba5754de32284b3149ddd5c9bb1701b05707752Timo Sirainen if (ret == 0 && !index->syncing && changed) {
dba5754de32284b3149ddd5c9bb1701b05707752Timo Sirainen /* if we're committing a normal transaction, we want to
dba5754de32284b3149ddd5c9bb1701b05707752Timo Sirainen have those changes in the index mapping immediately. this
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen is especially important when committing cache offset
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen updates.
dba5754de32284b3149ddd5c9bb1701b05707752Timo Sirainen
dba5754de32284b3149ddd5c9bb1701b05707752Timo Sirainen however if we're syncing the index now, the mapping must
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen be done later as MAIL_INDEX_SYNC_HANDLER_FILE so that
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen expunge handlers get run for the newly expunged messages
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen (and sync handlers that require HANDLER_FILE as well). */
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen index->sync_commit_result = result_r;
8d59f06c9422fa49b538e23ffb06eddb23c6add2Timo Sirainen (void)mail_index_refresh(index);
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen index->sync_commit_result = NULL;
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen }
8d59f06c9422fa49b538e23ffb06eddb23c6add2Timo Sirainen
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen mail_index_transaction_unref(&t);
8d59f06c9422fa49b538e23ffb06eddb23c6add2Timo Sirainen return ret;
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen}
8d59f06c9422fa49b538e23ffb06eddb23c6add2Timo Sirainen
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainenstatic void mail_index_transaction_rollback_v(struct mail_index_transaction *t)
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen{
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen mail_index_transaction_unref(&t);
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen}
a912d084eb8024ce35462c9fd2d50b86b13d8d33Timo Sirainen
a912d084eb8024ce35462c9fd2d50b86b13d8d33Timo Sirainenint mail_index_transaction_commit(struct mail_index_transaction **t)
a912d084eb8024ce35462c9fd2d50b86b13d8d33Timo Sirainen{
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen struct mail_index_transaction_commit_result result;
a912d084eb8024ce35462c9fd2d50b86b13d8d33Timo Sirainen
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen return mail_index_transaction_commit_full(t, &result);
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen}
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainenint mail_index_transaction_commit_full(struct mail_index_transaction **_t,
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen struct mail_index_transaction_commit_result *result_r)
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen{
struct mail_index_transaction *t = *_t;
struct mail_index *index = t->view->index;
bool index_undeleted = t->index_undeleted;
if (mail_index_view_is_inconsistent(t->view)) {
mail_index_transaction_rollback(_t);
return -1;
}
if (!index_undeleted) {
if (t->view->index->index_deleted ||
(t->view->index->index_delete_requested &&
!t->view->index->syncing)) {
/* no further changes allowed */
mail_index_transaction_rollback(_t);
return -1;
}
}
*_t = NULL;
memset(result_r, 0, sizeof(*result_r));
if (t->v.commit(t, result_r) < 0)
return -1;
if (index_undeleted) {
index->index_deleted = FALSE;
index->index_delete_requested = FALSE;
}
return 0;
}
void mail_index_transaction_rollback(struct mail_index_transaction **_t)
{
struct mail_index_transaction *t = *_t;
*_t = NULL;
t->v.rollback(t);
}
static struct mail_index_transaction_vfuncs trans_vfuncs = {
mail_index_transaction_reset_v,
mail_index_transaction_commit_v,
mail_index_transaction_rollback_v
};
struct mail_index_transaction *
mail_index_transaction_begin(struct mail_index_view *view,
enum mail_index_transaction_flags flags)
{
struct mail_index_transaction *t;
/* don't allow syncing view while there's ongoing transactions */
mail_index_view_transaction_ref(view);
mail_index_view_ref(view);
t = i_new(struct mail_index_transaction, 1);
t->refcount = 1;
t->v = trans_vfuncs;
t->view = view;
t->flags = flags;
if (view->syncing) {
/* transaction view cannot work if new records are being added
in two places. make sure it doesn't happen. */
t->no_appends = TRUE;
t->first_new_seq = (uint32_t)-1;
} else {
t->first_new_seq =
mail_index_view_get_messages_count(t->view) + 1;
}
i_array_init(&t->module_contexts,
I_MIN(5, mail_index_module_register.id));
if (hook_mail_index_transaction_created != NULL)
hook_mail_index_transaction_created(t);
return t;
}