mail-transaction-log-file.c revision d98109d230575391c1dfe1bea3800d3ff0ac3f11
89a126810703c666309310d0f3189e9834d70b5bTimo Sirainen/* Copyright (c) 2003-2007 Dovecot authors, see the included COPYING file */
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen#define MEMORY_LOG_NAME "(in-memory transaction log file)"
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainenmail_transaction_log_file_set_corrupted(struct mail_transaction_log_file *file,
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen const char *fmt, ...)
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen if (!MAIL_TRANSACTION_LOG_FILE_IN_MEMORY(file)) {
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen /* indexid=0 marks the log file as corrupted */
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen mail_index_file_set_syscall_error(file->log->index,
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen "Corrupted transaction log file %s: %s",
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainenmail_transaction_log_file_alloc(struct mail_transaction_log *log,
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen file = i_new(struct mail_transaction_log_file, 1);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainenvoid mail_transaction_log_file_free(struct mail_transaction_log_file **_file)
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen struct mail_transaction_log_file *file = *_file;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen for (p = &file->log->files; *p != NULL; p = &(*p)->next) {
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen if (munmap(file->mmap_base, file->mmap_size) < 0) {
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen mail_index_file_set_syscall_error(file->log->index,
675b2b1c4587a79478062b05725da61afa5d8045Timo Sirainen mail_index_file_set_syscall_error(file->log->index,
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainenmail_transaction_log_file_add_to_list(struct mail_transaction_log_file *file)
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen if (map != NULL && file->hdr.file_seq == map->hdr.log_file_seq &&
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen /* we can get a valid log offset from index file. initialize
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen sync_offset from it so we don't have to read the whole log
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen file from beginning. */
675b2b1c4587a79478062b05725da61afa5d8045Timo Sirainen if (map->hdr.log_file_head_offset >= file->hdr.hdr_size)
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen file->sync_offset = map->hdr.log_file_head_offset;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen "%s: log_file_head_offset too small",
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen file->saved_tail_offset = map->hdr.log_file_tail_offset;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen /* insert it to correct position */
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen for (p = &log->files; *p != NULL; p = &(*p)->next) {
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen i_assert((*p)->hdr.file_seq < file->hdr.file_seq);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainenmail_transaction_log_init_hdr(struct mail_transaction_log *log,
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen hdr->major_version = MAIL_TRANSACTION_LOG_MAJOR_VERSION;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen hdr->minor_version = MAIL_TRANSACTION_LOG_MINOR_VERSION;
c2f2a6cdf7dd55a4aabe72495cabb4deaa59cffcTimo Sirainen hdr->hdr_size = sizeof(struct mail_transaction_log_header);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen /* not creating index - make sure we have latest header */
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen /* if we got here from mapping, the .log file is
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen corrupted. use whatever values we got from index
c2f2a6cdf7dd55a4aabe72495cabb4deaa59cffcTimo Sirainen hdr->prev_file_seq = index->map->hdr.log_file_seq;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen hdr->prev_file_offset = index->map->hdr.log_file_head_offset;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen hdr->file_seq = index->map->hdr.log_file_seq + 1;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen if (log->head != NULL && hdr->file_seq <= log->head->hdr.file_seq) {
c2f2a6cdf7dd55a4aabe72495cabb4deaa59cffcTimo Sirainen /* make sure the sequence grows */
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainenmail_transaction_log_file_alloc_in_memory(struct mail_transaction_log *log)
064ccad9cea2a75a0d6caa2c679b6cd22be58174Timo Sirainen file = mail_transaction_log_file_alloc(log, MEMORY_LOG_NAME);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen if (mail_transaction_log_init_hdr(log, &file->hdr) < 0) {
064ccad9cea2a75a0d6caa2c679b6cd22be58174Timo Sirainen file->buffer = buffer_create_dynamic(default_pool, 4096);
064ccad9cea2a75a0d6caa2c679b6cd22be58174Timo Sirainenmail_transaction_log_file_dotlock(struct mail_transaction_log_file *file)
064ccad9cea2a75a0d6caa2c679b6cd22be58174Timo Sirainen ret = file_dotlock_create(&file->log->dotlock_settings,
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen mail_index_file_set_syscall_error(file->log->index,
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen "file_dotlock_create()");
51c331377beb4a2acb81aee4d12bc8ef6c496625Timo Sirainen "Timeout while waiting for release of "
51c331377beb4a2acb81aee4d12bc8ef6c496625Timo Sirainen "dotlock for transaction log file %s",
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainenmail_transaction_log_file_undotlock(struct mail_transaction_log_file *file)
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen ret = file_dotlock_delete(&file->log->dotlock);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen mail_index_file_set_syscall_error(file->log->index,
675b2b1c4587a79478062b05725da61afa5d8045Timo Sirainen "Dotlock was lost for transaction log file %s",
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainenint mail_transaction_log_file_lock(struct mail_transaction_log_file *file)
675b2b1c4587a79478062b05725da61afa5d8045Timo Sirainen if (MAIL_TRANSACTION_LOG_FILE_IN_MEMORY(file)) {
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen if (file->log->index->lock_method == FILE_LOCK_METHOD_DOTLOCK)
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen return mail_transaction_log_file_dotlock(file);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen ret = mail_index_lock_fd(file->log->index, file->filepath, file->fd,
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen mail_index_file_set_syscall_error(file->log->index,
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen "mail_index_wait_lock_fd()");
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen "Timeout while waiting for lock for transaction log file %s",
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainenvoid mail_transaction_log_file_unlock(struct mail_transaction_log_file *file)
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen if (MAIL_TRANSACTION_LOG_FILE_IN_MEMORY(file))
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen if (file->log->index->lock_method == FILE_LOCK_METHOD_DOTLOCK) {
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainenmail_transaction_log_file_read_hdr(struct mail_transaction_log_file *file,
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen i_assert(!MAIL_TRANSACTION_LOG_FILE_IN_MEMORY(file));
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen ret = pread_full(file->fd, &file->hdr, sizeof(file->hdr), 0);
f3aff3c6bf32d5bb0a61993b76a3fbe5ad798c09Timo Sirainen mail_index_file_set_syscall_error(file->log->index,
f3aff3c6bf32d5bb0a61993b76a3fbe5ad798c09Timo Sirainen "pread_full()");
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen "unexpected end of file while reading header");
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen if (file->hdr.major_version != MAIL_TRANSACTION_LOG_MAJOR_VERSION) {
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen /* incompatible version - fix silently */
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen if (file->hdr.hdr_size < MAIL_TRANSACTION_LOG_HEADER_MIN_SIZE) {
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen "Header size too small");
e161a5225abda0837b5deb8746ef808ba5e98d94Timo Sirainen /* @UNSAFE: smaller than we expected - zero out the fields we
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen shouldn't have filled */
e161a5225abda0837b5deb8746ef808ba5e98d94Timo Sirainen memset(PTR_OFFSET(&file->hdr, file->hdr.hdr_size), 0,
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainen /* corrupted */
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainen "Transaction log file %s: marked corrupted",
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen if (file->hdr.indexid != file->log->index->indexid) {
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen /* index file was probably just rebuilt and we don't
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen know about it yet */
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen "indexid changed %u -> %u",
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen file->log->index->indexid, file->hdr.indexid);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen /* creating index file. since transaction log is created
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen first, use the indexid in it to create the main index
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen to avoid races. */
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen file->log->index->indexid = file->hdr.indexid;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen /* make sure we already don't have a file with the same sequence
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen opened. it shouldn't happen unless the old log file was
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen corrupted. */
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen for (f = file->log->files; f != NULL; f = f->next) {
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen /* mark the old file corrupted. we can't safely remove
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen it from the list however, so return failure. */
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen "duplicate transaction log sequence (%u)",
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainenmail_transaction_log_file_stat(struct mail_transaction_log_file *file,
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen mail_index_file_set_syscall_error(file->log->index,
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;
end_offset) == 0)
if (ret > 0) {
if (ret <= 0)
return ret;
} while (ret == 0);
*file)