mail-transaction-log.c revision 6f807c51cc3715884a3d12f25969f0b71eb5bf3b
45312f52ff3a3d4c137447be4c7556500c2f8bf2Timo Sirainen/* Copyright (C) 2003-2007 Timo Sirainen */
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "lib.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include "ioloop.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include "buffer.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "file-dotlock.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include "nfs-workarounds.h"
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen#include "close-keep-errno.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include "mmap-util.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include "mail-index-private.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include "mail-transaction-log-private.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include <stddef.h>
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include <stdio.h>
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen#include <sys/stat.h>
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen/* this lock should never exist for a long time.. */
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#define LOG_DOTLOCK_TIMEOUT 60
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#define LOG_DOTLOCK_STALE_TIMEOUT 60
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#define MAIL_TRANSACTION_LOG_SUFFIX ".log"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#define LOG_NEW_DOTLOCK_SUFFIX ".newlock"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic void
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenmail_transaction_log_set_head(struct mail_transaction_log *log,
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct mail_transaction_log_file *file)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen i_assert(log->head != file);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen file->refcount++;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen log->head = file;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen i_assert(log->files != NULL);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen i_assert(log->files->next != NULL || log->files == file);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen}
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstruct mail_transaction_log *
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenmail_transaction_log_alloc(struct mail_index *index)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct mail_transaction_log *log;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen log = i_new(struct mail_transaction_log, 1);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen log->index = index;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen log->dotlock_settings.use_excl_lock = index->use_excl_dotlocks;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen log->dotlock_settings.timeout = LOG_DOTLOCK_TIMEOUT;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen log->dotlock_settings.stale_timeout = LOG_DOTLOCK_STALE_TIMEOUT;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen log->new_dotlock_settings = log->dotlock_settings;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen log->new_dotlock_settings.lock_suffix = LOG_NEW_DOTLOCK_SUFFIX;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen return log;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen}
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic void mail_transaction_log_2_unlink_old(struct mail_transaction_log *log)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct stat st;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen const char *path;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen path = t_strconcat(log->index->filepath,
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen MAIL_TRANSACTION_LOG_SUFFIX".2", NULL);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (stat(path, &st) < 0) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (errno != ENOENT && errno != ESTALE) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen mail_index_set_error(log->index,
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen "stat(%s) failed: %m", path);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen }
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen return;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen }
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (st.st_mtime + MAIL_TRANSACTION_LOG2_STALE_SECS <= ioloop_time) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (unlink(path) < 0 && errno != ENOENT) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen mail_index_set_error(log->index,
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen "unlink(%s) failed: %m", path);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen }
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen }
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen}
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenint mail_transaction_log_open(struct mail_transaction_log *log)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct mail_transaction_log_file *file;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen const char *path;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen int ret;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (log->open_file != NULL)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen mail_transaction_log_file_free(&log->open_file);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (MAIL_INDEX_IS_IN_MEMORY(log->index))
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen return 0;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen path = t_strconcat(log->index->filepath,
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen MAIL_TRANSACTION_LOG_SUFFIX, NULL);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen file = mail_transaction_log_file_alloc(log, path);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if ((ret = mail_transaction_log_file_open(file, FALSE)) <= 0) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen /* leave the file for _create() */
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen log->open_file = file;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen return ret;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen }
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen mail_transaction_log_set_head(log, file);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen mail_transaction_log_2_unlink_old(log);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen return 1;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen}
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenint mail_transaction_log_create(struct mail_transaction_log *log)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct mail_transaction_log_file *file;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen const char *path;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (MAIL_INDEX_IS_IN_MEMORY(log->index)) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen file = mail_transaction_log_file_alloc_in_memory(log);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen mail_transaction_log_set_head(log, file);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen return 0;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen }
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen path = t_strconcat(log->index->filepath,
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen MAIL_TRANSACTION_LOG_SUFFIX, NULL);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen file = mail_transaction_log_file_alloc(log, path);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (log->open_file != NULL) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen /* remember what file we tried to open. if someone else created
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen a new file, use it instead of recreating it */
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen file->st_ino = log->open_file->st_ino;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen file->st_dev = log->open_file->st_dev;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen file->last_size = log->open_file->last_size;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen file->last_mtime = log->open_file->last_mtime;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen mail_transaction_log_file_free(&log->open_file);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen }
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (mail_transaction_log_file_create(file, FALSE) < 0) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen mail_transaction_log_file_free(&file);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen return -1;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen }
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen mail_transaction_log_set_head(log, file);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen return 1;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen}
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenvoid mail_transaction_log_close(struct mail_transaction_log *log)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen mail_transaction_log_views_close(log);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (log->open_file != NULL)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen mail_transaction_log_file_free(&log->open_file);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (log->head != NULL)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen log->head->refcount--;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen mail_transaction_logs_clean(log);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen i_assert(log->files == NULL);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen}
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenvoid mail_transaction_log_free(struct mail_transaction_log **_log)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct mail_transaction_log *log = *_log;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen *_log = NULL;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen mail_transaction_log_close(log);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen log->index->log = NULL;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen i_free(log);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen}
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenvoid mail_transaction_log_move_to_memory(struct mail_transaction_log *log)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (log->head != NULL)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen mail_transaction_log_file_move_to_memory(log->head);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen}
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenvoid mail_transaction_log_indexid_changed(struct mail_transaction_log *log)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct mail_transaction_log_file *file;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_transaction_logs_clean(log);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen for (file = log->files; file != NULL; file = file->next) {
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen if (file->hdr.indexid != log->index->indexid) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_transaction_log_file_set_corrupted(file,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "indexid changed: %u -> %u",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen file->hdr.indexid, log->index->indexid);
4dc8837ab37c1a606add1067e21ed868754db4e3Timo Sirainen }
8e5fedd9ada47735be8ac0f8af2a66e8528bd776Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (log->head != NULL &&
e8bdf1be00aec45d0c6dd72ad9c8be02a3dfc778Timo Sirainen log->head->hdr.indexid != log->index->indexid) {
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen if (--log->head->refcount == 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_transaction_log_file_free(&log->head);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen (void)mail_transaction_log_create(log);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen }
2abfef71398a61e5ed97c23a1ceb71461933ccb8Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid mail_transaction_logs_clean(struct mail_transaction_log *log)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_transaction_log_file *file, *next;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen for (file = log->files; file != NULL; file = next) {
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen next = file->next;
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen i_assert(file->refcount >= 0);
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen if (file->refcount == 0)
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen mail_transaction_log_file_free(&file);
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen }
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen i_assert(log->head == NULL || log->files != NULL);
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen}
cbf7138b49d32fce0645dc6523fbb42cc07cb2faTimo Sirainen
cbf7138b49d32fce0645dc6523fbb42cc07cb2faTimo Sirainen#define LOG_WANT_ROTATE(file) \
b9b48aaaebf6f72dfab567cda073cde8a7b26598Timo Sirainen (((file)->sync_offset > MAIL_TRANSACTION_LOG_ROTATE_MIN_SIZE && \
b9b48aaaebf6f72dfab567cda073cde8a7b26598Timo Sirainen (time_t)(file)->hdr.create_stamp < \
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen ioloop_time - MAIL_TRANSACTION_LOG_ROTATE_TIME) || \
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen ((file)->sync_offset > MAIL_TRANSACTION_LOG_ROTATE_MAX_SIZE))
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainenbool mail_transaction_log_want_rotate(struct mail_transaction_log *log)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return LOG_WANT_ROTATE(log->head);
e30b748edcef3cf3352478bf21fa8f785bdc773aTimo Sirainen}
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainenint mail_transaction_log_rotate(struct mail_transaction_log *log, bool reset)
d4dcb9c30dba354cff7af6d303ecef7698194c55Timo Sirainen{
1582b4d531679849bba299c17b6ec9402b7df67dTimo Sirainen struct mail_transaction_log_file *file;
1582b4d531679849bba299c17b6ec9402b7df67dTimo Sirainen const char *path = log->head->filepath;
1582b4d531679849bba299c17b6ec9402b7df67dTimo Sirainen struct stat st;
1582b4d531679849bba299c17b6ec9402b7df67dTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_assert(log->head->locked);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
9c7e765845357342923e16351181091028e5930fTimo Sirainen if (MAIL_INDEX_IS_IN_MEMORY(log->index)) {
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen file = mail_transaction_log_file_alloc_in_memory(log);
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen if (reset) {
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen file->hdr.prev_file_seq = 0;
6bf1543bb7af03324c04e8f9ac8e430f395989aeTimo Sirainen file->hdr.prev_file_offset = 0;
6bf1543bb7af03324c04e8f9ac8e430f395989aeTimo Sirainen }
6bf1543bb7af03324c04e8f9ac8e430f395989aeTimo Sirainen } else {
6bf1543bb7af03324c04e8f9ac8e430f395989aeTimo Sirainen /* we're locked, we shouldn't need to worry about ESTALE
6bf1543bb7af03324c04e8f9ac8e430f395989aeTimo Sirainen problems in here. */
6bf1543bb7af03324c04e8f9ac8e430f395989aeTimo Sirainen if (fstat(log->head->fd, &st) < 0) {
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen mail_index_file_set_syscall_error(log->index,
b00787191c3c31bebb939c3d00f1fcdb67356c69Timo Sirainen file->filepath, "fstat()");
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen return -1;
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen }
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen file = mail_transaction_log_file_alloc(log, path);
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen file->st_dev = st.st_dev;
ee116df08d0fdab703483e18fe8076b2ef9fd9d7Timo Sirainen file->st_ino = st.st_ino;
ee116df08d0fdab703483e18fe8076b2ef9fd9d7Timo Sirainen file->last_mtime = st.st_mtime;
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen file->last_size = st.st_size;
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen if (mail_transaction_log_file_create(file, reset) < 0) {
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen mail_transaction_log_file_free(&file);
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen return -1;
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen }
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
e30b748edcef3cf3352478bf21fa8f785bdc773aTimo Sirainen if (--log->head->refcount == 0)
e30b748edcef3cf3352478bf21fa8f785bdc773aTimo Sirainen mail_transaction_logs_clean(log);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen else
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_transaction_log_file_unlock(log->head);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_transaction_log_set_head(log, file);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 0;
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen}
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainenstatic int mail_transaction_log_refresh(struct mail_transaction_log *log)
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen{
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen struct mail_transaction_log_file *file;
e30b748edcef3cf3352478bf21fa8f785bdc773aTimo Sirainen struct stat st;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *path;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_assert(log->head != NULL);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (MAIL_TRANSACTION_LOG_FILE_IN_MEMORY(log->head))
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 0;
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen
ea9fd7f876643e985946a2563140359064819b8eTimo Sirainen path = t_strconcat(log->index->filepath,
ea9fd7f876643e985946a2563140359064819b8eTimo Sirainen MAIL_TRANSACTION_LOG_SUFFIX, NULL);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (log->index->nfs_flush)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen nfs_flush_attr_cache(path);
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen if (nfs_safe_stat(path, &st) < 0) {
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen if (errno != ENOENT) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_index_file_set_syscall_error(log->index, path,
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen "stat()");
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen return -1;
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* the file should always exist at this point. if it doesn't,
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen someone deleted it manually while the index was open. try to
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen handle this nicely by creating a new log file. */
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen file = log->head;
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen if (mail_transaction_log_create(log) < 0)
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen return -1;
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen i_assert(file->refcount > 0);
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen file->refcount--;
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen return 0;
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen } else {
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen if (log->head->st_ino == st.st_ino &&
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen CMP_DEV_T(log->head->st_dev, st.st_dev)) {
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen /* same file */
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen return 0;
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen }
cbf7138b49d32fce0645dc6523fbb42cc07cb2faTimo Sirainen }
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen file = mail_transaction_log_file_alloc(log, path);
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen if (mail_transaction_log_file_open(file, FALSE) <= 0) {
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen mail_transaction_log_file_free(&file);
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen return -1;
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen }
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen i_assert(!file->locked);
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen if (--log->head->refcount == 0)
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen mail_transaction_logs_clean(log);
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen mail_transaction_log_set_head(log, file);
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen return 0;
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen}
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainenvoid mail_transaction_log_get_mailbox_sync_pos(struct mail_transaction_log *log,
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen uint32_t *file_seq_r,
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen uoff_t *file_offset_r)
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen{
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen *file_seq_r = log->head->hdr.file_seq;
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen *file_offset_r = log->head->max_tail_offset;
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen}
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainenvoid mail_transaction_log_set_mailbox_sync_pos(struct mail_transaction_log *log,
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen uint32_t file_seq,
538303a216166f3526c0ae9658c9978275cfa100Timo Sirainen uoff_t file_offset)
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen{
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen i_assert(file_seq == log->head->hdr.file_seq);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_assert(file_offset >= log->head->saved_tail_offset);
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen if (file_offset >= log->head->max_tail_offset)
a87e5f15283e057c7dc26dd9db7b616268c95ca7Timo Sirainen log->head->max_tail_offset = file_offset;
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen}
c93cd163f9c1d4b0ca29f49cbfdbf474caeef5bfTimo Sirainen
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainenint mail_transaction_log_find_file(struct mail_transaction_log *log,
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen uint32_t file_seq,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_transaction_log_file **file_r)
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_transaction_log_file *file;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *path;
8e5fedd9ada47735be8ac0f8af2a66e8528bd776Timo Sirainen int ret;
8e5fedd9ada47735be8ac0f8af2a66e8528bd776Timo Sirainen
8e5fedd9ada47735be8ac0f8af2a66e8528bd776Timo Sirainen if (file_seq > log->head->hdr.file_seq) {
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen /* see if the .log file has been recreated */
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen if (log->head->locked) {
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen /* transaction log is locked. there's no way a newer
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen file exists. */
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen return 0;
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen }
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen if (mail_transaction_log_refresh(log) < 0)
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen return -1;
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen if (file_seq > log->head->hdr.file_seq)
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen return 0;
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen }
8e5fedd9ada47735be8ac0f8af2a66e8528bd776Timo Sirainen
8e5fedd9ada47735be8ac0f8af2a66e8528bd776Timo Sirainen for (file = log->files; file != NULL; file = file->next) {
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen if (file->hdr.file_seq == file_seq) {
8e5fedd9ada47735be8ac0f8af2a66e8528bd776Timo Sirainen *file_r = file;
8e5fedd9ada47735be8ac0f8af2a66e8528bd776Timo Sirainen return 1;
8e5fedd9ada47735be8ac0f8af2a66e8528bd776Timo Sirainen }
38df0cacce475112991e60d796f8f2105c616f01Timo Sirainen }
38df0cacce475112991e60d796f8f2105c616f01Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (MAIL_INDEX_IS_IN_MEMORY(log->index))
ccc895c0358108d2304239063e940b7d75f364abTimo Sirainen return 0;
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* see if we have it in log.2 file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen path = t_strconcat(log->index->filepath,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen MAIL_TRANSACTION_LOG_SUFFIX".2", NULL);
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen file = mail_transaction_log_file_alloc(log, path);
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen if ((ret = mail_transaction_log_file_open(file, TRUE)) <= 0)
b60baf6af900a610b2b2ddd24a46f8311acc3386Timo Sirainen return ret;
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen /* but is it what we expected? */
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen if (file->hdr.file_seq != file_seq)
d3eff05aaa4c2bc0a7580ee87a54f6693f4a8241Timo Sirainen return 0;
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen *file_r = file;
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen return 1;
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen}
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainenint mail_transaction_log_lock_head(struct mail_transaction_log *log)
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen{
4dc8837ab37c1a606add1067e21ed868754db4e3Timo Sirainen struct mail_transaction_log_file *file;
4dc8837ab37c1a606add1067e21ed868754db4e3Timo Sirainen int ret = 0;
4dc8837ab37c1a606add1067e21ed868754db4e3Timo Sirainen
4dc8837ab37c1a606add1067e21ed868754db4e3Timo Sirainen /* we want to get the head file locked. this is a bit racy,
4dc8837ab37c1a606add1067e21ed868754db4e3Timo Sirainen since by the time we have it locked a new log file may have been
4dc8837ab37c1a606add1067e21ed868754db4e3Timo Sirainen created.
4dc8837ab37c1a606add1067e21ed868754db4e3Timo Sirainen
8e5fedd9ada47735be8ac0f8af2a66e8528bd776Timo Sirainen creating new log file requires locking the head file, so if we
8e5fedd9ada47735be8ac0f8af2a66e8528bd776Timo Sirainen can lock it and don't see another file, we can be sure no-one is
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen creating a new log at the moment */
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen for (;;) {
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen file = log->head;
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen if (mail_transaction_log_file_lock(file) < 0)
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen return -1;
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen file->refcount++;
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen ret = mail_transaction_log_refresh(log);
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen if (--file->refcount == 0) {
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen mail_transaction_logs_clean(log);
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen file = NULL;
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen }
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen if (ret == 0 && log->head == file) {
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen /* success */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen break;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen if (file != NULL)
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen mail_transaction_log_file_unlock(file);
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen if (ret < 0)
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen break;
b3bb775c6b735a7f6021dea799601fbfdb656e58Timo Sirainen
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen /* try again */
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen }
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen
b3bb775c6b735a7f6021dea799601fbfdb656e58Timo Sirainen return ret;
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
d77c309fccbc6a7594f8cb08fb01009fa613c568Timo Sirainenint mail_transaction_log_sync_lock(struct mail_transaction_log *log,
d77c309fccbc6a7594f8cb08fb01009fa613c568Timo Sirainen uint32_t *file_seq_r, uoff_t *file_offset_r)
d77c309fccbc6a7594f8cb08fb01009fa613c568Timo Sirainen{
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen i_assert(!log->index->log_locked);
1582b4d531679849bba299c17b6ec9402b7df67dTimo Sirainen
41264e5dcef8335ab7ba422822b3ab518b7a327aTimo Sirainen if (mail_transaction_log_lock_head(log) < 0)
41264e5dcef8335ab7ba422822b3ab518b7a327aTimo Sirainen return -1;
41264e5dcef8335ab7ba422822b3ab518b7a327aTimo Sirainen
7bd6001d84ecc1792ddfd54fe8efa63c509d90b1Timo Sirainen /* update sync_offset */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (mail_transaction_log_file_map(log->head, log->head->sync_offset,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen (uoff_t)-1) <= 0) {
d3eff05aaa4c2bc0a7580ee87a54f6693f4a8241Timo Sirainen mail_transaction_log_file_unlock(log->head);
641f0c0900ee6e7cf9667f4b40ed95cec7d0cdcaTimo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen log->index->log_locked = TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *file_seq_r = log->head->hdr.file_seq;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *file_offset_r = log->head->sync_offset;
8754bb7a1f24705ffa5434f9e10d57e0b3b88d6eTimo Sirainen return 0;
8754bb7a1f24705ffa5434f9e10d57e0b3b88d6eTimo Sirainen}
8754bb7a1f24705ffa5434f9e10d57e0b3b88d6eTimo Sirainen
641f0c0900ee6e7cf9667f4b40ed95cec7d0cdcaTimo Sirainenvoid mail_transaction_log_sync_unlock(struct mail_transaction_log *log)
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen{
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen i_assert(log->index->log_locked);
b60baf6af900a610b2b2ddd24a46f8311acc3386Timo Sirainen
641f0c0900ee6e7cf9667f4b40ed95cec7d0cdcaTimo Sirainen log->index->log_locked = FALSE;
641f0c0900ee6e7cf9667f4b40ed95cec7d0cdcaTimo Sirainen mail_transaction_log_file_unlock(log->head);
641f0c0900ee6e7cf9667f4b40ed95cec7d0cdcaTimo Sirainen}
641f0c0900ee6e7cf9667f4b40ed95cec7d0cdcaTimo Sirainen
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainenvoid mail_transaction_log_get_head(struct mail_transaction_log *log,
b60baf6af900a610b2b2ddd24a46f8311acc3386Timo Sirainen uint32_t *file_seq_r, uoff_t *file_offset_r)
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen{
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen i_assert(log->index->log_locked);
9a099a65160987349f441c82ab0e38f32b747adbTimo Sirainen
9a099a65160987349f441c82ab0e38f32b747adbTimo Sirainen *file_seq_r = log->head->hdr.file_seq;
9a099a65160987349f441c82ab0e38f32b747adbTimo Sirainen *file_offset_r = log->head->sync_offset;
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenbool mail_transaction_log_is_head_prev(struct mail_transaction_log *log,
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen uint32_t file_seq, uoff_t file_offset)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return log->head->hdr.prev_file_seq == file_seq &&
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen log->head->hdr.prev_file_offset == file_offset;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
b60baf6af900a610b2b2ddd24a46f8311acc3386Timo Sirainen