mail-transaction-log-append.c revision 40a5aeebf6b4858b93f0ddff0bf12fba769cf903
45312f52ff3a3d4c137447be4c7556500c2f8bf2Timo Sirainen/* Copyright (c) 2003-2009 Dovecot authors, see the included COPYING file */
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen#include "lib.h"
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen#include "array.h"
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen#include "write-full.h"
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen#include "mail-index-private.h"
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen#include "mail-transaction-log-private.h"
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen
45155bb1250cf5a120278f349465aded513a100fTimo Sirainenvoid mail_transaction_log_append_add(struct mail_transaction_log_append_ctx *ctx,
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen enum mail_transaction_type type,
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen const void *data, size_t size)
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen{
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen struct mail_transaction_header hdr;
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen i_assert((type & MAIL_TRANSACTION_TYPE_MASK) != 0);
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen i_assert((size % 4) == 0);
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen if (size == 0)
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen return;
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen memset(&hdr, 0, sizeof(hdr));
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen hdr.type = type;
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen if (type == MAIL_TRANSACTION_EXPUNGE)
53d564c421ca7292d7b1bd945f86894a34b75370Timo Sirainen hdr.type |= MAIL_TRANSACTION_EXPUNGE_PROT;
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen if (ctx->external)
53d564c421ca7292d7b1bd945f86894a34b75370Timo Sirainen hdr.type |= MAIL_TRANSACTION_EXTERNAL;
53d564c421ca7292d7b1bd945f86894a34b75370Timo Sirainen hdr.size = sizeof(hdr) + size;
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen hdr.size = mail_index_uint32_to_offset(hdr.size);
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen buffer_append(ctx->output, &hdr, sizeof(hdr));
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen buffer_append(ctx->output, data, size);
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen if (mail_transaction_header_has_modseq(data,
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen CONST_PTR_OFFSET(data, sizeof(hdr)),
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen ctx->new_highest_modseq))
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen ctx->new_highest_modseq++;
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen}
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainenstatic int
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainenlog_buffer_move_to_memory(struct mail_transaction_log_append_ctx *ctx)
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen{
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen struct mail_transaction_log_file *file = ctx->log->head;
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen
493123e38ca1f27b07ac30dcbc59663c5fcdcba2Timo Sirainen /* first we need to truncate this latest write so that log syncing
493123e38ca1f27b07ac30dcbc59663c5fcdcba2Timo Sirainen doesn't break */
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen if (ftruncate(file->fd, file->sync_offset) < 0) {
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen mail_index_file_set_syscall_error(file->log->index,
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen file->filepath,
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen "ftruncate()");
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen }
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen if (mail_index_move_to_memory(file->log->index) < 0)
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen return -1;
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen i_assert(MAIL_TRANSACTION_LOG_FILE_IN_MEMORY(file));
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen i_assert(file->buffer_offset + file->buffer->used ==
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen file->sync_offset);
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen buffer_append_buf(file->buffer, ctx->output, 0, (size_t)-1);
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen file->sync_offset = file->buffer_offset + file->buffer->used;
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen return 0;
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen}
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainenstatic int log_buffer_write(struct mail_transaction_log_append_ctx *ctx)
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen{
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen struct mail_transaction_log_file *file = ctx->log->head;
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen struct mail_transaction_header *hdr;
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen uint32_t first_size;
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen if (MAIL_TRANSACTION_LOG_FILE_IN_MEMORY(file)) {
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen if (file->buffer == NULL) {
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen file->buffer = buffer_create_dynamic(default_pool, 4096);
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen file->buffer_offset = sizeof(file->hdr);
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen }
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen buffer_append_buf(file->buffer, ctx->output, 0, (size_t)-1);
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen file->sync_offset = file->buffer_offset + file->buffer->used;
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen return 0;
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen }
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen /* size will be written later once everything is in disk */
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen hdr = buffer_get_space_unsafe(ctx->output, 0, sizeof(*hdr));
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen first_size = hdr->size;
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen i_assert(first_size != 0);
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen hdr->size = 0;
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen if (pwrite_full(file->fd, ctx->output->data, ctx->output->used,
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen file->sync_offset) < 0) {
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen /* write failure, fallback to in-memory indexes. */
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen hdr->size = first_size;
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen mail_index_file_set_syscall_error(file->log->index,
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen file->filepath,
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen "pwrite_full()");
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen return log_buffer_move_to_memory(ctx);
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen }
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen i_assert(!ctx->sync_includes_this ||
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen file->sync_offset + ctx->output->used ==
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen file->max_tail_offset);
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen /* now that the whole transaction has been written, rewrite the first
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen record's size so the transaction becomes visible */
53d564c421ca7292d7b1bd945f86894a34b75370Timo Sirainen if (pwrite_full(file->fd, &first_size, sizeof(uint32_t),
53d564c421ca7292d7b1bd945f86894a34b75370Timo Sirainen file->sync_offset +
53d564c421ca7292d7b1bd945f86894a34b75370Timo Sirainen offsetof(struct mail_transaction_header, size)) < 0) {
53d564c421ca7292d7b1bd945f86894a34b75370Timo Sirainen mail_index_file_set_syscall_error(file->log->index,
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen file->filepath,
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen "pwrite_full()");
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen return log_buffer_move_to_memory(ctx);
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen }
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen if ((ctx->want_fsync && !file->log->index->fsync_disable) ||
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen file->log->index->nfs_flush) {
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen if (fdatasync(file->fd) < 0) {
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen mail_index_file_set_syscall_error(file->log->index,
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen file->filepath,
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen "fdatasync()");
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen return log_buffer_move_to_memory(ctx);
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen }
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen }
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen /* FIXME: when we're relying on O_APPEND and someone else wrote a
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen transaction, we'll need to wait for it to commit its transaction.
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen if it crashes before doing that, we'll need to overwrite it with
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen a dummy record */
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen file->sync_offset += ctx->output->used;
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen return 0;
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen}
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainenstatic void
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainenlog_append_sync_offset_if_needed(struct mail_transaction_log_append_ctx *ctx)
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen{
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen struct mail_transaction_log_file *file = ctx->log->head;
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen struct mail_transaction_header_update *u;
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen struct mail_transaction_header *hdr;
feb665db52583259a1f42037c6e8a22852aa8889Timo Sirainen buffer_t *buf;
9bc0204ec8bda657ce2e96e6ae715e4034f1538bTimo Sirainen uint32_t offset;
ab1236617440e654d5c5a043b677512714b788ddTimo Sirainen
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen if (file->max_tail_offset == file->sync_offset) {
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen /* FIXME: when we remove exclusive log locking, we
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen can't rely on this. then write non-changed offset + check
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen real offset + rewrite the new offset if other transactions
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen weren't written in the middle */
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen file->max_tail_offset += ctx->output->used +
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen sizeof(*hdr) + sizeof(*u) + sizeof(offset);
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen ctx->sync_includes_this = TRUE;
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen }
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen offset = file->max_tail_offset;
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen if (file->saved_tail_offset == offset)
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen return;
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen i_assert(offset > file->saved_tail_offset);
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen buf = buffer_create_static_hard(pool_datastack_create(),
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen sizeof(*u) + sizeof(offset));
8e50329e2c5e3a199674ae9f6d3dfcddab02487bTimo Sirainen u = buffer_append_space_unsafe(buf, sizeof(*u));
8e50329e2c5e3a199674ae9f6d3dfcddab02487bTimo Sirainen u->offset = offsetof(struct mail_index_header, log_file_tail_offset);
8e50329e2c5e3a199674ae9f6d3dfcddab02487bTimo Sirainen u->size = sizeof(offset);
8e50329e2c5e3a199674ae9f6d3dfcddab02487bTimo Sirainen buffer_append(buf, &offset, sizeof(offset));
8e50329e2c5e3a199674ae9f6d3dfcddab02487bTimo Sirainen
8e50329e2c5e3a199674ae9f6d3dfcddab02487bTimo Sirainen mail_transaction_log_append_add(ctx, MAIL_TRANSACTION_HEADER_UPDATE,
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen buf->data, buf->used);
d67848ba944a3172c4834c591ddc921fa4ff16b1Timo Sirainen}
d67848ba944a3172c4834c591ddc921fa4ff16b1Timo Sirainen
d67848ba944a3172c4834c591ddc921fa4ff16b1Timo Sirainenstatic int
d67848ba944a3172c4834c591ddc921fa4ff16b1Timo Sirainenmail_transaction_log_append_locked(struct mail_transaction_log_append_ctx *ctx)
d67848ba944a3172c4834c591ddc921fa4ff16b1Timo Sirainen{
d67848ba944a3172c4834c591ddc921fa4ff16b1Timo Sirainen struct mail_transaction_log_file *file = ctx->log->head;
d67848ba944a3172c4834c591ddc921fa4ff16b1Timo Sirainen
d67848ba944a3172c4834c591ddc921fa4ff16b1Timo Sirainen if (file->sync_offset < file->last_size) {
d67848ba944a3172c4834c591ddc921fa4ff16b1Timo Sirainen /* there is some garbage at the end of the transaction log
d67848ba944a3172c4834c591ddc921fa4ff16b1Timo Sirainen (eg. previous write failed). remove it so reader doesn't
d67848ba944a3172c4834c591ddc921fa4ff16b1Timo Sirainen break because of it. */
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen buffer_set_used_size(file->buffer,
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen file->sync_offset - file->buffer_offset);
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen if (!MAIL_TRANSACTION_LOG_FILE_IN_MEMORY(file)) {
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen if (ftruncate(file->fd, file->sync_offset) < 0) {
1eff76c5dbd2ff14bbb7e40a164c290931bdf692Timo Sirainen mail_index_file_set_syscall_error(ctx->log->index,
00b2227d6ff65629707670b7b8dfd236fced8293Timo Sirainen file->filepath, "ftruncate()");
cd94aeaa294f7cc507206b4b2075852f00e14d61Timo Sirainen }
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen }
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen }
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen
cd94aeaa294f7cc507206b4b2075852f00e14d61Timo Sirainen if (ctx->append_sync_offset)
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen log_append_sync_offset_if_needed(ctx);
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen
d67848ba944a3172c4834c591ddc921fa4ff16b1Timo Sirainen if (log_buffer_write(ctx) < 0)
eb188b2a2d5395b2c6125f875ec053b04a10e5fbTimo Sirainen return -1;
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen file->sync_highest_modseq = ctx->new_highest_modseq;
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen return 0;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen}
6e8ad595d0603295f57bef576da8a3a00b55c5e2Timo Sirainen
6e8ad595d0603295f57bef576da8a3a00b55c5e2Timo Sirainenint mail_transaction_log_append_begin(struct mail_index *index, bool external,
6e8ad595d0603295f57bef576da8a3a00b55c5e2Timo Sirainen struct mail_transaction_log_append_ctx **ctx_r)
6e8ad595d0603295f57bef576da8a3a00b55c5e2Timo Sirainen{
6e8ad595d0603295f57bef576da8a3a00b55c5e2Timo Sirainen struct mail_transaction_log_append_ctx *ctx;
6e8ad595d0603295f57bef576da8a3a00b55c5e2Timo Sirainen
6e8ad595d0603295f57bef576da8a3a00b55c5e2Timo Sirainen if (!index->log_locked) {
6e8ad595d0603295f57bef576da8a3a00b55c5e2Timo Sirainen if (mail_transaction_log_lock_head(index->log) < 0)
6e8ad595d0603295f57bef576da8a3a00b55c5e2Timo Sirainen return -1;
6e8ad595d0603295f57bef576da8a3a00b55c5e2Timo Sirainen }
6e8ad595d0603295f57bef576da8a3a00b55c5e2Timo Sirainen ctx = i_new(struct mail_transaction_log_append_ctx, 1);
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen ctx->log = index->log;
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen ctx->output = buffer_create_dynamic(default_pool, 1024);
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen ctx->external = external;
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen
6e8ad595d0603295f57bef576da8a3a00b55c5e2Timo Sirainen *ctx_r = ctx;
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen return 0;
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen}
6e8ad595d0603295f57bef576da8a3a00b55c5e2Timo Sirainen
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainenint mail_transaction_log_append_commit(struct mail_transaction_log_append_ctx **_ctx)
6e8ad595d0603295f57bef576da8a3a00b55c5e2Timo Sirainen{
6e8ad595d0603295f57bef576da8a3a00b55c5e2Timo Sirainen struct mail_transaction_log_append_ctx *ctx = *_ctx;
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen struct mail_index *index = ctx->log->index;
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen int ret = 0;
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen *_ctx = NULL;
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen if (ctx->output->used > 0)
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen ret = mail_transaction_log_append_locked(ctx);
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen if (!index->log_locked)
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen mail_transaction_log_file_unlock(index->log->head);
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen buffer_free(&ctx->output);
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen i_free(ctx);
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen return ret;
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen}
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen