mail-transaction-log.c revision c1d45cada20777e1973579d40d0ebe43f89bb053
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoo/* Copyright (C) 2003-2004 Timo Sirainen */
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoomail_transaction_log_file_open_or_create(struct mail_transaction_log *log,
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoo const char *path);
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoostatic int mail_transaction_log_rotate(struct mail_transaction_log *log);
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoomail_transaction_log_file_lock(struct mail_transaction_log_file *file,
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoostatic int mail_transaction_log_lock_head(struct mail_transaction_log *log);
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoomail_transaction_log_file_set_corrupted(struct mail_transaction_log_file *file,
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoo const char *fmt, ...)
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoo mail_index_file_set_syscall_error(file->log->index,
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoo "Corrupted transaction log file %s: %s",
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoostatic int mail_transaction_log_check_file_seq(struct mail_transaction_log *log)
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoo unsigned int lock_id;
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoo ret = mail_index_lock_shared(index, TRUE, &lock_id);
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoo else if (file->hdr.file_seq != index->hdr->log_file_seq) {
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoo /* broken - fix it by creating a new log file */
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoo (void)mail_transaction_log_file_lock(file, F_UNLCK);
1bc07a5b8dbaef4b6eb6d30a260e9c2153ed368bKATOH Yasufumimail_transaction_log_open_or_create(struct mail_index *index)
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoo const char *path;
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoo log->head = mail_transaction_log_file_open_or_create(log, path);
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoo log->head->hdr.file_seq != index->hdr->log_file_seq) {
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoo /* head log file isn't same as head index file -
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoo shouldn't happen except in race conditions. lock them and
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoo check again - FIXME: missing error handling.
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoo FIXME: index->hdr check crashes if we created the log */
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoovoid mail_transaction_log_close(struct mail_transaction_log *log)
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoomail_transaction_log_file_lock(struct mail_transaction_log_file *file,
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoo ret = file_wait_lock_full(file->fd, lock_type, DEFAULT_LOCK_TIMEOUT,
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoo mail_index_file_set_syscall_error(file->log->index,
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoo "file_wait_lock()");
1bc07a5b8dbaef4b6eb6d30a260e9c2153ed368bKATOH Yasufumi "Timeout while waiting for release of "
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoo "%s fcntl() lock for transaction log file %s",
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoomail_transaction_log_file_close(struct mail_transaction_log_file *file)
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoo mail_index_file_set_syscall_error(file->log->index,
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoomail_transaction_log_file_read_hdr(struct mail_transaction_log_file *file,
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoo ret = pread_full(file->fd, &file->hdr, sizeof(file->hdr), 0);
1bc07a5b8dbaef4b6eb6d30a260e9c2153ed368bKATOH Yasufumi if (mail_transaction_log_file_lock(file, F_RDLCK) < 0)
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoo ret = pread_full(file->fd, &file->hdr, sizeof(file->hdr), 0);
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoo (void)mail_transaction_log_file_lock(file, F_UNLCK);
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoo // FIXME: handle ESTALE
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoo mail_index_file_set_syscall_error(file->log->index,
1bc07a5b8dbaef4b6eb6d30a260e9c2153ed368bKATOH Yasufumi "unexpected end of file while reading header");
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoo /* corrupted */
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoo "Transaction log file %s: marked corrupted",
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoo if (file->hdr.indexid != file->log->index->indexid &&
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoo /* either index was just recreated, or transaction has wrong
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoo indexid. we don't know here which one is the case, so we'll
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoo just fail. If index->indexid == 0, we're rebuilding it and
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoo we just want to lock the transaction log. */
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoo "Transaction log file %s: invalid indexid",
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoo "used_size (%u) < old_size (%u)",
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoostatic int mail_transaction_log_file_create(struct mail_transaction_log *log,
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoo const char *path,
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoo unsigned int lock_id;
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoo /* this lock should never exist for a long time.. */
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoo fd = file_dotlock_open(path, NULL, 30, 0, 120, NULL, NULL);
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoo "file_dotlock_open()");
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoo /* log creation is locked now - see if someone already created it */
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoo } else if (st.st_dev == dev && st.st_ino == ino) {
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoo /* same file, still broken */
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoo mail_index_file_set_syscall_error(index, path, "open()");
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoo index->log_locked = TRUE; /* kludging around assert.. */
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoo if (mail_index_lock_exclusive(index, 0, 0, &lock_id) < 0) {
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoo /* update log_file_* fields in header */
77fbb4d2d9580887b984ee29cf36042d1384de06Sungbae Yoo if (mail_index_write_header(index, &idx_hdr) < 0)
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoo /* creating new index file */
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoo mail_index_file_set_syscall_error(index, path, "write_full()");
2b371b262f7272266ff18cc2aff65176a2c16383Sungbae Yoo mail_index_file_set_syscall_error(index, path, "dup()");
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;
struct mail_transaction_log_file **p;
if ((*p)->refcount != 0)
p = &(*p)->next;
*p = (*p)->next;
int fd;
const char *path;
int ret;
void *data;
int ret;
ret = 0;
if (ret <= 0)
return ret;
size = 0;
if (size == 0)
ret = 0;
return ret;
if (!use_mmap) {
if (ret <= 0) {
return ret;
int ret = 0;
if (ret < 0)
return ret;
const void *data;
int ret;
return ret;
unsigned char *data;
expunges_before = 0;
exp++;
if (!two)
if (expunges_before != 0) {
if (uids) {
if (two) {
exp2++;
if (count != 0) {
if (uids) {
struct mail_index_transaction *t)
sizeof(struct mail_transaction_flag_update),
sizeof(struct mail_transaction_cache_update),
sizeof(struct mail_transaction_expunge),
const void *data;
if (size == 0)
size = 0;
if (external)
if (size != 0) {
int ret;
ret = 0;
if (ret == 0) {
t->hide_transaction) {
if (ret < 0) {
return ret;