mail-transaction-log.c revision 96975ce7b258b4ed09040bd1dc9a453106dee581
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (c) 2003-2010 Dovecot authors, see the included COPYING file */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "lib.h"
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "ioloop.h"
0536ccb51d41e3078c3a9fa33e509fb4b2420f95Timo Sirainen#include "buffer.h"
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "file-dotlock.h"
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen#include "nfs-workarounds.h"
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen#include "close-keep-errno.h"
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen#include "mmap-util.h"
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen#include "mail-index-private.h"
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen#include "mail-transaction-log-private.h"
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen#include <stddef.h>
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen#include <stdio.h>
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen#include <sys/stat.h>
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainenstatic void
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainenmail_transaction_log_set_head(struct mail_transaction_log *log,
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen struct mail_transaction_log_file *file)
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen{
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen i_assert(log->head != file);
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen
8b247780e911909a9fdc47f69ce6d1478902ad98Timo Sirainen file->refcount++;
8b247780e911909a9fdc47f69ce6d1478902ad98Timo Sirainen log->head = file;
8b247780e911909a9fdc47f69ce6d1478902ad98Timo Sirainen
8b247780e911909a9fdc47f69ce6d1478902ad98Timo Sirainen i_assert(log->files != NULL);
8b247780e911909a9fdc47f69ce6d1478902ad98Timo Sirainen i_assert(log->files->next != NULL || log->files == file);
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen}
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainenstruct mail_transaction_log *
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainenmail_transaction_log_alloc(struct mail_index *index)
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen{
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen struct mail_transaction_log *log;
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen log = i_new(struct mail_transaction_log, 1);
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen log->index = index;
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen return log;
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen}
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainenstatic void mail_transaction_log_2_unlink_old(struct mail_transaction_log *log)
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen{
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen struct stat st;
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen if (stat(log->filepath2, &st) < 0) {
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen if (errno != ENOENT && errno != ESTALE) {
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen mail_index_set_error(log->index,
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen "stat(%s) failed: %m", log->filepath2);
9a48c2243fe98ca8393be7908f84d20c634bcdf9Timo Sirainen }
9a48c2243fe98ca8393be7908f84d20c634bcdf9Timo Sirainen return;
9a48c2243fe98ca8393be7908f84d20c634bcdf9Timo Sirainen }
9a48c2243fe98ca8393be7908f84d20c634bcdf9Timo Sirainen
9a48c2243fe98ca8393be7908f84d20c634bcdf9Timo Sirainen if (st.st_mtime + MAIL_TRANSACTION_LOG2_STALE_SECS <= ioloop_time &&
9a48c2243fe98ca8393be7908f84d20c634bcdf9Timo Sirainen !log->index->readonly) {
59e26ff34b05cd971a111f8a42fc60c13d9f688bTimo Sirainen if (unlink(log->filepath2) < 0 && errno != ENOENT) {
9a48c2243fe98ca8393be7908f84d20c634bcdf9Timo Sirainen mail_index_set_error(log->index,
2d2ebe91d56e9a158de000c9d0026f65600fbcfaTimo Sirainen "unlink(%s) failed: %m", log->filepath2);
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen }
f988b93c2ef773987bcdcbfb4cca39b955e3a392Timo Sirainen }
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen}
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainenint mail_transaction_log_open(struct mail_transaction_log *log)
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen{
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen struct mail_transaction_log_file *file;
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen int ret;
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen i_free(log->filepath);
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen i_free(log->filepath2);
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen log->filepath = i_strconcat(log->index->filepath,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen MAIL_TRANSACTION_LOG_SUFFIX, NULL);
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen log->filepath2 = i_strconcat(log->filepath, ".2", NULL);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* these settings aren't available at alloc() time, so we need to
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen set them here: */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen log->nfs_flush =
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen (log->index->flags & MAIL_INDEX_OPEN_FLAG_NFS_FLUSH) != 0;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen
571fd6ff94570ee11a72a20b649acfdac2495919Timo Sirainen if (log->open_file != NULL)
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen mail_transaction_log_file_free(&log->open_file);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen if (MAIL_INDEX_IS_IN_MEMORY(log->index))
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen return 0;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen file = mail_transaction_log_file_alloc(log, log->filepath);
5a1b498b646b5c5dbd1b3f3861df766f560578c5Timo Sirainen if ((ret = mail_transaction_log_file_open(file, FALSE)) <= 0) {
5a1b498b646b5c5dbd1b3f3861df766f560578c5Timo Sirainen /* leave the file for _create() */
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen log->open_file = file;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return ret;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen mail_transaction_log_set_head(log, file);
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen return 1;
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen}
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainenint mail_transaction_log_create(struct mail_transaction_log *log, bool reset)
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen{
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen struct mail_transaction_log_file *file;
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen if (MAIL_INDEX_IS_IN_MEMORY(log->index)) {
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen file = mail_transaction_log_file_alloc_in_memory(log);
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen mail_transaction_log_set_head(log, file);
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen return 0;
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen }
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen file = mail_transaction_log_file_alloc(log, log->filepath);
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen if (log->open_file != NULL) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* remember what file we tried to open. if someone else created
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen a new file, use it instead of recreating it */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen file->st_ino = log->open_file->st_ino;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen file->st_dev = log->open_file->st_dev;
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen file->last_size = log->open_file->last_size;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen file->last_mtime = log->open_file->last_mtime;
211ed7806d8715ec2280ffbf5d10f0d6e4f1beb2Timo Sirainen mail_transaction_log_file_free(&log->open_file);
211ed7806d8715ec2280ffbf5d10f0d6e4f1beb2Timo Sirainen }
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen if (mail_transaction_log_file_create(file, reset) < 0) {
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen mail_transaction_log_file_free(&file);
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen return -1;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen }
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen mail_transaction_log_set_head(log, file);
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen return 1;
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen}
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainenvoid mail_transaction_log_close(struct mail_transaction_log *log)
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen{
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen mail_transaction_log_views_close(log);
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (log->open_file != NULL)
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen mail_transaction_log_file_free(&log->open_file);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (log->head != NULL)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen log->head->refcount--;
556f95092c3bc850517d5ab2bb502024a55645f1Timo Sirainen mail_transaction_logs_clean(log);
556f95092c3bc850517d5ab2bb502024a55645f1Timo Sirainen i_assert(log->files == NULL);
556f95092c3bc850517d5ab2bb502024a55645f1Timo Sirainen}
556f95092c3bc850517d5ab2bb502024a55645f1Timo Sirainen
556f95092c3bc850517d5ab2bb502024a55645f1Timo Sirainenvoid mail_transaction_log_free(struct mail_transaction_log **_log)
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen{
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen struct mail_transaction_log *log = *_log;
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen *_log = NULL;
3d77cc0d502dc69ffe2afe318605964dd40b7b20Timo Sirainen
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen mail_transaction_log_close(log);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen log->index->log = NULL;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen i_free(log->filepath);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen i_free(log->filepath2);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen i_free(log);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainenvoid mail_transaction_log_move_to_memory(struct mail_transaction_log *log)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
3d77cc0d502dc69ffe2afe318605964dd40b7b20Timo Sirainen struct mail_transaction_log_file *file;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (!log->index->initial_mapped && log->files != NULL &&
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen log->files->hdr.prev_file_seq != 0) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* we couldn't read dovecot.index and we don't have the first
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen .log file, so just start from scratch */
10ff47d5d6146995e16da00d36eca7d162064a7bTimo Sirainen mail_transaction_log_close(log);
10ff47d5d6146995e16da00d36eca7d162064a7bTimo Sirainen }
10ff47d5d6146995e16da00d36eca7d162064a7bTimo Sirainen
10ff47d5d6146995e16da00d36eca7d162064a7bTimo Sirainen i_free(log->filepath);
10ff47d5d6146995e16da00d36eca7d162064a7bTimo Sirainen i_free(log->filepath2);
10ff47d5d6146995e16da00d36eca7d162064a7bTimo Sirainen log->filepath = i_strconcat(log->index->filepath,
10ff47d5d6146995e16da00d36eca7d162064a7bTimo Sirainen MAIL_TRANSACTION_LOG_SUFFIX, NULL);
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen log->filepath2 = i_strconcat(log->filepath, ".2", NULL);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen if (log->head != NULL)
8f32e59200da904613506f5649ffa4d9f5989cebTimo Sirainen mail_transaction_log_file_move_to_memory(log->head);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen else {
3d77cc0d502dc69ffe2afe318605964dd40b7b20Timo Sirainen file = mail_transaction_log_file_alloc_in_memory(log);
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen mail_transaction_log_set_head(log, file);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainenvoid mail_transaction_log_indexid_changed(struct mail_transaction_log *log)
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen{
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen struct mail_transaction_log_file *file;
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen mail_transaction_logs_clean(log);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen for (file = log->files; file != NULL; file = file->next) {
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen if (file->hdr.indexid != log->index->indexid) {
5238111c460098d9cc8cc22527026138a278b9a4Timo Sirainen mail_transaction_log_file_set_corrupted(file,
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen "indexid changed: %u -> %u",
5238111c460098d9cc8cc22527026138a278b9a4Timo Sirainen file->hdr.indexid, log->index->indexid);
3d77cc0d502dc69ffe2afe318605964dd40b7b20Timo Sirainen }
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen }
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen if (log->head != NULL &&
5238111c460098d9cc8cc22527026138a278b9a4Timo Sirainen log->head->hdr.indexid != log->index->indexid) {
5238111c460098d9cc8cc22527026138a278b9a4Timo Sirainen if (--log->head->refcount == 0)
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainen mail_transaction_log_file_free(&log->head);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen (void)mail_transaction_log_create(log, FALSE);
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenvoid mail_transaction_logs_clean(struct mail_transaction_log *log)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
de954ff15b495be13007a8aca2c09fd1d356a283Timo Sirainen struct mail_transaction_log_file *file, *next;
de954ff15b495be13007a8aca2c09fd1d356a283Timo Sirainen
de954ff15b495be13007a8aca2c09fd1d356a283Timo Sirainen /* remove only files from the beginning. this way if a view has
de954ff15b495be13007a8aca2c09fd1d356a283Timo Sirainen referenced an old file, it can still find the new files even if
de954ff15b495be13007a8aca2c09fd1d356a283Timo Sirainen there aren't any references to it currently. */
de954ff15b495be13007a8aca2c09fd1d356a283Timo Sirainen for (file = log->files; file != NULL; file = next) {
de954ff15b495be13007a8aca2c09fd1d356a283Timo Sirainen next = file->next;
de954ff15b495be13007a8aca2c09fd1d356a283Timo Sirainen
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen i_assert(file->refcount >= 0);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (file->refcount > 0)
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen break;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
3d77cc0d502dc69ffe2afe318605964dd40b7b20Timo Sirainen mail_transaction_log_file_free(&file);
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* if we still have locked files with refcount=0, unlock them */
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen for (; file != NULL; file = file->next) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (file->locked && file->refcount == 0)
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen mail_transaction_log_file_unlock(file);
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen }
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen i_assert(log->head == NULL || log->files != NULL);
8f32e59200da904613506f5649ffa4d9f5989cebTimo Sirainen}
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen#define LOG_WANT_ROTATE(file) \
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen (((file)->sync_offset > MAIL_TRANSACTION_LOG_ROTATE_MIN_SIZE && \
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen (time_t)(file)->hdr.create_stamp < \
b92e979748a22925b0770d3004eaab043ed69574Timo Sirainen ioloop_time - MAIL_TRANSACTION_LOG_ROTATE_TIME) || \
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen ((file)->sync_offset > MAIL_TRANSACTION_LOG_ROTATE_MAX_SIZE))
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainenbool mail_transaction_log_want_rotate(struct mail_transaction_log *log)
35283613d4c04ce18836e9fc431582c87b3710a0Timo Sirainen{
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen return LOG_WANT_ROTATE(log->head);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen}
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen
35283613d4c04ce18836e9fc431582c87b3710a0Timo Sirainenint mail_transaction_log_rotate(struct mail_transaction_log *log, bool reset)
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen{
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen struct mail_transaction_log_file *file;
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen const char *path = log->head->filepath;
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen struct stat st;
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen i_assert(log->head->locked);
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen
0ce5f96804e81cb0f857e7df32c0272f1eed9377Timo Sirainen if (MAIL_INDEX_IS_IN_MEMORY(log->index)) {
0ce5f96804e81cb0f857e7df32c0272f1eed9377Timo Sirainen file = mail_transaction_log_file_alloc_in_memory(log);
0ce5f96804e81cb0f857e7df32c0272f1eed9377Timo Sirainen if (reset) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen file->hdr.prev_file_seq = 0;
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen file->hdr.prev_file_offset = 0;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
0ce5f96804e81cb0f857e7df32c0272f1eed9377Timo Sirainen } else {
0ce5f96804e81cb0f857e7df32c0272f1eed9377Timo Sirainen /* we're locked, we shouldn't need to worry about ESTALE
0dbcf4026ff8471b4d6d2e14f7e52321396bf087Timo Sirainen problems in here. */
0dbcf4026ff8471b4d6d2e14f7e52321396bf087Timo Sirainen if (fstat(log->head->fd, &st) < 0) {
0ce5f96804e81cb0f857e7df32c0272f1eed9377Timo Sirainen mail_index_file_set_syscall_error(log->index,
0ce5f96804e81cb0f857e7df32c0272f1eed9377Timo Sirainen log->head->filepath, "fstat()");
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen return -1;
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen }
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen file = mail_transaction_log_file_alloc(log, path);
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen
8b2cf1c1bd8ddcea0525b62fd35ba76e136828a1Timo Sirainen file->st_dev = st.st_dev;
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen file->st_ino = st.st_ino;
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen file->last_mtime = st.st_mtime;
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen file->last_size = st.st_size;
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen
0ce5f96804e81cb0f857e7df32c0272f1eed9377Timo Sirainen if (mail_transaction_log_file_create(file, reset) < 0) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen mail_transaction_log_file_free(&file);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return -1;
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen }
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen }
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen if (--log->head->refcount == 0)
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen mail_transaction_logs_clean(log);
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen else
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen mail_transaction_log_file_unlock(log->head);
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen mail_transaction_log_set_head(log, file);
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen return 0;
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen}
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainenstatic int
b92e979748a22925b0770d3004eaab043ed69574Timo Sirainenmail_transaction_log_refresh(struct mail_transaction_log *log, bool nfs_flush)
555ebb032f9b8f0cdb66f27ce7374734833e7cacTimo Sirainen{
555ebb032f9b8f0cdb66f27ce7374734833e7cacTimo Sirainen struct mail_transaction_log_file *file;
555ebb032f9b8f0cdb66f27ce7374734833e7cacTimo Sirainen struct stat st;
555ebb032f9b8f0cdb66f27ce7374734833e7cacTimo Sirainen
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen i_assert(log->head != NULL);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen if (MAIL_TRANSACTION_LOG_FILE_IN_MEMORY(log->head))
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen return 0;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen if (nfs_flush && log->nfs_flush)
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen nfs_flush_file_handle_cache(log->filepath);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen if (nfs_safe_stat(log->filepath, &st) < 0) {
4e8d6d03c2ff85448df79b181a2ea850fb5d4199Timo Sirainen if (errno != ENOENT) {
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen mail_index_file_set_syscall_error(log->index,
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen log->filepath,
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen "stat()");
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen return -1;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen }
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen /* see if the whole directory got deleted */
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen if (nfs_safe_stat(log->index->dir, &st) < 0 &&
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen errno == ENOENT) {
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen log->index->index_deleted = TRUE;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen return -1;
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen }
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen /* the file should always exist at this point. if it doesn't,
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen someone deleted it manually while the index was open. try to
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen handle this nicely by creating a new log file. */
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen file = log->head;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen if (mail_transaction_log_create(log, FALSE) < 0)
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen return -1;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen i_assert(file->refcount > 0);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen file->refcount--;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen log->index->need_recreate = TRUE;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen return 0;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen } else if (log->head->st_ino == st.st_ino &&
3d77cc0d502dc69ffe2afe318605964dd40b7b20Timo Sirainen CMP_DEV_T(log->head->st_dev, st.st_dev)) {
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen /* NFS: log files get rotated to .log.2 files instead
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen of being unlinked, so we don't bother checking if
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen the existing file has already been unlinked here
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen (in which case inodes could match but point to
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen different files) */
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen return 0;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen }
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen
98a73e104c7b9c3747053e63113451e24daf7f36Timo Sirainen file = mail_transaction_log_file_alloc(log, log->filepath);
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen if (mail_transaction_log_file_open(file, FALSE) <= 0) {
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen mail_transaction_log_file_free(&file);
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen return -1;
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen }
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen i_assert(!file->locked);
f988b93c2ef773987bcdcbfb4cca39b955e3a392Timo Sirainen
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen if (--log->head->refcount == 0)
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen mail_transaction_logs_clean(log);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen mail_transaction_log_set_head(log, file);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen return 0;
98a73e104c7b9c3747053e63113451e24daf7f36Timo Sirainen}
98a73e104c7b9c3747053e63113451e24daf7f36Timo Sirainen
98a73e104c7b9c3747053e63113451e24daf7f36Timo Sirainenvoid mail_transaction_log_get_mailbox_sync_pos(struct mail_transaction_log *log,
98a73e104c7b9c3747053e63113451e24daf7f36Timo Sirainen uint32_t *file_seq_r,
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen uoff_t *file_offset_r)
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen{
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen *file_seq_r = log->head->hdr.file_seq;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen *file_offset_r = log->head->max_tail_offset;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen}
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainenvoid mail_transaction_log_set_mailbox_sync_pos(struct mail_transaction_log *log,
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen uint32_t file_seq,
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen uoff_t file_offset)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen i_assert(file_seq == log->head->hdr.file_seq);
6adf683655750bcb809275cd65dc75fd12214198Timo Sirainen i_assert(file_offset >= log->head->saved_tail_offset);
6adf683655750bcb809275cd65dc75fd12214198Timo Sirainen
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen if (file_offset >= log->head->max_tail_offset)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen log->head->max_tail_offset = file_offset;
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen}
6adf683655750bcb809275cd65dc75fd12214198Timo Sirainen
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainenint mail_transaction_log_find_file(struct mail_transaction_log *log,
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen uint32_t file_seq, bool nfs_flush,
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen struct mail_transaction_log_file **file_r)
6adf683655750bcb809275cd65dc75fd12214198Timo Sirainen{
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen struct mail_transaction_log_file *file;
6adf683655750bcb809275cd65dc75fd12214198Timo Sirainen int ret;
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen if (file_seq > log->head->hdr.file_seq) {
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen /* see if the .log file has been recreated */
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen if (log->head->locked) {
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen /* transaction log is locked. there's no way a newer
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen file exists. */
6adf683655750bcb809275cd65dc75fd12214198Timo Sirainen return 0;
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen }
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen if (mail_transaction_log_refresh(log, FALSE) < 0)
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen return -1;
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen if (file_seq > log->head->hdr.file_seq) {
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen if (!nfs_flush || !log->nfs_flush)
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen return 0;
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen /* try again, this time flush attribute cache */
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen if (mail_transaction_log_refresh(log, TRUE) < 0)
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen return -1;
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen if (file_seq > log->head->hdr.file_seq)
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen return 0;
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen }
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen }
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen for (file = log->files; file != NULL; file = file->next) {
6adf683655750bcb809275cd65dc75fd12214198Timo Sirainen if (file->hdr.file_seq == file_seq) {
6adf683655750bcb809275cd65dc75fd12214198Timo Sirainen *file_r = file;
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen return 1;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
b90fb7f78aca271243c26074ddd6587cce112a1eTimo Sirainen
b90fb7f78aca271243c26074ddd6587cce112a1eTimo Sirainen if (MAIL_INDEX_IS_IN_MEMORY(log->index))
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen return 0;
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen
b90fb7f78aca271243c26074ddd6587cce112a1eTimo Sirainen /* see if we have it in log.2 file */
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen file = mail_transaction_log_file_alloc(log, log->filepath2);
b90fb7f78aca271243c26074ddd6587cce112a1eTimo Sirainen if ((ret = mail_transaction_log_file_open(file, TRUE)) <= 0) {
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen mail_transaction_log_file_free(&file);
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen return ret;
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen }
b90fb7f78aca271243c26074ddd6587cce112a1eTimo Sirainen
b90fb7f78aca271243c26074ddd6587cce112a1eTimo Sirainen /* but is it what we expected? */
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen if (file->hdr.file_seq != file_seq)
b90fb7f78aca271243c26074ddd6587cce112a1eTimo Sirainen return 0;
b90fb7f78aca271243c26074ddd6587cce112a1eTimo Sirainen
b90fb7f78aca271243c26074ddd6587cce112a1eTimo Sirainen *file_r = file;
b90fb7f78aca271243c26074ddd6587cce112a1eTimo Sirainen return 1;
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen}
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainenint mail_transaction_log_lock_head(struct mail_transaction_log *log)
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen{
b90fb7f78aca271243c26074ddd6587cce112a1eTimo Sirainen struct mail_transaction_log_file *file;
b90fb7f78aca271243c26074ddd6587cce112a1eTimo Sirainen int ret = 0;
b90fb7f78aca271243c26074ddd6587cce112a1eTimo Sirainen
b90fb7f78aca271243c26074ddd6587cce112a1eTimo Sirainen if (!log->log_2_unlink_checked) {
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen /* we need to check once in a while if .log.2 should be deleted
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen to avoid wasting space on such old files. but we also don't
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen want to waste time on checking it when the same mailbox
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen gets opened over and over again rapidly (e.g. pop3). so
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen do this only when there have actually been some changes
3d77cc0d502dc69ffe2afe318605964dd40b7b20Timo Sirainen to mailbox (i.e. when it's being locked here) */
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen log->log_2_unlink_checked = TRUE;
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen mail_transaction_log_2_unlink_old(log);
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen }
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen /* we want to get the head file locked. this is a bit racy,
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen since by the time we have it locked a new log file may have been
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen created.
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen creating new log file requires locking the head file, so if we
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen can lock it and don't see another file, we can be sure no-one is
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen creating a new log at the moment */
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen for (;;) {
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen file = log->head;
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen if (mail_transaction_log_file_lock(file) < 0)
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen return -1;
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen file->refcount++;
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen ret = mail_transaction_log_refresh(log, TRUE);
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen if (--file->refcount == 0) {
6adf683655750bcb809275cd65dc75fd12214198Timo Sirainen mail_transaction_logs_clean(log);
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen file = NULL;
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen }
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen if (ret == 0 && log->head == file) {
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen /* success */
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen break;
6adf683655750bcb809275cd65dc75fd12214198Timo Sirainen }
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen
6adf683655750bcb809275cd65dc75fd12214198Timo Sirainen if (file != NULL)
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen mail_transaction_log_file_unlock(file);
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen if (ret < 0)
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen break;
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen
71da447014454c84828d9dface77219875554d7dTimo Sirainen /* try again */
71da447014454c84828d9dface77219875554d7dTimo Sirainen }
71da447014454c84828d9dface77219875554d7dTimo Sirainen
71da447014454c84828d9dface77219875554d7dTimo Sirainen return ret;
71da447014454c84828d9dface77219875554d7dTimo Sirainen}
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainenint mail_transaction_log_sync_lock(struct mail_transaction_log *log,
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen uint32_t *file_seq_r, uoff_t *file_offset_r)
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen{
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen i_assert(!log->index->log_locked);
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen if (mail_transaction_log_lock_head(log) < 0)
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen return -1;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen /* update sync_offset */
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen if (mail_transaction_log_file_map(log->head, log->head->sync_offset,
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen (uoff_t)-1) <= 0) {
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen mail_transaction_log_file_unlock(log->head);
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen return -1;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen }
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen log->index->log_locked = TRUE;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen *file_seq_r = log->head->hdr.file_seq;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen *file_offset_r = log->head->sync_offset;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen return 0;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen}
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainenvoid mail_transaction_log_sync_unlock(struct mail_transaction_log *log)
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen{
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen i_assert(log->index->log_locked);
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen log->index->log_locked = FALSE;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen mail_transaction_log_file_unlock(log->head);
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen}
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainenvoid mail_transaction_log_get_head(struct mail_transaction_log *log,
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen uint32_t *file_seq_r, uoff_t *file_offset_r)
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen{
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen *file_seq_r = log->head->hdr.file_seq;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen *file_offset_r = log->head->sync_offset;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen}
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainenvoid mail_transaction_log_get_tail(struct mail_transaction_log *log,
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen uint32_t *file_seq_r)
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen{
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen struct mail_transaction_log_file *tail, *file = log->files;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen for (tail = file; file->next != NULL; file = file->next) {
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen if (file->hdr.file_seq + 1 != file->next->hdr.file_seq)
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen tail = file->next;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen }
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen *file_seq_r = tail->hdr.file_seq;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen}
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainenbool mail_transaction_log_is_head_prev(struct mail_transaction_log *log,
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen uint32_t file_seq, uoff_t file_offset)
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen{
2d2ebe91d56e9a158de000c9d0026f65600fbcfaTimo Sirainen return log->head->hdr.prev_file_seq == file_seq &&
2d2ebe91d56e9a158de000c9d0026f65600fbcfaTimo Sirainen log->head->hdr.prev_file_offset == file_offset;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen}
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
d691782ae9eb4f6ab06bc42f1617e889e7c18a3bTimo Sirainenint mail_transaction_log_get_mtime(struct mail_transaction_log *log,
d691782ae9eb4f6ab06bc42f1617e889e7c18a3bTimo Sirainen time_t *mtime_r)
d691782ae9eb4f6ab06bc42f1617e889e7c18a3bTimo Sirainen{
d691782ae9eb4f6ab06bc42f1617e889e7c18a3bTimo Sirainen struct stat st;
d691782ae9eb4f6ab06bc42f1617e889e7c18a3bTimo Sirainen
d691782ae9eb4f6ab06bc42f1617e889e7c18a3bTimo Sirainen *mtime_r = 0;
d691782ae9eb4f6ab06bc42f1617e889e7c18a3bTimo Sirainen if (stat(log->filepath, &st) < 0) {
d691782ae9eb4f6ab06bc42f1617e889e7c18a3bTimo Sirainen if (errno == ENOENT)
d691782ae9eb4f6ab06bc42f1617e889e7c18a3bTimo Sirainen return 0;
d691782ae9eb4f6ab06bc42f1617e889e7c18a3bTimo Sirainen
d691782ae9eb4f6ab06bc42f1617e889e7c18a3bTimo Sirainen mail_index_file_set_syscall_error(log->index, log->filepath,
d691782ae9eb4f6ab06bc42f1617e889e7c18a3bTimo Sirainen "stat()");
d691782ae9eb4f6ab06bc42f1617e889e7c18a3bTimo Sirainen return -1;
d691782ae9eb4f6ab06bc42f1617e889e7c18a3bTimo Sirainen }
d691782ae9eb4f6ab06bc42f1617e889e7c18a3bTimo Sirainen *mtime_r = st.st_mtime;
d691782ae9eb4f6ab06bc42f1617e889e7c18a3bTimo Sirainen return 0;
d691782ae9eb4f6ab06bc42f1617e889e7c18a3bTimo Sirainen}
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainenvoid mail_transaction_log_get_dotlock_set(struct mail_transaction_log *log,
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen struct dotlock_settings *set_r)
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen{
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen struct mail_index *index = log->index;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen memset(set_r, 0, sizeof(*set_r));
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen set_r->timeout = I_MIN(MAIL_TRANSCATION_LOG_LOCK_TIMEOUT,
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen index->max_lock_timeout_secs);
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen set_r->stale_timeout = MAIL_TRANSCATION_LOG_LOCK_CHANGE_TIMEOUT;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen set_r->nfs_flush = (index->flags & MAIL_INDEX_OPEN_FLAG_NFS_FLUSH) != 0;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen set_r->use_excl_lock =
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen (index->flags & MAIL_INDEX_OPEN_FLAG_DOTLOCK_USE_EXCL) != 0;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen}
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen