mail-transaction-log.c revision 07e80e04c8876b6bf3f95266f48b41e1a681e445
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek/* Copyright (c) 2003-2010 Dovecot authors, see the included COPYING file */
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek#include "lib.h"
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek#include "ioloop.h"
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek#include "buffer.h"
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek#include "file-dotlock.h"
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek#include "nfs-workarounds.h"
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek#include "close-keep-errno.h"
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek#include "mmap-util.h"
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek#include "mail-index-private.h"
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek#include "mail-transaction-log-private.h"
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek#include <stddef.h>
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek#include <stdio.h>
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek#include <sys/stat.h>
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozekstatic void
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozekmail_transaction_log_set_head(struct mail_transaction_log *log,
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek struct mail_transaction_log_file *file)
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek{
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek i_assert(log->head != file);
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek file->refcount++;
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek log->head = file;
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek i_assert(log->files != NULL);
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek i_assert(log->files->next != NULL || log->files == file);
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek}
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozekstruct mail_transaction_log *
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozekmail_transaction_log_alloc(struct mail_index *index)
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek{
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek struct mail_transaction_log *log;
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek log = i_new(struct mail_transaction_log, 1);
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek log->index = index;
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek return log;
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek}
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozekstatic void mail_transaction_log_2_unlink_old(struct mail_transaction_log *log)
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek{
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek struct stat st;
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek if (stat(log->filepath2, &st) < 0) {
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek if (errno != ENOENT && errno != ESTALE) {
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek mail_index_set_error(log->index,
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek "stat(%s) failed: %m", log->filepath2);
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek }
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek return;
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek }
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek if (st.st_mtime + MAIL_TRANSACTION_LOG2_STALE_SECS <= ioloop_time &&
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek !log->index->readonly) {
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek if (unlink(log->filepath2) < 0 && errno != ENOENT) {
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek mail_index_set_error(log->index,
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek "unlink(%s) failed: %m", log->filepath2);
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek }
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek }
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek}
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozekint mail_transaction_log_open(struct mail_transaction_log *log)
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek{
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek struct mail_transaction_log_file *file;
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek int ret;
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek i_free(log->filepath);
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek i_free(log->filepath2);
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek log->filepath = i_strconcat(log->index->filepath,
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek MAIL_TRANSACTION_LOG_SUFFIX, NULL);
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek log->filepath2 = i_strconcat(log->filepath, ".2", NULL);
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek /* these settings aren't available at alloc() time, so we need to
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek set them here: */
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek log->nfs_flush =
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek (log->index->flags & MAIL_INDEX_OPEN_FLAG_NFS_FLUSH) != 0;
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek if (log->open_file != NULL)
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek mail_transaction_log_file_free(&log->open_file);
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek if (MAIL_INDEX_IS_IN_MEMORY(log->index))
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek return 0;
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek file = mail_transaction_log_file_alloc(log, log->filepath);
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek if ((ret = mail_transaction_log_file_open(file, FALSE)) <= 0) {
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek /* leave the file for _create() */
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek log->open_file = file;
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek return ret;
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek }
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek mail_transaction_log_set_head(log, file);
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek return 1;
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek}
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozekint mail_transaction_log_create(struct mail_transaction_log *log, bool reset)
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek{
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek struct mail_transaction_log_file *file;
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek if (MAIL_INDEX_IS_IN_MEMORY(log->index)) {
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek file = mail_transaction_log_file_alloc_in_memory(log);
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek mail_transaction_log_set_head(log, file);
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek return 0;
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek }
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek file = mail_transaction_log_file_alloc(log, log->filepath);
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek if (log->open_file != NULL) {
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek /* remember what file we tried to open. if someone else created
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek a new file, use it instead of recreating it */
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek file->st_ino = log->open_file->st_ino;
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek file->st_dev = log->open_file->st_dev;
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek file->last_size = log->open_file->last_size;
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek file->last_mtime = log->open_file->last_mtime;
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek mail_transaction_log_file_free(&log->open_file);
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek }
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek if (mail_transaction_log_file_create(file, reset) < 0) {
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek mail_transaction_log_file_free(&file);
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek return -1;
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek }
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek mail_transaction_log_set_head(log, file);
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek return 1;
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek}
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozekvoid mail_transaction_log_close(struct mail_transaction_log *log)
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek{
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek mail_transaction_log_views_close(log);
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek if (log->open_file != NULL)
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek mail_transaction_log_file_free(&log->open_file);
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek if (log->head != NULL)
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek log->head->refcount--;
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek mail_transaction_logs_clean(log);
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek i_assert(log->files == NULL);
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek}
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozekvoid mail_transaction_log_free(struct mail_transaction_log **_log)
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek{
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek struct mail_transaction_log *log = *_log;
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek *_log = NULL;
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek mail_transaction_log_close(log);
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek log->index->log = NULL;
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek i_free(log->filepath);
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek i_free(log->filepath2);
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek i_free(log);
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek}
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozekvoid mail_transaction_log_move_to_memory(struct mail_transaction_log *log)
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek{
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek struct mail_transaction_log_file *file;
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek if (!log->index->initial_mapped && log->files != NULL &&
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek log->files->hdr.prev_file_seq != 0) {
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek /* we couldn't read dovecot.index and we don't have the first
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek .log file, so just start from scratch */
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek mail_transaction_log_close(log);
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek }
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek i_free(log->filepath);
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek i_free(log->filepath2);
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek log->filepath = i_strconcat(log->index->filepath,
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek MAIL_TRANSACTION_LOG_SUFFIX, NULL);
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek log->filepath2 = i_strconcat(log->filepath, ".2", NULL);
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek if (log->head != NULL)
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek mail_transaction_log_file_move_to_memory(log->head);
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek else {
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek file = mail_transaction_log_file_alloc_in_memory(log);
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek mail_transaction_log_set_head(log, file);
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek }
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek}
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozekvoid mail_transaction_log_indexid_changed(struct mail_transaction_log *log)
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek{
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek struct mail_transaction_log_file *file;
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek mail_transaction_logs_clean(log);
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek
cc4caf88344210ea9777d618f0f71935ca5e7f8bSumit Bose for (file = log->files; file != NULL; file = file->next) {
cc4caf88344210ea9777d618f0f71935ca5e7f8bSumit Bose if (file->hdr.indexid != log->index->indexid) {
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek mail_transaction_log_file_set_corrupted(file,
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek "indexid changed: %u -> %u",
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek file->hdr.indexid, log->index->indexid);
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek }
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek }
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek if (log->head != NULL &&
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek log->head->hdr.indexid != log->index->indexid) {
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek if (--log->head->refcount == 0)
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek mail_transaction_log_file_free(&log->head);
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek (void)mail_transaction_log_create(log, FALSE);
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek }
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek}
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozekvoid mail_transaction_logs_clean(struct mail_transaction_log *log)
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek{
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek struct mail_transaction_log_file *file, *next;
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek /* remove only files from the beginning. this way if a view has
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek referenced an old file, it can still find the new files even if
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek there aren't any references to it currently. */
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek for (file = log->files; file != NULL; file = next) {
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek next = file->next;
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek i_assert(file->refcount >= 0);
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek if (file->refcount > 0)
de2bad8ae08f09964834bda0f88db9de39f47c5cJakub Hrozek break;
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek mail_transaction_log_file_free(&file);
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek }
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek /* if we still have locked files with refcount=0, unlock them */
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek for (; file != NULL; file = file->next) {
de2bad8ae08f09964834bda0f88db9de39f47c5cJakub Hrozek if (file->locked && file->refcount == 0)
de2bad8ae08f09964834bda0f88db9de39f47c5cJakub Hrozek mail_transaction_log_file_unlock(file);
de2bad8ae08f09964834bda0f88db9de39f47c5cJakub Hrozek }
d2c552edde275e6c0de904760147afb2992796e9Jakub Hrozek i_assert(log->head == NULL || log->files != NULL);
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek}
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek#define LOG_WANT_ROTATE(file) \
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek (((file)->sync_offset > MAIL_TRANSACTION_LOG_ROTATE_MIN_SIZE && \
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek (time_t)(file)->hdr.create_stamp < \
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek ioloop_time - MAIL_TRANSACTION_LOG_ROTATE_TIME) || \
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek ((file)->sync_offset > MAIL_TRANSACTION_LOG_ROTATE_MAX_SIZE))
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozekbool mail_transaction_log_want_rotate(struct mail_transaction_log *log)
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek{
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek return LOG_WANT_ROTATE(log->head);
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek}
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozekint mail_transaction_log_rotate(struct mail_transaction_log *log, bool reset)
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek{
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek struct mail_transaction_log_file *file;
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek const char *path = log->head->filepath;
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek struct stat st;
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek i_assert(log->head->locked);
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek if (MAIL_INDEX_IS_IN_MEMORY(log->index)) {
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek file = mail_transaction_log_file_alloc_in_memory(log);
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek if (reset) {
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek file->hdr.prev_file_seq = 0;
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek file->hdr.prev_file_offset = 0;
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek }
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek } else {
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek /* we're locked, we shouldn't need to worry about ESTALE
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek problems in here. */
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek if (fstat(log->head->fd, &st) < 0) {
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek mail_index_file_set_syscall_error(log->index,
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek log->head->filepath, "fstat()");
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek return -1;
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek }
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek
149174acae677d1e72a0da431bf0850d55f2ccb4Sumit Bose file = mail_transaction_log_file_alloc(log, path);
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek file->st_dev = st.st_dev;
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek file->st_ino = st.st_ino;
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek file->last_mtime = st.st_mtime;
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek file->last_size = st.st_size;
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek if (mail_transaction_log_file_create(file, reset) < 0) {
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek mail_transaction_log_file_free(&file);
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek return -1;
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek }
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek }
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek if (--log->head->refcount == 0)
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek mail_transaction_logs_clean(log);
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek else
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek mail_transaction_log_file_unlock(log->head);
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek mail_transaction_log_set_head(log, file);
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek return 0;
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek}
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozekstatic int
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozekmail_transaction_log_refresh(struct mail_transaction_log *log, bool nfs_flush)
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek{
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek struct mail_transaction_log_file *file;
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek struct stat st;
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek i_assert(log->head != NULL);
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek if (MAIL_TRANSACTION_LOG_FILE_IN_MEMORY(log->head))
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek return 0;
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek if (nfs_flush && log->nfs_flush)
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek nfs_flush_file_handle_cache(log->filepath);
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek if (nfs_safe_stat(log->filepath, &st) < 0) {
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek if (errno != ENOENT) {
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek mail_index_file_set_syscall_error(log->index,
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek log->filepath,
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek "stat()");
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek return -1;
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek }
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek /* see if the whole directory got deleted */
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek if (nfs_safe_stat(log->index->dir, &st) < 0 &&
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek errno == ENOENT) {
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek log->index->index_deleted = TRUE;
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek return -1;
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek }
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek /* the file should always exist at this point. if it doesn't,
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek someone deleted it manually while the index was open. try to
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek handle this nicely by creating a new log file. */
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek file = log->head;
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek if (mail_transaction_log_create(log, FALSE) < 0)
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek return -1;
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek i_assert(file->refcount > 0);
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek file->refcount--;
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek log->index->need_recreate = TRUE;
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek return 0;
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek } else if (log->head->st_ino == st.st_ino &&
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek CMP_DEV_T(log->head->st_dev, st.st_dev)) {
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek /* NFS: log files get rotated to .log.2 files instead
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek of being unlinked, so we don't bother checking if
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek the existing file has already been unlinked here
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek (in which case inodes could match but point to
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek different files) */
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek return 0;
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek }
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek file = mail_transaction_log_file_alloc(log, log->filepath);
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek if (mail_transaction_log_file_open(file, FALSE) <= 0) {
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek mail_transaction_log_file_free(&file);
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek return -1;
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek }
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek i_assert(!file->locked);
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek if (--log->head->refcount == 0)
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek mail_transaction_logs_clean(log);
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek mail_transaction_log_set_head(log, file);
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek return 0;
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek}
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozekvoid mail_transaction_log_get_mailbox_sync_pos(struct mail_transaction_log *log,
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek uint32_t *file_seq_r,
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek uoff_t *file_offset_r)
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek{
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek *file_seq_r = log->head->hdr.file_seq;
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek *file_offset_r = log->head->max_tail_offset;
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek}
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozekvoid mail_transaction_log_set_mailbox_sync_pos(struct mail_transaction_log *log,
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek uint32_t file_seq,
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek uoff_t file_offset)
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek{
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek i_assert(file_seq == log->head->hdr.file_seq);
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek i_assert(file_offset >= log->head->saved_tail_offset);
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek if (file_offset >= log->head->max_tail_offset)
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek log->head->max_tail_offset = file_offset;
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek}
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozekint mail_transaction_log_find_file(struct mail_transaction_log *log,
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek uint32_t file_seq, bool nfs_flush,
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek struct mail_transaction_log_file **file_r)
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek{
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek struct mail_transaction_log_file *file;
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek int ret;
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek if (file_seq > log->head->hdr.file_seq) {
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek /* see if the .log file has been recreated */
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek if (log->head->locked) {
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek /* transaction log is locked. there's no way a newer
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek file exists. */
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek return 0;
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek }
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek if (log->index->open_count == 0) {
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek /* we're opening the index and we just opened the
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek log file. don't waste time checking if there's a
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek newer one. */
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek return 0;
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek }
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek if (mail_transaction_log_refresh(log, FALSE) < 0)
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek return -1;
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek if (file_seq > log->head->hdr.file_seq) {
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek if (!nfs_flush || !log->nfs_flush)
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek return 0;
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek /* try again, this time flush attribute cache */
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek if (mail_transaction_log_refresh(log, TRUE) < 0)
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek return -1;
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek if (file_seq > log->head->hdr.file_seq)
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek return 0;
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek }
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek }
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek for (file = log->files; file != NULL; file = file->next) {
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek if (file->hdr.file_seq == file_seq) {
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek *file_r = file;
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek return 1;
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek }
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek }
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek if (MAIL_INDEX_IS_IN_MEMORY(log->index))
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek return 0;
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek /* see if we have it in log.2 file */
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek file = mail_transaction_log_file_alloc(log, log->filepath2);
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek if ((ret = mail_transaction_log_file_open(file, TRUE)) <= 0) {
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek mail_transaction_log_file_free(&file);
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek return ret;
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek }
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek /* but is it what we expected? */
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek if (file->hdr.file_seq != file_seq)
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek return 0;
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek *file_r = file;
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek return 1;
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek}
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozekint mail_transaction_log_lock_head(struct mail_transaction_log *log)
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek{
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek struct mail_transaction_log_file *file;
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek int ret = 0;
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek if (!log->log_2_unlink_checked) {
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek /* we need to check once in a while if .log.2 should be deleted
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek to avoid wasting space on such old files. but we also don't
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek want to waste time on checking it when the same mailbox
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek gets opened over and over again rapidly (e.g. pop3). so
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek do this only when there have actually been some changes
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek to mailbox (i.e. when it's being locked here) */
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek log->log_2_unlink_checked = TRUE;
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek mail_transaction_log_2_unlink_old(log);
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek }
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek /* we want to get the head file locked. this is a bit racy,
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek since by the time we have it locked a new log file may have been
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek created.
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek creating new log file requires locking the head file, so if we
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek can lock it and don't see another file, we can be sure no-one is
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek creating a new log at the moment */
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek for (;;) {
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek file = log->head;
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek if (mail_transaction_log_file_lock(file) < 0)
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek return -1;
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek file->refcount++;
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek ret = mail_transaction_log_refresh(log, TRUE);
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek if (--file->refcount == 0) {
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek mail_transaction_logs_clean(log);
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek file = NULL;
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek }
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek
db5f9ab3feb85aa444eab20428ca2b98801b6783Jakub Hrozek if (ret == 0 && log->head == file) {
db5f9ab3feb85aa444eab20428ca2b98801b6783Jakub Hrozek /* success */
db5f9ab3feb85aa444eab20428ca2b98801b6783Jakub Hrozek break;
db5f9ab3feb85aa444eab20428ca2b98801b6783Jakub Hrozek }
db5f9ab3feb85aa444eab20428ca2b98801b6783Jakub Hrozek
db5f9ab3feb85aa444eab20428ca2b98801b6783Jakub Hrozek if (file != NULL)
db5f9ab3feb85aa444eab20428ca2b98801b6783Jakub Hrozek mail_transaction_log_file_unlock(file);
db5f9ab3feb85aa444eab20428ca2b98801b6783Jakub Hrozek
db5f9ab3feb85aa444eab20428ca2b98801b6783Jakub Hrozek if (ret < 0)
db5f9ab3feb85aa444eab20428ca2b98801b6783Jakub Hrozek break;
db5f9ab3feb85aa444eab20428ca2b98801b6783Jakub Hrozek
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek /* try again */
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek }
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek return ret;
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek}
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozekint mail_transaction_log_sync_lock(struct mail_transaction_log *log,
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek uint32_t *file_seq_r, uoff_t *file_offset_r)
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek{
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek i_assert(!log->index->log_sync_locked);
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek if (mail_transaction_log_lock_head(log) < 0)
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek return -1;
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek /* update sync_offset */
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek if (mail_transaction_log_file_map(log->head, log->head->sync_offset,
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek (uoff_t)-1) <= 0) {
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek mail_transaction_log_file_unlock(log->head);
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek return -1;
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek }
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek log->index->log_sync_locked = TRUE;
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek *file_seq_r = log->head->hdr.file_seq;
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek *file_offset_r = log->head->sync_offset;
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek return 0;
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek}
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozekvoid mail_transaction_log_sync_unlock(struct mail_transaction_log *log)
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek{
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek i_assert(log->index->log_sync_locked);
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek log->index->log_sync_locked = FALSE;
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek mail_transaction_log_file_unlock(log->head);
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek}
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozekvoid mail_transaction_log_get_head(struct mail_transaction_log *log,
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek uint32_t *file_seq_r, uoff_t *file_offset_r)
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek{
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek *file_seq_r = log->head->hdr.file_seq;
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek *file_offset_r = log->head->sync_offset;
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek}
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozekvoid mail_transaction_log_get_tail(struct mail_transaction_log *log,
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek uint32_t *file_seq_r)
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek{
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek struct mail_transaction_log_file *tail, *file = log->files;
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek for (tail = file; file->next != NULL; file = file->next) {
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek if (file->hdr.file_seq + 1 != file->next->hdr.file_seq)
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek tail = file->next;
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek }
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek *file_seq_r = tail->hdr.file_seq;
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek}
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozekbool mail_transaction_log_is_head_prev(struct mail_transaction_log *log,
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek uint32_t file_seq, uoff_t file_offset)
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek{
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek return log->head->hdr.prev_file_seq == file_seq &&
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek log->head->hdr.prev_file_offset == file_offset;
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek}
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozekint mail_transaction_log_get_mtime(struct mail_transaction_log *log,
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek time_t *mtime_r)
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek{
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek struct stat st;
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek *mtime_r = 0;
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek if (stat(log->filepath, &st) < 0) {
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek if (errno == ENOENT)
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek return 0;
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek mail_index_file_set_syscall_error(log->index, log->filepath,
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek "stat()");
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek return -1;
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek }
6ed964cf2e5a68e92e220f3b9f55029731bcabaaJakub Hrozek *mtime_r = st.st_mtime;
6ed964cf2e5a68e92e220f3b9f55029731bcabaaJakub Hrozek return 0;
6ed964cf2e5a68e92e220f3b9f55029731bcabaaJakub Hrozek}
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozekvoid mail_transaction_log_get_dotlock_set(struct mail_transaction_log *log,
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek struct dotlock_settings *set_r)
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek{
6ed964cf2e5a68e92e220f3b9f55029731bcabaaJakub Hrozek struct mail_index *index = log->index;
6ed964cf2e5a68e92e220f3b9f55029731bcabaaJakub Hrozek
6ed964cf2e5a68e92e220f3b9f55029731bcabaaJakub Hrozek memset(set_r, 0, sizeof(*set_r));
6ed964cf2e5a68e92e220f3b9f55029731bcabaaJakub Hrozek set_r->timeout = I_MIN(MAIL_TRANSCATION_LOG_LOCK_TIMEOUT,
6ed964cf2e5a68e92e220f3b9f55029731bcabaaJakub Hrozek index->max_lock_timeout_secs);
6ed964cf2e5a68e92e220f3b9f55029731bcabaaJakub Hrozek set_r->stale_timeout = MAIL_TRANSCATION_LOG_LOCK_CHANGE_TIMEOUT;
6ed964cf2e5a68e92e220f3b9f55029731bcabaaJakub Hrozek set_r->nfs_flush = (index->flags & MAIL_INDEX_OPEN_FLAG_NFS_FLUSH) != 0;
6ed964cf2e5a68e92e220f3b9f55029731bcabaaJakub Hrozek set_r->use_excl_lock =
6ed964cf2e5a68e92e220f3b9f55029731bcabaaJakub Hrozek (index->flags & MAIL_INDEX_OPEN_FLAG_DOTLOCK_USE_EXCL) != 0;
6ed964cf2e5a68e92e220f3b9f55029731bcabaaJakub Hrozek}
6ed964cf2e5a68e92e220f3b9f55029731bcabaaJakub Hrozek