mail-index-transaction.c revision d2470b3dfe91ca07459185384ee25080b42a1636
76b43e4417bab52e913da39b5f5bc2a130d3f149Timo Sirainen/* Copyright (c) 2003-2010 Dovecot authors, see the included COPYING file */
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainenmail_index_transaction_get_view(struct mail_index_transaction *t)
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainenbool mail_index_transaction_is_expunged(struct mail_index_transaction *t,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid mail_index_transaction_ref(struct mail_index_transaction *t)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid mail_index_transaction_unref(struct mail_index_transaction **_t)
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainenuint32_t mail_index_transaction_get_next_uid(struct mail_index_transaction *t)
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen const struct mail_index_header *head_hdr, *hdr;
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen unsigned int offset;
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen next_uid = t->reset || head_hdr->uid_validity != hdr->uid_validity ?
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 /* see if it's been updated in pre/post header changes */
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen offset = offsetof(struct mail_index_header, next_uid);
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainenmail_transaction_log_file_refresh(struct mail_index_transaction *t,
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)
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen /* we only wanted to reset */
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen /* make sure we have everything mapped */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (mail_index_map(t->view->index, MAIL_INDEX_SYNC_HANDLER_HEAD) <= 0)
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen i_assert(file->sync_offset >= file->buffer_offset);
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen ctx->new_highest_modseq = file->sync_highest_modseq;
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainenmail_index_transaction_commit_real(struct mail_index_transaction *t,
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen struct mail_transaction_log *log = t->view->index->log;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen bool external = (t->flags & MAIL_INDEX_TRANSACTION_FLAG_EXTERNAL) != 0;
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen if (mail_transaction_log_append_begin(log->index, external, &ctx) < 0)
0d658231054332c3f4c04aab0422af649de89a8cTimo Sirainen ret = mail_transaction_log_file_refresh(t, ctx);
45e62043058738e294f89504c319d852e25943ccTimo Sirainen mail_transaction_log_get_head(log, &log_seq1, &log_offset1);
45e62043058738e294f89504c319d852e25943ccTimo Sirainen if (mail_transaction_log_append_commit(&ctx) < 0 || ret < 0)
45e62043058738e294f89504c319d852e25943ccTimo Sirainen mail_transaction_log_get_head(log, &log_seq2, &log_offset2);
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);
95a284736b8b11319a3f575ba249ba2eb7dbac1bTimo Sirainen if ((t->flags & MAIL_INDEX_TRANSACTION_FLAG_HIDE) != 0 &&
95a284736b8b11319a3f575ba249ba2eb7dbac1bTimo Sirainen /* mark the area covered by this transaction hidden */
95a284736b8b11319a3f575ba249ba2eb7dbac1bTimo Sirainen mail_index_view_add_hidden_transaction(t->view, log_seq1,
a4d209d480d453566d331e870b8d0c99af7716c8Timo Sirainenstatic int mail_index_transaction_commit_v(struct mail_index_transaction *t,
a4d209d480d453566d331e870b8d0c99af7716c8Timo Sirainen struct mail_index_transaction_commit_result *result_r)
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen changed = MAIL_INDEX_TRANSACTION_HAS_CHANGES(t) || t->reset;
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 /* 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 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). */
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainenstatic void mail_index_transaction_rollback_v(struct mail_index_transaction *t)
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainenint mail_index_transaction_commit(struct mail_index_transaction **t)
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen struct mail_index_transaction_commit_result result;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen return mail_index_transaction_commit_full(t, &result);
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainenint mail_index_transaction_commit_full(struct mail_index_transaction **_t,
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen struct mail_index_transaction_commit_result *result_r)
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen if (mail_index_view_is_inconsistent(t->view)) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* no further changes allowed */
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainenvoid mail_index_transaction_rollback(struct mail_index_transaction **_t)
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainenstatic struct mail_index_transaction_vfuncs trans_vfuncs = {
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainenmail_index_transaction_begin(struct mail_index_view *view,
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen /* don't allow syncing view while there's ongoing transactions */
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 mail_index_view_get_messages_count(t->view) + 1;