bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2003-2018 Dovecot authors, see the included COPYING file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "lib.h"
35316602eabbae7dcb86dd74c71e04cce45ba7c7Timo Sirainen#include "ioloop.h"
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen#include "array.h"
26e5bdf37d7d0deed1e2e8483366c83631b9d251Aki Tuomi#include "hook-build.h"
27bc15088a485a8047fca9b0d24d2904c6dda919Timo Sirainen#include "bsearch-insert-pos.h"
ef4d0eafab4d26bba047551db1e23ceff8aa9404Timo Sirainen#include "llist.h"
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen#include "mail-index-private.h"
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen#include "mail-transaction-log-private.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mail-index-transaction-private.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
a102d189881a35d72ac3106a9e7e00577ae69310Aki Tuomistatic ARRAY(hook_mail_index_transaction_created_t *)
2b8ff102f5117f917248f98ccbdc8e6a6af83c87Aki Tuomi hook_mail_index_transaction_created;
2b8ff102f5117f917248f98ccbdc8e6a6af83c87Aki Tuomi
a102d189881a35d72ac3106a9e7e00577ae69310Aki Tuomivoid mail_index_transaction_hook_register(hook_mail_index_transaction_created_t *hook)
2b8ff102f5117f917248f98ccbdc8e6a6af83c87Aki Tuomi{
2b8ff102f5117f917248f98ccbdc8e6a6af83c87Aki Tuomi if (!array_is_created(&hook_mail_index_transaction_created))
2b8ff102f5117f917248f98ccbdc8e6a6af83c87Aki Tuomi i_array_init(&hook_mail_index_transaction_created, 8);
2b8ff102f5117f917248f98ccbdc8e6a6af83c87Aki Tuomi array_append(&hook_mail_index_transaction_created, &hook, 1);
2b8ff102f5117f917248f98ccbdc8e6a6af83c87Aki Tuomi}
2b8ff102f5117f917248f98ccbdc8e6a6af83c87Aki Tuomi
a102d189881a35d72ac3106a9e7e00577ae69310Aki Tuomivoid mail_index_transaction_hook_unregister(hook_mail_index_transaction_created_t *hook)
2b8ff102f5117f917248f98ccbdc8e6a6af83c87Aki Tuomi{
2b8ff102f5117f917248f98ccbdc8e6a6af83c87Aki Tuomi unsigned int idx;
2b8ff102f5117f917248f98ccbdc8e6a6af83c87Aki Tuomi bool found = FALSE;
2b8ff102f5117f917248f98ccbdc8e6a6af83c87Aki Tuomi
2b8ff102f5117f917248f98ccbdc8e6a6af83c87Aki Tuomi i_assert(array_is_created(&hook_mail_index_transaction_created));
2b8ff102f5117f917248f98ccbdc8e6a6af83c87Aki Tuomi for(idx = 0; idx < array_count(&hook_mail_index_transaction_created); idx++) {
a102d189881a35d72ac3106a9e7e00577ae69310Aki Tuomi hook_mail_index_transaction_created_t *const *hook_ptr =
2b8ff102f5117f917248f98ccbdc8e6a6af83c87Aki Tuomi array_idx(&hook_mail_index_transaction_created, idx);
2b8ff102f5117f917248f98ccbdc8e6a6af83c87Aki Tuomi if (*hook_ptr == hook) {
2b8ff102f5117f917248f98ccbdc8e6a6af83c87Aki Tuomi array_delete(&hook_mail_index_transaction_created, idx, 1);
2b8ff102f5117f917248f98ccbdc8e6a6af83c87Aki Tuomi found = TRUE;
2b8ff102f5117f917248f98ccbdc8e6a6af83c87Aki Tuomi break;
2b8ff102f5117f917248f98ccbdc8e6a6af83c87Aki Tuomi }
2b8ff102f5117f917248f98ccbdc8e6a6af83c87Aki Tuomi }
2b8ff102f5117f917248f98ccbdc8e6a6af83c87Aki Tuomi i_assert(found == TRUE);
2b8ff102f5117f917248f98ccbdc8e6a6af83c87Aki Tuomi if (array_count(&hook_mail_index_transaction_created) == 0)
2b8ff102f5117f917248f98ccbdc8e6a6af83c87Aki Tuomi array_free(&hook_mail_index_transaction_created);
2b8ff102f5117f917248f98ccbdc8e6a6af83c87Aki Tuomi}
b346610430690398b8c840006004a2df4aa8ce92Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
48136ae5a0eb49daa44e343553f3688a500307e2Timo Sirainenstruct mail_index_view *
2674b4f0cf8f3c203d8e56b29735f5e267038dafTimo Sirainenmail_index_transaction_get_view(struct mail_index_transaction *t)
48136ae5a0eb49daa44e343553f3688a500307e2Timo Sirainen{
48136ae5a0eb49daa44e343553f3688a500307e2Timo Sirainen return t->view;
48136ae5a0eb49daa44e343553f3688a500307e2Timo Sirainen}
48136ae5a0eb49daa44e343553f3688a500307e2Timo Sirainen
e376693bfa3985232c41df99c7010fca22612c89Timo Sirainenbool mail_index_transaction_is_expunged(struct mail_index_transaction *t,
e376693bfa3985232c41df99c7010fca22612c89Timo Sirainen uint32_t seq)
e376693bfa3985232c41df99c7010fca22612c89Timo Sirainen{
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen struct mail_transaction_expunge_guid key;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen if (!array_is_created(&t->expunges))
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen return FALSE;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen if (t->expunges_nonsorted)
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen mail_index_transaction_sort_expunges(t);
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen key.uid = seq;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen return array_bsearch(&t->expunges, &key,
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen mail_transaction_expunge_guid_cmp) != NULL;
e376693bfa3985232c41df99c7010fca22612c89Timo Sirainen}
e376693bfa3985232c41df99c7010fca22612c89Timo Sirainen
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainenvoid mail_index_transaction_ref(struct mail_index_transaction *t)
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen{
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen t->refcount++;
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen}
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainenvoid mail_index_transaction_unref(struct mail_index_transaction **_t)
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen{
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen struct mail_index_transaction *t = *_t;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen *_t = NULL;
b346610430690398b8c840006004a2df4aa8ce92Timo Sirainen if (--t->refcount > 0)
b346610430690398b8c840006004a2df4aa8ce92Timo Sirainen return;
b346610430690398b8c840006004a2df4aa8ce92Timo Sirainen
741d705983e10046f07ef372b760bcdd169b068aTimo Sirainen mail_index_transaction_reset_v(t);
b346610430690398b8c840006004a2df4aa8ce92Timo Sirainen
ef4d0eafab4d26bba047551db1e23ceff8aa9404Timo Sirainen DLLIST_REMOVE(&t->view->transactions_list, t);
b346610430690398b8c840006004a2df4aa8ce92Timo Sirainen array_free(&t->module_contexts);
b346610430690398b8c840006004a2df4aa8ce92Timo Sirainen mail_index_view_transaction_unref(t->view);
515f81466f673c1b4f72e053f1a9686e6fca6b61Timo Sirainen if (t->latest_view != NULL)
515f81466f673c1b4f72e053f1a9686e6fca6b61Timo Sirainen mail_index_view_close(&t->latest_view);
b346610430690398b8c840006004a2df4aa8ce92Timo Sirainen mail_index_view_close(&t->view);
b346610430690398b8c840006004a2df4aa8ce92Timo Sirainen i_free(t);
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen}
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenuint32_t mail_index_transaction_get_next_uid(struct mail_index_transaction *t)
659fe5d24825b160cae512538088020d97a60239Timo Sirainen{
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen const struct mail_index_header *head_hdr, *hdr;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen unsigned int offset;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen uint32_t next_uid;
7212243efb0d8fa1cd8b2e37b7498323540b9e97Timo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen head_hdr = &t->view->index->map->hdr;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen hdr = &t->view->map->hdr;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen next_uid = t->reset || head_hdr->uid_validity != hdr->uid_validity ?
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen 1 : hdr->next_uid;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (array_is_created(&t->appends) && t->highest_append_uid != 0) {
d1baa8c6f97cdb1b3c2c44a73cc21f9dfc7a963fTimo Sirainen /* get next_uid from appends if they have UIDs. it's possible
d1baa8c6f97cdb1b3c2c44a73cc21f9dfc7a963fTimo Sirainen that some appends have too low UIDs, they'll be caught
d1baa8c6f97cdb1b3c2c44a73cc21f9dfc7a963fTimo Sirainen later. */
d1baa8c6f97cdb1b3c2c44a73cc21f9dfc7a963fTimo Sirainen if (next_uid <= t->highest_append_uid)
d1baa8c6f97cdb1b3c2c44a73cc21f9dfc7a963fTimo Sirainen next_uid = t->highest_append_uid + 1;
7212243efb0d8fa1cd8b2e37b7498323540b9e97Timo Sirainen }
7212243efb0d8fa1cd8b2e37b7498323540b9e97Timo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* see if it's been updated in pre/post header changes */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen offset = offsetof(struct mail_index_header, next_uid);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (t->post_hdr_mask[offset] != 0) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen hdr = (const void *)t->post_hdr_change;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (hdr->next_uid > next_uid)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen next_uid = hdr->next_uid;
7212243efb0d8fa1cd8b2e37b7498323540b9e97Timo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (t->pre_hdr_mask[offset] != 0) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen hdr = (const void *)t->pre_hdr_change;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (hdr->next_uid > next_uid)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen next_uid = hdr->next_uid;
7212243efb0d8fa1cd8b2e37b7498323540b9e97Timo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen return next_uid;
7212243efb0d8fa1cd8b2e37b7498323540b9e97Timo Sirainen}
7212243efb0d8fa1cd8b2e37b7498323540b9e97Timo Sirainen
515f81466f673c1b4f72e053f1a9686e6fca6b61Timo Sirainenvoid mail_index_transaction_lookup_latest_keywords(struct mail_index_transaction *t,
515f81466f673c1b4f72e053f1a9686e6fca6b61Timo Sirainen uint32_t seq,
515f81466f673c1b4f72e053f1a9686e6fca6b61Timo Sirainen ARRAY_TYPE(keyword_indexes) *keywords)
515f81466f673c1b4f72e053f1a9686e6fca6b61Timo Sirainen{
515f81466f673c1b4f72e053f1a9686e6fca6b61Timo Sirainen uint32_t uid, latest_seq;
515f81466f673c1b4f72e053f1a9686e6fca6b61Timo Sirainen
4253a4a66323bc5ff1103af7d7f77fe7c78b9b2bTimo Sirainen /* seq points to the transaction's primary view */
4253a4a66323bc5ff1103af7d7f77fe7c78b9b2bTimo Sirainen mail_index_lookup_uid(t->view, seq, &uid);
4253a4a66323bc5ff1103af7d7f77fe7c78b9b2bTimo Sirainen
4253a4a66323bc5ff1103af7d7f77fe7c78b9b2bTimo Sirainen /* get the latest keywords from the updated index, or fallback to the
4253a4a66323bc5ff1103af7d7f77fe7c78b9b2bTimo Sirainen primary view if the message is already expunged */
515f81466f673c1b4f72e053f1a9686e6fca6b61Timo Sirainen if (t->latest_view == NULL) {
b66d803de86bfb411165b3465b0d9ef64ecfe2a1Timo Sirainen mail_index_refresh(t->view->index);
515f81466f673c1b4f72e053f1a9686e6fca6b61Timo Sirainen t->latest_view = mail_index_view_open(t->view->index);
515f81466f673c1b4f72e053f1a9686e6fca6b61Timo Sirainen }
93d08c32afb545ba32e9a1d973b34756c4b01983Timo Sirainen if (mail_index_lookup_seq(t->latest_view, uid, &latest_seq))
93d08c32afb545ba32e9a1d973b34756c4b01983Timo Sirainen mail_index_lookup_keywords(t->latest_view, latest_seq, keywords);
4253a4a66323bc5ff1103af7d7f77fe7c78b9b2bTimo Sirainen else
4253a4a66323bc5ff1103af7d7f77fe7c78b9b2bTimo Sirainen mail_index_lookup_keywords(t->view, seq, keywords);
515f81466f673c1b4f72e053f1a9686e6fca6b61Timo Sirainen}
515f81466f673c1b4f72e053f1a9686e6fca6b61Timo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenstatic int
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenmail_transaction_log_file_refresh(struct mail_index_transaction *t,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen struct mail_transaction_log_append_ctx *ctx)
7212243efb0d8fa1cd8b2e37b7498323540b9e97Timo Sirainen{
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen struct mail_transaction_log_file *file;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (t->reset) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* Reset the whole index, preserving only indexid. Begin by
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen rotating the log. We don't care if we skip some non-synced
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen transactions. */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (mail_transaction_log_rotate(t->view->index->log, TRUE) < 0)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen return -1;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (!MAIL_INDEX_TRANSACTION_HAS_CHANGES(t)) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* we only wanted to reset */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen return 0;
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen }
659fe5d24825b160cae512538088020d97a60239Timo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen file = t->view->index->log->head;
659fe5d24825b160cae512538088020d97a60239Timo Sirainen
5e88e4624aa6d482b5b195acd2f4e02aeb385f20Timo Sirainen /* make sure we have everything mapped */
5e88e4624aa6d482b5b195acd2f4e02aeb385f20Timo Sirainen if (mail_index_map(t->view->index, MAIL_INDEX_SYNC_HANDLER_HEAD) <= 0)
5e88e4624aa6d482b5b195acd2f4e02aeb385f20Timo Sirainen return -1;
5e88e4624aa6d482b5b195acd2f4e02aeb385f20Timo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen i_assert(file->sync_offset >= file->buffer_offset);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen ctx->new_highest_modseq = file->sync_highest_modseq;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen return 1;
e6f0cbdb1eb604f21a65cd45072febe678187054Timo Sirainen}
e6f0cbdb1eb604f21a65cd45072febe678187054Timo Sirainen
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainenstatic int
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainenmail_index_transaction_commit_real(struct mail_index_transaction *t,
6a0855a04d75bce3c0a2f68517d02f86ae72087fTimo Sirainen uoff_t *commit_size_r,
6a0855a04d75bce3c0a2f68517d02f86ae72087fTimo Sirainen enum mail_index_transaction_change *changes_r)
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen{
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen struct mail_transaction_log *log = t->view->index->log;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen struct mail_transaction_log_append_ctx *ctx;
e169102fb38ce788b76c2a344bee7d77079dea05Timo Sirainen enum mail_transaction_type trans_flags = 0;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen uint32_t log_seq1, log_seq2;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen uoff_t log_offset1, log_offset2;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen int ret;
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen
6a0855a04d75bce3c0a2f68517d02f86ae72087fTimo Sirainen *changes_r = 0;
6a0855a04d75bce3c0a2f68517d02f86ae72087fTimo Sirainen
e169102fb38ce788b76c2a344bee7d77079dea05Timo Sirainen if ((t->flags & MAIL_INDEX_TRANSACTION_FLAG_EXTERNAL) != 0)
e169102fb38ce788b76c2a344bee7d77079dea05Timo Sirainen trans_flags |= MAIL_TRANSACTION_EXTERNAL;
e169102fb38ce788b76c2a344bee7d77079dea05Timo Sirainen if ((t->flags & MAIL_INDEX_TRANSACTION_FLAG_SYNC) != 0)
e169102fb38ce788b76c2a344bee7d77079dea05Timo Sirainen trans_flags |= MAIL_TRANSACTION_SYNC;
e169102fb38ce788b76c2a344bee7d77079dea05Timo Sirainen
e169102fb38ce788b76c2a344bee7d77079dea05Timo Sirainen if (mail_transaction_log_append_begin(log->index, trans_flags, &ctx) < 0)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen return -1;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen ret = mail_transaction_log_file_refresh(t, ctx);
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen#ifdef DEBUG
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen uint64_t expected_highest_modseq =
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen mail_index_transaction_get_highest_modseq(t);
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen#endif
d2470b3dfe91ca07459185384ee25080b42a1636Timo Sirainen if (ret > 0) T_BEGIN {
5e88e4624aa6d482b5b195acd2f4e02aeb385f20Timo Sirainen mail_index_transaction_finish(t);
6a0855a04d75bce3c0a2f68517d02f86ae72087fTimo Sirainen mail_index_transaction_export(t, ctx, changes_r);
d2470b3dfe91ca07459185384ee25080b42a1636Timo Sirainen } T_END;
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen mail_transaction_log_get_head(log, &log_seq1, &log_offset1);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (mail_transaction_log_append_commit(&ctx) < 0 || ret < 0)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen return -1;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen mail_transaction_log_get_head(log, &log_seq2, &log_offset2);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen i_assert(log_seq1 == log_seq2);
406393bc328f056c49df0804f894ac2070aa5846Timo Sirainen
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen#ifdef DEBUG
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen i_assert(expected_highest_modseq == log->head->sync_highest_modseq);
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen#endif
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen
3b426f49d36187895debdda67fff09f97941881cTimo Sirainen if (t->reset) {
3b426f49d36187895debdda67fff09f97941881cTimo Sirainen /* get rid of the old index. it might just confuse readers,
3b426f49d36187895debdda67fff09f97941881cTimo Sirainen especially if it's broken. */
46b823ac3bce2c0f9f0fc73911e48d3a77b04fbeTimo Sirainen i_unlink_if_exists(log->index->filepath);
3b426f49d36187895debdda67fff09f97941881cTimo Sirainen }
3b426f49d36187895debdda67fff09f97941881cTimo Sirainen
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen *commit_size_r = log_offset2 - log_offset1;
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if ((t->flags & MAIL_INDEX_TRANSACTION_FLAG_HIDE) != 0 &&
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen log_offset1 != log_offset2) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* mark the area covered by this transaction hidden */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen mail_index_view_add_hidden_transaction(t->view, log_seq1,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen log_offset1, log_offset2 - log_offset1);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen return 0;
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen}
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainenstatic int mail_index_transaction_commit_v(struct mail_index_transaction *t,
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen struct mail_index_transaction_commit_result *result_r)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen struct mail_index *index = t->view->index;
61ddcdc28f50d9cb9994fcc4ad63f9dff0e80628Timo Sirainen bool changed;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen int ret;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
439942f89a77180719644e7af3752a8329259eb9Timo Sirainen i_assert(t->first_new_seq >
439942f89a77180719644e7af3752a8329259eb9Timo Sirainen mail_index_view_get_messages_count(t->view));
439942f89a77180719644e7af3752a8329259eb9Timo Sirainen
61ddcdc28f50d9cb9994fcc4ad63f9dff0e80628Timo Sirainen changed = MAIL_INDEX_TRANSACTION_HAS_CHANGES(t) || t->reset;
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen ret = !changed ? 0 :
6a0855a04d75bce3c0a2f68517d02f86ae72087fTimo Sirainen mail_index_transaction_commit_real(t, &result_r->commit_size,
6a0855a04d75bce3c0a2f68517d02f86ae72087fTimo Sirainen &result_r->changes_mask);
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen mail_transaction_log_get_head(index->log, &result_r->log_file_seq,
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen &result_r->log_file_offset);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
61ddcdc28f50d9cb9994fcc4ad63f9dff0e80628Timo Sirainen if (ret == 0 && !index->syncing && changed) {
5d1833b98fa85d8061626aa986f38dcbcd70553eTimo Sirainen /* if we're committing a normal transaction, we want to
5d1833b98fa85d8061626aa986f38dcbcd70553eTimo Sirainen have those changes in the index mapping immediately. this
5d1833b98fa85d8061626aa986f38dcbcd70553eTimo Sirainen is especially important when committing cache offset
5d1833b98fa85d8061626aa986f38dcbcd70553eTimo Sirainen updates.
5d1833b98fa85d8061626aa986f38dcbcd70553eTimo Sirainen
5d1833b98fa85d8061626aa986f38dcbcd70553eTimo Sirainen however if we're syncing the index now, the mapping must
5d1833b98fa85d8061626aa986f38dcbcd70553eTimo Sirainen be done later as MAIL_INDEX_SYNC_HANDLER_FILE so that
5d1833b98fa85d8061626aa986f38dcbcd70553eTimo Sirainen expunge handlers get run for the newly expunged messages
5d1833b98fa85d8061626aa986f38dcbcd70553eTimo Sirainen (and sync handlers that require HANDLER_FILE as well). */
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen index->sync_commit_result = result_r;
b66d803de86bfb411165b3465b0d9ef64ecfe2a1Timo Sirainen mail_index_refresh(index);
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen index->sync_commit_result = NULL;
1f68b6db9b8d02b0f4116e42ac82c4aac5579574Timo Sirainen }
1f68b6db9b8d02b0f4116e42ac82c4aac5579574Timo Sirainen
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen mail_index_transaction_unref(&t);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return ret;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainenstatic void mail_index_transaction_rollback_v(struct mail_index_transaction *t)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen mail_index_transaction_unref(&t);
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen}
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen
9404a7b90dcb80d31bd37ee2493f03751acdb1bdTimo Sirainenint mail_index_transaction_commit(struct mail_index_transaction **t)
9404a7b90dcb80d31bd37ee2493f03751acdb1bdTimo Sirainen{
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen struct mail_index_transaction_commit_result result;
9404a7b90dcb80d31bd37ee2493f03751acdb1bdTimo Sirainen
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen return mail_index_transaction_commit_full(t, &result);
9404a7b90dcb80d31bd37ee2493f03751acdb1bdTimo Sirainen}
9404a7b90dcb80d31bd37ee2493f03751acdb1bdTimo Sirainen
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainenint mail_index_transaction_commit_full(struct mail_index_transaction **_t,
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen struct mail_index_transaction_commit_result *result_r)
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen{
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen struct mail_index_transaction *t = *_t;
8872e5c991430f96138a46e36b7f3c2c40d8e5c2Timo Sirainen struct mail_index *index = t->view->index;
8872e5c991430f96138a46e36b7f3c2c40d8e5c2Timo Sirainen bool index_undeleted = t->index_undeleted;
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen if (mail_index_view_is_inconsistent(t->view)) {
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen mail_index_transaction_rollback(_t);
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen return -1;
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen }
491178793199e62320f7bc6292e7b8fd843ae5bcTimo Sirainen if (!index_undeleted && !t->commit_deleted_index) {
8872e5c991430f96138a46e36b7f3c2c40d8e5c2Timo Sirainen if (t->view->index->index_deleted ||
8872e5c991430f96138a46e36b7f3c2c40d8e5c2Timo Sirainen (t->view->index->index_delete_requested &&
8872e5c991430f96138a46e36b7f3c2c40d8e5c2Timo Sirainen !t->view->index->syncing)) {
8872e5c991430f96138a46e36b7f3c2c40d8e5c2Timo Sirainen /* no further changes allowed */
8872e5c991430f96138a46e36b7f3c2c40d8e5c2Timo Sirainen mail_index_transaction_rollback(_t);
8872e5c991430f96138a46e36b7f3c2c40d8e5c2Timo Sirainen return -1;
8872e5c991430f96138a46e36b7f3c2c40d8e5c2Timo Sirainen }
651fc0f1e43fef3e02e0e7b5f498973b05f641d7Timo Sirainen }
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen *_t = NULL;
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(result_r);
8872e5c991430f96138a46e36b7f3c2c40d8e5c2Timo Sirainen if (t->v.commit(t, result_r) < 0)
8872e5c991430f96138a46e36b7f3c2c40d8e5c2Timo Sirainen return -1;
8872e5c991430f96138a46e36b7f3c2c40d8e5c2Timo Sirainen
8872e5c991430f96138a46e36b7f3c2c40d8e5c2Timo Sirainen if (index_undeleted) {
8872e5c991430f96138a46e36b7f3c2c40d8e5c2Timo Sirainen index->index_deleted = FALSE;
8872e5c991430f96138a46e36b7f3c2c40d8e5c2Timo Sirainen index->index_delete_requested = FALSE;
8872e5c991430f96138a46e36b7f3c2c40d8e5c2Timo Sirainen }
8872e5c991430f96138a46e36b7f3c2c40d8e5c2Timo Sirainen return 0;
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen}
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainenvoid mail_index_transaction_rollback(struct mail_index_transaction **_t)
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen{
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen struct mail_index_transaction *t = *_t;
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen *_t = NULL;
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen t->v.rollback(t);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
ab0d9eecd85f74acae18fe88529302e0776cc500Timo Sirainenstatic struct mail_index_transaction_vfuncs trans_vfuncs = {
5e40ed3f0a2c2acddc9b8eab59670c7a850114c5Timo Sirainen mail_index_transaction_reset_v,
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen mail_index_transaction_commit_v,
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen mail_index_transaction_rollback_v
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen};
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainenstruct mail_index_transaction *
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainenmail_index_transaction_begin(struct mail_index_view *view,
db87d16551d1081ada01f787ea21aa3ed1402c31Timo Sirainen enum mail_index_transaction_flags flags)
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen{
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen struct mail_index_transaction *t;
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen /* don't allow syncing view while there's ongoing transactions */
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen mail_index_view_transaction_ref(view);
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen mail_index_view_ref(view);
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen t = i_new(struct mail_index_transaction, 1);
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen t->refcount = 1;
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen t->v = trans_vfuncs;
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen t->view = view;
db87d16551d1081ada01f787ea21aa3ed1402c31Timo Sirainen t->flags = flags;
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen if (view->syncing) {
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen /* transaction view cannot work if new records are being added
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen in two places. make sure it doesn't happen. */
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen t->no_appends = TRUE;
439942f89a77180719644e7af3752a8329259eb9Timo Sirainen t->first_new_seq = (uint32_t)-1;
439942f89a77180719644e7af3752a8329259eb9Timo Sirainen } else {
439942f89a77180719644e7af3752a8329259eb9Timo Sirainen t->first_new_seq =
439942f89a77180719644e7af3752a8329259eb9Timo Sirainen mail_index_view_get_messages_count(t->view) + 1;
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen }
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen
46c31f64b9f0949f00b7819f45b22f2d64b2ea27Timo Sirainen i_array_init(&t->module_contexts,
46c31f64b9f0949f00b7819f45b22f2d64b2ea27Timo Sirainen I_MIN(5, mail_index_module_register.id));
ef4d0eafab4d26bba047551db1e23ceff8aa9404Timo Sirainen DLLIST_PREPEND(&view->transactions_list, t);
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen
2b8ff102f5117f917248f98ccbdc8e6a6af83c87Aki Tuomi if (array_is_created(&hook_mail_index_transaction_created)) {
26e5bdf37d7d0deed1e2e8483366c83631b9d251Aki Tuomi struct hook_build_context *ctx =
26e5bdf37d7d0deed1e2e8483366c83631b9d251Aki Tuomi hook_build_init((void *)&t->v, sizeof(t->v));
a102d189881a35d72ac3106a9e7e00577ae69310Aki Tuomi hook_mail_index_transaction_created_t *const *ptr;
2b8ff102f5117f917248f98ccbdc8e6a6af83c87Aki Tuomi array_foreach(&hook_mail_index_transaction_created, ptr) {
2b8ff102f5117f917248f98ccbdc8e6a6af83c87Aki Tuomi (*ptr)(t);
26e5bdf37d7d0deed1e2e8483366c83631b9d251Aki Tuomi hook_build_update(ctx, t->vlast);
2b8ff102f5117f917248f98ccbdc8e6a6af83c87Aki Tuomi }
26e5bdf37d7d0deed1e2e8483366c83631b9d251Aki Tuomi t->vlast = NULL;
26e5bdf37d7d0deed1e2e8483366c83631b9d251Aki Tuomi hook_build_deinit(&ctx);
2b8ff102f5117f917248f98ccbdc8e6a6af83c87Aki Tuomi }
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen return t;
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen}