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