mail-transaction-log-file.c revision 94aa90d2d17a7aebcda5a4193a62e80ddbb169b7
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (c) 2003-2008 Dovecot authors, see the included COPYING file */
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen#define MEMORY_LOG_NAME "(in-memory transaction log file)"
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenmail_transaction_log_file_set_corrupted(struct mail_transaction_log_file *file,
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen const char *fmt, ...)
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen if (!MAIL_TRANSACTION_LOG_FILE_IN_MEMORY(file)) {
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen /* indexid=0 marks the log file as corrupted */
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen mail_index_file_set_syscall_error(file->log->index,
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen "Corrupted transaction log file %s: %s",
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenmail_transaction_log_file_alloc(struct mail_transaction_log *log,
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen file = i_new(struct mail_transaction_log_file, 1);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenvoid mail_transaction_log_file_free(struct mail_transaction_log_file **_file)
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen struct mail_transaction_log_file *file = *_file;
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen for (p = &file->log->files; *p != NULL; p = &(*p)->next) {
e07bf3772a2bc075de4915ad0961beb8d083c22dTimo Sirainen if (munmap(file->mmap_base, file->mmap_size) < 0) {
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen mail_index_file_set_syscall_error(file->log->index,
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen mail_index_file_set_syscall_error(file->log->index,
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainenmail_transaction_log_file_add_to_list(struct mail_transaction_log_file *file)
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen if (map != NULL && file->hdr.file_seq == map->hdr.log_file_seq &&
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen /* we can get a valid log offset from index file. initialize
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen sync_offset from it so we don't have to read the whole log
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen file from beginning. */
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen if (map->hdr.log_file_head_offset >= file->hdr.hdr_size)
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen file->sync_offset = map->hdr.log_file_head_offset;
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen "%s: log_file_head_offset too small",
d66be2bebfa96e7d3d20e2153f60e6e25dcc9a18Timo Sirainen file->saved_tail_offset = map->hdr.log_file_tail_offset;
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen /* insert it to correct position */
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen for (p = &log->files; *p != NULL; p = &(*p)->next) {
fd35227c47190afc832579ca5c76524792701bf7Timo Sirainen i_assert((*p)->hdr.file_seq < file->hdr.file_seq);
2e263a9d901483a902720a30c474761bd3324fe8Timo Sirainenmail_transaction_log_init_hdr(struct mail_transaction_log *log,
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen hdr->major_version = MAIL_TRANSACTION_LOG_MAJOR_VERSION;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen hdr->minor_version = MAIL_TRANSACTION_LOG_MINOR_VERSION;
d66be2bebfa96e7d3d20e2153f60e6e25dcc9a18Timo Sirainen hdr->hdr_size = sizeof(struct mail_transaction_log_header);
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen /* not creating index - make sure we have latest header */
ce3faaaaab3e2d45b023396287e02f88e5c76e74Timo Sirainen /* if we got here from mapping, the .log file is
ce3faaaaab3e2d45b023396287e02f88e5c76e74Timo Sirainen corrupted. use whatever values we got from index
3e7565a7b39694bcdf448d8eb2a7f0774733297bTimo Sirainen hdr->prev_file_seq = index->map->hdr.log_file_seq;
3e7565a7b39694bcdf448d8eb2a7f0774733297bTimo Sirainen hdr->prev_file_offset = index->map->hdr.log_file_head_offset;
3e7565a7b39694bcdf448d8eb2a7f0774733297bTimo Sirainen hdr->file_seq = index->map->hdr.log_file_seq + 1;
3e7565a7b39694bcdf448d8eb2a7f0774733297bTimo Sirainen if (log->head != NULL && hdr->file_seq <= log->head->hdr.file_seq) {
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen /* make sure the sequence grows */
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainenmail_transaction_log_file_alloc_in_memory(struct mail_transaction_log *log)
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen file = mail_transaction_log_file_alloc(log, MEMORY_LOG_NAME);
2e263a9d901483a902720a30c474761bd3324fe8Timo Sirainen if (mail_transaction_log_init_hdr(log, &file->hdr) < 0) {
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen file->buffer = buffer_create_dynamic(default_pool, 4096);
3e7565a7b39694bcdf448d8eb2a7f0774733297bTimo Sirainenmail_transaction_log_file_dotlock(struct mail_transaction_log_file *file)
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen ret = file_dotlock_create(&file->log->dotlock_settings,
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen mail_index_file_set_syscall_error(file->log->index,
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen "file_dotlock_create()");
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen "Timeout while waiting for "
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen "dotlock for transaction log file %s",
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainenmail_transaction_log_file_undotlock(struct mail_transaction_log_file *file)
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen ret = file_dotlock_delete(&file->log->dotlock);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen mail_index_file_set_syscall_error(file->log->index,
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen "Dotlock was lost for transaction log file %s",
cbc61fcb33b370d049c16a3c44568b4deb4e2b33Timo Sirainenint mail_transaction_log_file_lock(struct mail_transaction_log_file *file)
bd4d0a1a7c0626452b8d82f37e3ec07267ac9896Timo Sirainen if (MAIL_TRANSACTION_LOG_FILE_IN_MEMORY(file)) {
bd4d0a1a7c0626452b8d82f37e3ec07267ac9896Timo Sirainen if (file->log->index->lock_method == FILE_LOCK_METHOD_DOTLOCK)
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen return mail_transaction_log_file_dotlock(file);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen ret = mail_index_lock_fd(file->log->index, file->filepath, file->fd,
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen mail_index_file_set_syscall_error(file->log->index,
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen "mail_index_wait_lock_fd()");
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen "Timeout while waiting for lock for transaction log file %s",
56963ffad65b860c827553dfaf09fb766cb7e20eTimo Sirainenvoid mail_transaction_log_file_unlock(struct mail_transaction_log_file *file)
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen if (MAIL_TRANSACTION_LOG_FILE_IN_MEMORY(file))
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen if (file->log->index->lock_method == FILE_LOCK_METHOD_DOTLOCK) {
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainenmail_transaction_log_file_read_hdr(struct mail_transaction_log_file *file,
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen i_assert(!MAIL_TRANSACTION_LOG_FILE_IN_MEMORY(file));
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen ret = pread_full(file->fd, &file->hdr, sizeof(file->hdr), 0);
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen mail_index_file_set_syscall_error(file->log->index,
9514dbd41faad453406fc3a10aca791417a9ce75Timo Sirainen "pread_full()");
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen "unexpected end of file while reading header");
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen if (file->hdr.major_version != MAIL_TRANSACTION_LOG_MAJOR_VERSION) {
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen /* incompatible version - fix silently */
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen if (file->hdr.hdr_size < MAIL_TRANSACTION_LOG_HEADER_MIN_SIZE) {
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen "Header size too small");
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen /* @UNSAFE: smaller than we expected - zero out the fields we
783278c012551bc2f25f065a8d3ec1a3cfc0d296Timo Sirainen shouldn't have filled */
783278c012551bc2f25f065a8d3ec1a3cfc0d296Timo Sirainen memset(PTR_OFFSET(&file->hdr, file->hdr.hdr_size), 0,
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen /* corrupted */
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen "Transaction log file %s: marked corrupted",
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen if (file->hdr.indexid != file->log->index->indexid) {
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen /* index file was probably just rebuilt and we don't
5666a3d6a7ea89362b8d9e8b39b15424cd9d6388Timo Sirainen know about it yet */
5666a3d6a7ea89362b8d9e8b39b15424cd9d6388Timo Sirainen "indexid changed %u -> %u",
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen file->log->index->indexid, file->hdr.indexid);
5666a3d6a7ea89362b8d9e8b39b15424cd9d6388Timo Sirainen /* creating index file. since transaction log is created
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen first, use the indexid in it to create the main index
bool ignore_estale)
return TRUE;
return FALSE;
const char *path2;
bool rename_existing;
if (reset)
FALSE) > 0 &&
if (reset) {
if (ret < 0)
if (rename_existing) {
path2);
bool reset)
int fd;
bool check_existing)
bool ignore_estale;
int ret;
else if (check_existing &&
if (ret > 0) {
if (ret == 0) {
i == MAIL_INDEX_ESTALE_RETRY_COUNT) {
const unsigned int offset_pos =
sizeof(sync_offset));
unsigned int trans_size)
int ret;
sizeof(*hdr));
if (ret != 0)
const void *data;
if (trans_size == 0) {
trans_size) < 0)
trans_size = 0;
if (trans_size != 0) {
void *data;
if (ret > 0) {
if (ret == 0) {
void *data;
if (ret > 0)
if (ret < 0) {
return TRUE;
return TRUE;
return FALSE;
int ret;
if (ret <= 0)
return ret;
return ret;
MADV_SEQUENTIAL) < 0) {
int ret;
if (ret > 0)
FALSE);
} while (ret == 0);
int ret;
end_offset) == 0)
*file)