bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2003-2018 Dovecot authors, see the included COPYING file */
d48a2f3288eba53dd10d9d8029ec583d78a977e0Timo Sirainen
d48a2f3288eba53dd10d9d8029ec583d78a977e0Timo Sirainen#include "lib.h"
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen#include "array.h"
d48a2f3288eba53dd10d9d8029ec583d78a977e0Timo Sirainen#include "write-full.h"
d48a2f3288eba53dd10d9d8029ec583d78a977e0Timo Sirainen#include "mail-index-private.h"
d48a2f3288eba53dd10d9d8029ec583d78a977e0Timo Sirainen#include "mail-transaction-log-private.h"
d48a2f3288eba53dd10d9d8029ec583d78a977e0Timo Sirainen
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainenvoid mail_transaction_log_append_add(struct mail_transaction_log_append_ctx *ctx,
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen enum mail_transaction_type type,
40a5aeebf6b4858b93f0ddff0bf12fba769cf903Timo Sirainen const void *data, size_t size)
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen{
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen struct mail_transaction_header hdr;
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen i_assert((type & MAIL_TRANSACTION_TYPE_MASK) != 0);
40a5aeebf6b4858b93f0ddff0bf12fba769cf903Timo Sirainen i_assert((size % 4) == 0);
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen
40a5aeebf6b4858b93f0ddff0bf12fba769cf903Timo Sirainen if (size == 0)
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen return;
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&hdr);
e169102fb38ce788b76c2a344bee7d77079dea05Timo Sirainen hdr.type = type | ctx->trans_flags;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen if (type == MAIL_TRANSACTION_EXPUNGE ||
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen type == MAIL_TRANSACTION_EXPUNGE_GUID)
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen hdr.type |= MAIL_TRANSACTION_EXPUNGE_PROT;
e169102fb38ce788b76c2a344bee7d77079dea05Timo Sirainen if (type == MAIL_TRANSACTION_BOUNDARY)
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen hdr.type |= MAIL_TRANSACTION_EXTERNAL;
40a5aeebf6b4858b93f0ddff0bf12fba769cf903Timo Sirainen hdr.size = sizeof(hdr) + size;
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen hdr.size = mail_index_uint32_to_offset(hdr.size);
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen buffer_append(ctx->output, &hdr, sizeof(hdr));
40a5aeebf6b4858b93f0ddff0bf12fba769cf903Timo Sirainen buffer_append(ctx->output, data, size);
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen mail_transaction_update_modseq(&hdr, data, &ctx->new_highest_modseq,
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen MAIL_TRANSACTION_LOG_HDR_VERSION(&ctx->log->head->hdr));
bd503f12eb667df389a99162f567bd8785798f55Timo Sirainen ctx->transaction_count++;
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen}
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenstatic int
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenlog_buffer_move_to_memory(struct mail_transaction_log_append_ctx *ctx)
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen{
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen struct mail_transaction_log_file *file = ctx->log->head;
0d0451206a91e9f96e522075dce28a89adc2325dTimo Sirainen
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen /* first we need to truncate this latest write so that log syncing
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen doesn't break */
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen if (ftruncate(file->fd, file->sync_offset) < 0) {
ab11c996ff754af701b03c63db20e434469064e0Timo Sirainen mail_index_file_set_syscall_error(ctx->log->index,
41e09cca158ab614961e03deac60f12a58235cd3Timo Sirainen file->filepath,
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen "ftruncate()");
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen }
0d0451206a91e9f96e522075dce28a89adc2325dTimo Sirainen
ab11c996ff754af701b03c63db20e434469064e0Timo Sirainen if (mail_index_move_to_memory(ctx->log->index) < 0)
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen return -1;
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen i_assert(MAIL_TRANSACTION_LOG_FILE_IN_MEMORY(file));
0d0451206a91e9f96e522075dce28a89adc2325dTimo Sirainen
ab11c996ff754af701b03c63db20e434469064e0Timo Sirainen i_assert(file->buffer_offset + file->buffer->used == file->sync_offset);
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen buffer_append_buf(file->buffer, ctx->output, 0, (size_t)-1);
0d0451206a91e9f96e522075dce28a89adc2325dTimo Sirainen file->sync_offset = file->buffer_offset + file->buffer->used;
d48a2f3288eba53dd10d9d8029ec583d78a977e0Timo Sirainen return 0;
d48a2f3288eba53dd10d9d8029ec583d78a977e0Timo Sirainen}
d48a2f3288eba53dd10d9d8029ec583d78a977e0Timo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenstatic int log_buffer_write(struct mail_transaction_log_append_ctx *ctx)
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen{
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen struct mail_transaction_log_file *file = ctx->log->head;
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen
ab11c996ff754af701b03c63db20e434469064e0Timo Sirainen if (ctx->output->used == 0)
ab11c996ff754af701b03c63db20e434469064e0Timo Sirainen return 0;
ab11c996ff754af701b03c63db20e434469064e0Timo Sirainen
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen if (MAIL_TRANSACTION_LOG_FILE_IN_MEMORY(file)) {
6f90ce01176bd920609d9d12e6419b9ba27c1359Timo Sirainen if (file->buffer == NULL) {
6f90ce01176bd920609d9d12e6419b9ba27c1359Timo Sirainen file->buffer = buffer_create_dynamic(default_pool, 4096);
6f90ce01176bd920609d9d12e6419b9ba27c1359Timo Sirainen file->buffer_offset = sizeof(file->hdr);
6f90ce01176bd920609d9d12e6419b9ba27c1359Timo Sirainen }
a23197a5232f34121b1d32b73f2279c5d2f4491cTimo Sirainen buffer_append_buf(file->buffer, ctx->output, 0, (size_t)-1);
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen file->sync_offset = file->buffer_offset + file->buffer->used;
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen return 0;
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen }
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen
bd503f12eb667df389a99162f567bd8785798f55Timo Sirainen if (write_full(file->fd, ctx->output->data, ctx->output->used) < 0) {
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen /* write failure, fallback to in-memory indexes. */
ab11c996ff754af701b03c63db20e434469064e0Timo Sirainen mail_index_file_set_syscall_error(ctx->log->index,
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen file->filepath,
bd503f12eb667df389a99162f567bd8785798f55Timo Sirainen "write_full()");
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen return log_buffer_move_to_memory(ctx);
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen }
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen i_assert(!ctx->sync_includes_this ||
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen file->sync_offset + ctx->output->used ==
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen file->max_tail_offset);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
66ecc94150cbce23aad3240135e0782e0a74d479Timo Sirainen if ((ctx->want_fsync &&
b780aa272b742a43579cdb523cc79cc8d4521306Timo Sirainen file->log->index->fsync_mode != FSYNC_MODE_NEVER) ||
b780aa272b742a43579cdb523cc79cc8d4521306Timo Sirainen file->log->index->fsync_mode == FSYNC_MODE_ALWAYS) {
9b5a8e766112d24c12499aca85da5ddf24baad25Timo Sirainen if (fdatasync(file->fd) < 0) {
ab11c996ff754af701b03c63db20e434469064e0Timo Sirainen mail_index_file_set_syscall_error(ctx->log->index,
9b5a8e766112d24c12499aca85da5ddf24baad25Timo Sirainen file->filepath,
9b5a8e766112d24c12499aca85da5ddf24baad25Timo Sirainen "fdatasync()");
9b5a8e766112d24c12499aca85da5ddf24baad25Timo Sirainen return log_buffer_move_to_memory(ctx);
9b5a8e766112d24c12499aca85da5ddf24baad25Timo Sirainen }
9b5a8e766112d24c12499aca85da5ddf24baad25Timo Sirainen }
9b5a8e766112d24c12499aca85da5ddf24baad25Timo Sirainen
d6370c8138546e27119c6da3d482b7ea7c0b2289Timo Sirainen if (file->mmap_base == NULL && file->buffer != NULL) {
d8a786d2069fab818d0b62cd3eaa3ed08fe7c620Timo Sirainen /* we're reading from a file. avoid re-reading the data that
d8a786d2069fab818d0b62cd3eaa3ed08fe7c620Timo Sirainen we just wrote. this is also important for some NFS clients,
d8a786d2069fab818d0b62cd3eaa3ed08fe7c620Timo Sirainen which for some reason sometimes can't read() this data we
d8a786d2069fab818d0b62cd3eaa3ed08fe7c620Timo Sirainen just wrote in the same process */
d8a786d2069fab818d0b62cd3eaa3ed08fe7c620Timo Sirainen i_assert(file->buffer_offset +
d8a786d2069fab818d0b62cd3eaa3ed08fe7c620Timo Sirainen file->buffer->used == file->sync_offset);
d8a786d2069fab818d0b62cd3eaa3ed08fe7c620Timo Sirainen buffer_append(file->buffer, ctx->output->data,
d8a786d2069fab818d0b62cd3eaa3ed08fe7c620Timo Sirainen ctx->output->used);
d8a786d2069fab818d0b62cd3eaa3ed08fe7c620Timo Sirainen }
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen file->sync_offset += ctx->output->used;
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen return 0;
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen}
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainenstatic void
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenlog_append_sync_offset_if_needed(struct mail_transaction_log_append_ctx *ctx)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen{
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen struct mail_transaction_log_file *file = ctx->log->head;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen struct mail_transaction_header_update *u;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen struct mail_transaction_header *hdr;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen uint32_t offset;
02752bc8d64df8cd361f464e55422f7b3f2f143eTimo Sirainen buffer_t buf;
02752bc8d64df8cd361f464e55422f7b3f2f143eTimo Sirainen unsigned char update_data[sizeof(*u) + sizeof(offset)];
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
082e82792b8ac33ad42beac510441b37a3c50737Timo Sirainen if (!ctx->index_sync_transaction) {
082e82792b8ac33ad42beac510441b37a3c50737Timo Sirainen /* this is a non-syncing transaction. update the tail offset
082e82792b8ac33ad42beac510441b37a3c50737Timo Sirainen only if we're already writing something else to transaction
082e82792b8ac33ad42beac510441b37a3c50737Timo Sirainen log anyway. */
082e82792b8ac33ad42beac510441b37a3c50737Timo Sirainen i_assert(!ctx->tail_offset_changed);
082e82792b8ac33ad42beac510441b37a3c50737Timo Sirainen /* FIXME: For now we never do this update, because it would
082e82792b8ac33ad42beac510441b37a3c50737Timo Sirainen cause errors about shrinking tail offsets with old Dovecot
082e82792b8ac33ad42beac510441b37a3c50737Timo Sirainen versions. This is anyway just an optimization, so it doesn't
082e82792b8ac33ad42beac510441b37a3c50737Timo Sirainen matter all that much if we don't do it here. Finish this
082e82792b8ac33ad42beac510441b37a3c50737Timo Sirainen in v2.3. */
082e82792b8ac33ad42beac510441b37a3c50737Timo Sirainen /*if (ctx->output->used == 0)*/
082e82792b8ac33ad42beac510441b37a3c50737Timo Sirainen return;
082e82792b8ac33ad42beac510441b37a3c50737Timo Sirainen } else if (file->max_tail_offset == file->sync_offset) {
082e82792b8ac33ad42beac510441b37a3c50737Timo Sirainen /* we're synced all the way to tail offset, so this sync
082e82792b8ac33ad42beac510441b37a3c50737Timo Sirainen transaction can also be included in the same tail offset. */
082e82792b8ac33ad42beac510441b37a3c50737Timo Sirainen if (ctx->output->used == 0 && !ctx->tail_offset_changed) {
8f430e257605b2fd2b54cdf4c2a20ef8b53cf0baTimo Sirainen /* nothing to write here after all (e.g. all unchanged
8f430e257605b2fd2b54cdf4c2a20ef8b53cf0baTimo Sirainen flag updates were dropped by export) */
8f430e257605b2fd2b54cdf4c2a20ef8b53cf0baTimo Sirainen return;
8f430e257605b2fd2b54cdf4c2a20ef8b53cf0baTimo Sirainen }
8f430e257605b2fd2b54cdf4c2a20ef8b53cf0baTimo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen /* FIXME: when we remove exclusive log locking, we
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen can't rely on this. then write non-changed offset + check
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen real offset + rewrite the new offset if other transactions
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen weren't written in the middle */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen file->max_tail_offset += ctx->output->used +
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen sizeof(*hdr) + sizeof(*u) + sizeof(offset);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen ctx->sync_includes_this = TRUE;
082e82792b8ac33ad42beac510441b37a3c50737Timo Sirainen } else {
082e82792b8ac33ad42beac510441b37a3c50737Timo Sirainen /* This is a syncing transaction. Since we're finishing a sync,
082e82792b8ac33ad42beac510441b37a3c50737Timo Sirainen we may need to update the tail offset even if we don't have
082e82792b8ac33ad42beac510441b37a3c50737Timo Sirainen anything else to do. */
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen offset = file->max_tail_offset;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (file->saved_tail_offset == offset)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen i_assert(offset > file->saved_tail_offset);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
3281669db44d09a087a203201248abbc81b3cc1aTimo Sirainen buffer_create_from_data(&buf, update_data, sizeof(update_data));
02752bc8d64df8cd361f464e55422f7b3f2f143eTimo Sirainen u = buffer_append_space_unsafe(&buf, sizeof(*u));
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen u->offset = offsetof(struct mail_index_header, log_file_tail_offset);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen u->size = sizeof(offset);
02752bc8d64df8cd361f464e55422f7b3f2f143eTimo Sirainen buffer_append(&buf, &offset, sizeof(offset));
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen mail_transaction_log_append_add(ctx, MAIL_TRANSACTION_HEADER_UPDATE,
02752bc8d64df8cd361f464e55422f7b3f2f143eTimo Sirainen buf.data, buf.used);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen}
75ef04fc62a3955d3a5310410e09735cbd4e972bTimo Sirainen
b529a94ab17fe69cdcfab08d7030266cb2a564e4Timo Sirainenstatic int
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenmail_transaction_log_append_locked(struct mail_transaction_log_append_ctx *ctx)
d48a2f3288eba53dd10d9d8029ec583d78a977e0Timo Sirainen{
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen struct mail_transaction_log_file *file = ctx->log->head;
bd503f12eb667df389a99162f567bd8785798f55Timo Sirainen struct mail_transaction_boundary *boundary;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen if (file->sync_offset < file->last_size) {
4d5d16ff85dacf56ddd70f76e0ccdb12b9d314d0Timo Sirainen /* there is some garbage at the end of the transaction log
4d5d16ff85dacf56ddd70f76e0ccdb12b9d314d0Timo Sirainen (eg. previous write failed). remove it so reader doesn't
4d5d16ff85dacf56ddd70f76e0ccdb12b9d314d0Timo Sirainen break because of it. */
4d5d16ff85dacf56ddd70f76e0ccdb12b9d314d0Timo Sirainen buffer_set_used_size(file->buffer,
4d5d16ff85dacf56ddd70f76e0ccdb12b9d314d0Timo Sirainen file->sync_offset - file->buffer_offset);
4d5d16ff85dacf56ddd70f76e0ccdb12b9d314d0Timo Sirainen if (!MAIL_TRANSACTION_LOG_FILE_IN_MEMORY(file)) {
4d5d16ff85dacf56ddd70f76e0ccdb12b9d314d0Timo Sirainen if (ftruncate(file->fd, file->sync_offset) < 0) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen mail_index_file_set_syscall_error(ctx->log->index,
4d5d16ff85dacf56ddd70f76e0ccdb12b9d314d0Timo Sirainen file->filepath, "ftruncate()");
4d5d16ff85dacf56ddd70f76e0ccdb12b9d314d0Timo Sirainen }
4d5d16ff85dacf56ddd70f76e0ccdb12b9d314d0Timo Sirainen }
4d5d16ff85dacf56ddd70f76e0ccdb12b9d314d0Timo Sirainen }
4d5d16ff85dacf56ddd70f76e0ccdb12b9d314d0Timo Sirainen
bd503f12eb667df389a99162f567bd8785798f55Timo Sirainen /* don't include log_file_tail_offset update in the transaction */
bd503f12eb667df389a99162f567bd8785798f55Timo Sirainen boundary = buffer_get_space_unsafe(ctx->output,
bd503f12eb667df389a99162f567bd8785798f55Timo Sirainen sizeof(struct mail_transaction_header),
bd503f12eb667df389a99162f567bd8785798f55Timo Sirainen sizeof(*boundary));
bd503f12eb667df389a99162f567bd8785798f55Timo Sirainen boundary->size = ctx->output->used;
bd503f12eb667df389a99162f567bd8785798f55Timo Sirainen
bd503f12eb667df389a99162f567bd8785798f55Timo Sirainen if (ctx->transaction_count <= 2) {
bd503f12eb667df389a99162f567bd8785798f55Timo Sirainen /* 0-1 changes. don't bother with the boundary */
bd503f12eb667df389a99162f567bd8785798f55Timo Sirainen unsigned int boundary_size =
bd503f12eb667df389a99162f567bd8785798f55Timo Sirainen sizeof(struct mail_transaction_header) +
bd503f12eb667df389a99162f567bd8785798f55Timo Sirainen sizeof(*boundary);
bd503f12eb667df389a99162f567bd8785798f55Timo Sirainen
bd503f12eb667df389a99162f567bd8785798f55Timo Sirainen buffer_delete(ctx->output, 0, boundary_size);
bd503f12eb667df389a99162f567bd8785798f55Timo Sirainen }
bd503f12eb667df389a99162f567bd8785798f55Timo Sirainen
082e82792b8ac33ad42beac510441b37a3c50737Timo Sirainen log_append_sync_offset_if_needed(ctx);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (log_buffer_write(ctx) < 0)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen return -1;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen file->sync_highest_modseq = ctx->new_highest_modseq;
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen return 0;
d48a2f3288eba53dd10d9d8029ec583d78a977e0Timo Sirainen}
d48a2f3288eba53dd10d9d8029ec583d78a977e0Timo Sirainen
e169102fb38ce788b76c2a344bee7d77079dea05Timo Sirainenint mail_transaction_log_append_begin(struct mail_index *index,
e169102fb38ce788b76c2a344bee7d77079dea05Timo Sirainen enum mail_transaction_type flags,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen struct mail_transaction_log_append_ctx **ctx_r)
b529a94ab17fe69cdcfab08d7030266cb2a564e4Timo Sirainen{
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen struct mail_transaction_log_append_ctx *ctx;
bd503f12eb667df389a99162f567bd8785798f55Timo Sirainen struct mail_transaction_boundary boundary;
b529a94ab17fe69cdcfab08d7030266cb2a564e4Timo Sirainen
07e80e04c8876b6bf3f95266f48b41e1a681e445Timo Sirainen if (!index->log_sync_locked) {
6ded8819b9002150a95a7615e4f64f091c250464Timo Sirainen if (mail_transaction_log_lock_head(index->log, "appending") < 0)
b529a94ab17fe69cdcfab08d7030266cb2a564e4Timo Sirainen return -1;
b529a94ab17fe69cdcfab08d7030266cb2a564e4Timo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen ctx = i_new(struct mail_transaction_log_append_ctx, 1);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen ctx->log = index->log;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen ctx->output = buffer_create_dynamic(default_pool, 1024);
e169102fb38ce788b76c2a344bee7d77079dea05Timo Sirainen ctx->trans_flags = flags;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&boundary);
bd503f12eb667df389a99162f567bd8785798f55Timo Sirainen mail_transaction_log_append_add(ctx, MAIL_TRANSACTION_BOUNDARY,
bd503f12eb667df389a99162f567bd8785798f55Timo Sirainen &boundary, sizeof(boundary));
bd503f12eb667df389a99162f567bd8785798f55Timo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen *ctx_r = ctx;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen return 0;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen}
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenint mail_transaction_log_append_commit(struct mail_transaction_log_append_ctx **_ctx)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen{
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen struct mail_transaction_log_append_ctx *ctx = *_ctx;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen struct mail_index *index = ctx->log->index;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen int ret = 0;
b529a94ab17fe69cdcfab08d7030266cb2a564e4Timo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen *_ctx = NULL;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
ab11c996ff754af701b03c63db20e434469064e0Timo Sirainen ret = mail_transaction_log_append_locked(ctx);
07e80e04c8876b6bf3f95266f48b41e1a681e445Timo Sirainen if (!index->log_sync_locked)
2f8da04d700cc23fcd6630226a4866e828b761bdTimo Sirainen mail_transaction_log_file_unlock(index->log->head, "appending");
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen buffer_free(&ctx->output);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen i_free(ctx);
b529a94ab17fe69cdcfab08d7030266cb2a564e4Timo Sirainen return ret;
b529a94ab17fe69cdcfab08d7030266cb2a564e4Timo Sirainen}