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