mail-transaction-log.c revision 5b809b97673fb0a73aa5b9d82122612d699f6c5b
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen/* Copyright (c) 2003-2017 Dovecot authors, see the included COPYING file */
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainenmail_transaction_log_set_head(struct mail_transaction_log *log,
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen i_assert(log->files->next != NULL || log->files == file);
0ebeb1831a56e020b0958ed1ced50e86ee9347ecTimo Sirainenmail_transaction_log_alloc(struct mail_index *index)
0ebeb1831a56e020b0958ed1ced50e86ee9347ecTimo Sirainenstatic void mail_transaction_log_2_unlink_old(struct mail_transaction_log *log)
0ebeb1831a56e020b0958ed1ced50e86ee9347ecTimo Sirainen if (ioloop_time - st.st_mtime >= (time_t)log->index->log_rotate_log2_stale_secs &&
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainenint mail_transaction_log_open(struct mail_transaction_log *log)
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen log->filepath = i_strconcat(log->index->filepath,
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen log->filepath2 = i_strconcat(log->filepath, ".2", NULL);
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen /* these settings aren't available at alloc() time, so we need to
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen set them here: */
4ba3717a04823875c2a1d60ff9dc8177ae033d12Timo Sirainen (log->index->flags & MAIL_INDEX_OPEN_FLAG_NFS_FLUSH) != 0;
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen mail_transaction_log_file_free(&log->open_file);
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen file = mail_transaction_log_file_alloc(log, log->filepath);
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen if ((ret = mail_transaction_log_file_open(file, &reason)) <= 0) {
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen /* leave the file for _create() */
0ebeb1831a56e020b0958ed1ced50e86ee9347ecTimo Sirainenint mail_transaction_log_create(struct mail_transaction_log *log, bool reset)
57dc9669d34de7d08a44be9d7d3c9f6a0c34cc87Timo Sirainen file = mail_transaction_log_file_alloc_in_memory(log);
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen file = mail_transaction_log_file_alloc(log, log->filepath);
07dabfd18e418c92b4de84c133f105835779bebeTimo Sirainen /* remember what file we tried to open. if someone else created
07dabfd18e418c92b4de84c133f105835779bebeTimo Sirainen a new file, use it instead of recreating it */
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen file->last_mtime = log->open_file->last_mtime;
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen mail_transaction_log_file_free(&log->open_file);
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen if (mail_transaction_log_file_create(file, reset) < 0) {
4c61d6b6ad6173f06563c2cee9bd813c59277dd2Timo Sirainenvoid mail_transaction_log_close(struct mail_transaction_log *log)
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen mail_transaction_log_file_free(&log->open_file);
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainenvoid mail_transaction_log_free(struct mail_transaction_log **_log)
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainenint mail_transaction_log_move_to_memory(struct mail_transaction_log *log)
4ef1f9f3293965734e6e3c38c191ceb2246a721fTeemu Huovila if (!log->index->initial_mapped && log->files != NULL &&
4ef1f9f3293965734e6e3c38c191ceb2246a721fTeemu Huovila /* we couldn't read dovecot.index and we don't have the first
4ef1f9f3293965734e6e3c38c191ceb2246a721fTeemu Huovila .log file, so just start from scratch */
4ef1f9f3293965734e6e3c38c191ceb2246a721fTeemu Huovila log->filepath = i_strconcat(log->index->filepath,
4ef1f9f3293965734e6e3c38c191ceb2246a721fTeemu Huovila log->filepath2 = i_strconcat(log->filepath, ".2", NULL);
4ef1f9f3293965734e6e3c38c191ceb2246a721fTeemu Huovila return mail_transaction_log_file_move_to_memory(log->head);
4ef1f9f3293965734e6e3c38c191ceb2246a721fTeemu Huovila file = mail_transaction_log_file_alloc_in_memory(log);
4ef1f9f3293965734e6e3c38c191ceb2246a721fTeemu Huovilavoid mail_transaction_log_indexid_changed(struct mail_transaction_log *log)
4ef1f9f3293965734e6e3c38c191ceb2246a721fTeemu Huovila for (file = log->files; file != NULL; file = file->next) {
4ef1f9f3293965734e6e3c38c191ceb2246a721fTeemu Huovila if (file->hdr.indexid != log->index->indexid) {
0c827d2094e80ede4c089fc00260d7ffcc764636Timo Sirainen "indexid changed: %u -> %u",
0ebeb1831a56e020b0958ed1ced50e86ee9347ecTimo Sirainen log->head->hdr.indexid != log->index->indexid) {
4ef1f9f3293965734e6e3c38c191ceb2246a721fTeemu Huovila (void)mail_transaction_log_create(log, FALSE);
4ef1f9f3293965734e6e3c38c191ceb2246a721fTeemu Huovilavoid mail_transaction_logs_clean(struct mail_transaction_log *log)
4ef1f9f3293965734e6e3c38c191ceb2246a721fTeemu Huovila struct mail_transaction_log_file *file, *next;
4ef1f9f3293965734e6e3c38c191ceb2246a721fTeemu Huovila /* remove only files from the beginning. this way if a view has
4ef1f9f3293965734e6e3c38c191ceb2246a721fTeemu Huovila referenced an old file, it can still find the new files even if
4ef1f9f3293965734e6e3c38c191ceb2246a721fTeemu Huovila there aren't any references to it currently. */
4ef1f9f3293965734e6e3c38c191ceb2246a721fTeemu Huovila for (file = log->files; file != NULL; file = next) {
4ef1f9f3293965734e6e3c38c191ceb2246a721fTeemu Huovila /* sanity check: we shouldn't have locked refcount=0 files */
4ef1f9f3293965734e6e3c38c191ceb2246a721fTeemu Huovila i_assert(!file->locked || file->refcount > 0);
4ef1f9f3293965734e6e3c38c191ceb2246a721fTeemu Huovila i_assert(log->head == NULL || log->files != NULL);
4ef1f9f3293965734e6e3c38c191ceb2246a721fTeemu Huovilabool mail_transaction_log_want_rotate(struct mail_transaction_log *log)
4ef1f9f3293965734e6e3c38c191ceb2246a721fTeemu Huovila struct mail_transaction_log_file *file = log->head;
09aed882b99e865ff6d7140ae2f77a42c9e7d1a7Teemu Huovila if (file->hdr.major_version < MAIL_TRANSACTION_LOG_MAJOR_VERSION ||
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen (file->hdr.major_version == MAIL_TRANSACTION_LOG_MAJOR_VERSION &&
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen file->hdr.minor_version < MAIL_TRANSACTION_LOG_MINOR_VERSION)) {
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen /* upgrade immediately to a new log file format */
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen if (file->sync_offset > log->index->log_rotate_max_size) {
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen /* file is too large, definitely rotate */
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen if (file->sync_offset < log->index->log_rotate_min_size) {
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen /* file is still too small */
4ef1f9f3293965734e6e3c38c191ceb2246a721fTeemu Huovila /* rotate if the timestamp is old enough */
4ef1f9f3293965734e6e3c38c191ceb2246a721fTeemu Huovila ioloop_time - log->index->log_rotate_min_created_ago_secs;
4ef1f9f3293965734e6e3c38c191ceb2246a721fTeemu Huovilaint mail_transaction_log_rotate(struct mail_transaction_log *log, bool reset)
09aed882b99e865ff6d7140ae2f77a42c9e7d1a7Teemu Huovila file = mail_transaction_log_file_alloc_in_memory(log);
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen /* we're locked, we shouldn't need to worry about ESTALE
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen problems in here. */
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen file = mail_transaction_log_file_alloc(log, path);
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen if ((ret = mail_transaction_log_file_create(file, reset)) < 0) {
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen "Transaction log %s was recreated while we had it locked - "
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen file_lock_method_to_str(log->index->lock_method));
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen /* the newly created log file is already locked */
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen "rotating while syncing");
60ba197d17023594231d9805d889817782e41859Timo Sirainenmail_transaction_log_refresh(struct mail_transaction_log *log, bool nfs_flush,
60ba197d17023594231d9805d889817782e41859Timo Sirainen if (MAIL_TRANSACTION_LOG_FILE_IN_MEMORY(log->head)) {
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen *reason_r = t_strdup_printf("stat(%s) failed: %m", log->filepath);
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen /* see if the whole directory got deleted */
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen if (nfs_safe_stat(log->index->dir, &st) < 0 &&
4ef1f9f3293965734e6e3c38c191ceb2246a721fTeemu Huovila /* the file should always exist at this point. if it doesn't,
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen someone deleted it manually while the index was open. try to
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen handle this nicely by creating a new log file. */
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen if (mail_transaction_log_create(log, FALSE) < 0) {
4ef1f9f3293965734e6e3c38c191ceb2246a721fTeemu Huovila /* NFS: log files get rotated to .log.2 files instead
09aed882b99e865ff6d7140ae2f77a42c9e7d1a7Teemu Huovila of being unlinked, so we don't bother checking if
09aed882b99e865ff6d7140ae2f77a42c9e7d1a7Teemu Huovila the existing file has already been unlinked here
09aed882b99e865ff6d7140ae2f77a42c9e7d1a7Teemu Huovila (in which case inodes could match but point to
4ef1f9f3293965734e6e3c38c191ceb2246a721fTeemu Huovila different files) */
eeb03434472130f9631f164440566fd8d09e6380Timo Sirainen file = mail_transaction_log_file_alloc(log, log->filepath);
eeb03434472130f9631f164440566fd8d09e6380Timo Sirainen if (mail_transaction_log_file_open(file, reason_r) <= 0) {
const char **reason_r)
const char *reason;
int ret;
return ret;
const char *lock_reason)
const char *reason;
int ret = 0;
if (ret < 0)
return ret;
const char *lock_reason,
const char *reason;
const char *lock_reason)
*mtime_r = 0;