mail-index-transaction.c revision e169102fb38ce788b76c2a344bee7d77079dea05
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen/* Copyright (c) 2003-2012 Dovecot authors, see the included COPYING file */
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainenmail_index_transaction_get_view(struct mail_index_transaction *t)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainenbool mail_index_transaction_is_expunged(struct mail_index_transaction *t,
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainenvoid mail_index_transaction_ref(struct mail_index_transaction *t)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainenvoid mail_index_transaction_unref(struct mail_index_transaction **_t)
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainenuint32_t mail_index_transaction_get_next_uid(struct mail_index_transaction *t)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen const struct mail_index_header *head_hdr, *hdr;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen unsigned int offset;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen next_uid = t->reset || head_hdr->uid_validity != hdr->uid_validity ?
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 /* see if it's been updated in pre/post header changes */
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen offset = offsetof(struct mail_index_header, next_uid);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainenvoid mail_index_transaction_lookup_latest_keywords(struct mail_index_transaction *t,
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen t->latest_view = mail_index_view_open(t->view->index);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (mail_index_lookup_seq(t->view, uid, &latest_seq))
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen mail_index_lookup_keywords(t->view, latest_seq, keywords);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainenmail_transaction_log_file_refresh(struct mail_index_transaction *t,
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)
049da065aa64c1a5ed46eed6cde7382b011612a9Timo Sirainen /* we only wanted to reset */
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 i_assert(file->sync_offset >= file->buffer_offset);
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainen ctx->new_highest_modseq = file->sync_highest_modseq;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainenmail_index_transaction_commit_real(struct mail_index_transaction *t,
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen struct mail_transaction_log *log = t->view->index->log;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if ((t->flags & MAIL_INDEX_TRANSACTION_FLAG_EXTERNAL) != 0)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if ((t->flags & MAIL_INDEX_TRANSACTION_FLAG_SYNC) != 0)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (mail_transaction_log_append_begin(log->index, trans_flags, &ctx) < 0)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen ret = mail_transaction_log_file_refresh(t, ctx);
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 mail_transaction_log_get_head(log, &log_seq2, &log_offset2);
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 if ((t->flags & MAIL_INDEX_TRANSACTION_FLAG_HIDE) != 0 &&
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen /* mark the area covered by this transaction hidden */
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen mail_index_view_add_hidden_transaction(t->view, log_seq1,
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 changed = MAIL_INDEX_TRANSACTION_HAS_CHANGES(t) || t->reset;
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 /* 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 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 Sirainenstatic void mail_index_transaction_rollback_v(struct mail_index_transaction *t)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainenint mail_index_transaction_commit(struct mail_index_transaction **t)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen struct mail_index_transaction_commit_result result;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen return mail_index_transaction_commit_full(t, &result);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainenint mail_index_transaction_commit_full(struct mail_index_transaction **_t,
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen struct mail_index_transaction_commit_result *result_r)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (mail_index_view_is_inconsistent(t->view)) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (!index_undeleted && !t->commit_deleted_index) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen /* no further changes allowed */
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainenvoid mail_index_transaction_rollback(struct mail_index_transaction **_t)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainenstatic struct mail_index_transaction_vfuncs trans_vfuncs = {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainenmail_index_transaction_begin(struct mail_index_view *view,
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen /* don't allow syncing view while there's ongoing transactions */
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 mail_index_view_get_messages_count(t->view) + 1;