mail-transaction-log.c revision 3302ef441d062a93fd9928223993798ee5dd77e4
bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (C) 2003-2004 Timo Sirainen */
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi/* this lock should never exist for a long time.. */
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomimail_transaction_log_file_open_or_create(struct mail_transaction_log *log,
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi const char *path);
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomistatic int mail_transaction_log_rotate(struct mail_transaction_log *log,
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomistatic int mail_transaction_log_lock_head(struct mail_transaction_log *log);
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomimail_transaction_log_file_set_corrupted(struct mail_transaction_log_file *file,
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi const char *fmt, ...)
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi mail_index_file_set_syscall_error(file->log->index,
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi "Corrupted transaction log file %s: %s",
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi /* this may have happened because of broken index. make sure it's ok. */
45ba3f8b55734aa2c96b6fc510919565ba70038cTimo Sirainenmail_transaction_log_file_dotlock(struct mail_transaction_log_file *file)
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi ret = file_lock_dotlock(file->filepath, NULL, FALSE,
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi mail_index_file_set_syscall_error(file->log->index,
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi "file_lock_dotlock()");
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi "Timeout while waiting for release of "
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi "dotlock for transaction log file %s",
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomimail_transaction_log_file_undotlock(struct mail_transaction_log_file *file)
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi ret = file_unlock_dotlock(file->filepath, &file->log->dotlock);
c50acc5547b9d92784825a09e3de97db0a806f4eTimo Sirainen mail_index_file_set_syscall_error(file->log->index,
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi if (ret == 0) {
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi "Dotlock was lost for transaction log file %s",
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomimail_transaction_log_file_lock(struct mail_transaction_log_file *file)
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi if (file->log->index->lock_method == MAIL_INDEX_LOCK_DOTLOCK)
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi ret = mail_index_lock_fd(file->log->index, file->filepath, file->fd,
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi mail_index_file_set_syscall_error(file->log->index,
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi "mail_index_wait_lock_fd()");
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi "Timeout while waiting for release of "
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi "fcntl() lock for transaction log file %s",
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomimail_transaction_log_file_unlock(struct mail_transaction_log_file *file)
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi if (file->log->index->lock_method == MAIL_INDEX_LOCK_DOTLOCK) {
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi ret = mail_index_lock_fd(file->log->index, file->filepath, file->fd,
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi if (ret <= 0) {
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi mail_index_file_set_syscall_error(file->log->index,
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi "mail_index_wait_lock_fd()");
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi !(((file)->hdr.file_seq == (index)->hdr->log_file_seq && \
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi sizeof(struct mail_transaction_log_header)) || \
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi ((file)->hdr.prev_file_seq == (index)->hdr->log_file_seq && \
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi (file)->hdr.prev_file_offset == (index)->hdr->log_file_int_offset))
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomistatic int mail_transaction_log_check_file_seq(struct mail_transaction_log *log)
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi unsigned int lock_id;
36aa1b351b8e9d02a93aa17e5de8a06ac5440084Timo Sirainen ret = mail_index_lock_shared(index, TRUE, &lock_id);
36aa1b351b8e9d02a93aa17e5de8a06ac5440084Timo Sirainen else if (INDEX_HAS_MISSING_LOGS(index, file)) {
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi /* broken - fix it by creating a new log file */
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomimail_transaction_log_open_or_create(struct mail_index *index)
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi const char *path;
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi log->head = mail_transaction_log_file_open_or_create(log, path);
54bd0fec0be357266e299466a582f3c9269884e9Timo Sirainen /* head log file isn't same as head index file -
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi shouldn't happen except in race conditions. lock them and
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi check again - FIXME: missing error handling. */
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomivoid mail_transaction_log_close(struct mail_transaction_log *log)
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomimail_transaction_log_file_close(struct mail_transaction_log_file *file)
2974dca6be5120e49279f06c8aa952e5fac56048Timo Sirainen if (munmap(file->mmap_base, file->mmap_size) < 0) {
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi mail_index_file_set_syscall_error(file->log->index,
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi "munmap()");
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi mail_index_file_set_syscall_error(file->log->index,
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomimail_transaction_log_file_read_hdr(struct mail_transaction_log_file *file)
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi ret = pread_full(file->fd, &file->hdr, sizeof(file->hdr), 0);
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi // FIXME: handle ESTALE
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi mail_index_file_set_syscall_error(file->log->index,
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi "pread_full()");
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi if (ret == 0) {
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi "unexpected end of file while reading header");
unsigned int lock_id;
fd);
return fd2;
if (ret < 0)
if (fd2 < 0) {
return fd2;
if (fd2 < 0) {
return fd2;
static struct mail_transaction_log_file *
struct mail_transaction_log_file **p;
int ret;
return NULL;
if (ret == 0) {
if (ret <= 0) {
return NULL;
*p = file;
return file;
static struct mail_transaction_log_file *
const char *path)
int fd;
return NULL;
return NULL;
if ((*p)->refcount != 0)
p = &(*p)->next;
*p = next;
int fd;
if (lock) {
unsigned int lock_id;
int ret;
return ret;
const char *path;
const void *data;
if (hdr_size == 0) {
void *data;
int ret;
if (ret == 0) {
if (ret < 0) {
if (ret > 0)
if (ret == 0) {
if (!use_mmap) {
if (ret <= 0) {
return ret;
MADV_SEQUENTIAL) < 0) {
int ret = 0;
if (ret < 0)
return ret;
if (size == 0)
hdr_data_size = 0;
if (external)
hdr_size =
if (hdr_data_size > 0) {
static const buffer_t *
struct mail_transaction_header_update u;
int state = 0;
memset(&u, 0, sizeof(u));
if (state == 0) {
state++;
if (state > 0) {
u.size);
state = 0;
return buf;
struct mail_index_transaction *t,
size = 0;
if (reset_id != 0) {
t->external);
struct mail_index_transaction *t)
update_count = 0;
resize_count = 0;
reset_count = 0;
t->external) < 0)
struct mail_index_transaction *t)
size = 0;
reset_count = 0;
t->external) < 0)
struct mail_index_transaction *t)
for (i = 0; i < size; i++) {
t->external) < 0)
unsigned int lock_id;
int ret;
if (!t->log_updates) {
*log_file_seq_r = 0;
*log_file_offset_r = 0;
ret = 0;
t->external);
t->external);
if (ret < 0) {
t->hide_transaction) {
if (ret < 0) {
if (ret < 0)
return ret;