int mail_transaction_log_create(struct mail_transaction_log *log, bool reset) { struct mail_transaction_log_file *file; if (MAIL_INDEX_IS_IN_MEMORY(log->index)) { file = mail_transaction_log_file_alloc_in_memory(log); mail_transaction_log_set_head(log, file); return 0; } file = mail_transaction_log_file_alloc(log, log->filepath); if (log->open_file != NULL) { /* remember what file we tried to open. if someone else created a new file, use it instead of recreating it */ file->st_ino = log->open_file->st_ino; file->st_dev = log->open_file->st_dev; file->last_size = log->open_file->last_size; file->last_mtime = log->open_file->last_mtime; mail_transaction_log_file_free(&log->open_file); } if (mail_transaction_log_file_create(file, reset) < 0) { mail_transaction_log_file_free(&file); return -1; } mail_transaction_log_set_head(log, file); return 1; }
int mail_transaction_log_rotate(struct mail_transaction_log *log, bool reset) { struct mail_transaction_log_file *file; const char *path = log->head->filepath; struct stat st; int ret; i_assert(log->head->locked); if (MAIL_INDEX_IS_IN_MEMORY(log->index)) { file = mail_transaction_log_file_alloc_in_memory(log); if (reset) { file->hdr.prev_file_seq = 0; file->hdr.prev_file_offset = 0; } } else { /* we're locked, we shouldn't need to worry about ESTALE problems in here. */ if (fstat(log->head->fd, &st) < 0) { mail_index_file_set_syscall_error(log->index, log->head->filepath, "fstat()"); return -1; } file = mail_transaction_log_file_alloc(log, path); file->st_dev = st.st_dev; file->st_ino = st.st_ino; file->last_mtime = st.st_mtime; file->last_size = st.st_size; if ((ret = mail_transaction_log_file_create(file, reset)) < 0) { mail_transaction_log_file_free(&file); return -1; } if (ret == 0) { mail_index_set_error(log->index, "Transaction log %s was recreated while we had it locked - " "locking is broken (lock_method=%s)", path, file_lock_method_to_str(log->index->lock_method)); mail_transaction_log_file_free(&file); return -1; } i_assert(file->locked); } if (--log->head->refcount == 0) mail_transaction_logs_clean(log); else { /* the newly created log file is already locked */ mail_transaction_log_file_unlock(log->head, !log->index->log_sync_locked ? "rotating" : "rotating while syncing"); } mail_transaction_log_set_head(log, file); return 0; }
int mail_transaction_log_rotate(struct mail_transaction_log *log, bool reset) { struct mail_transaction_log_file *file; const char *path = log->head->filepath; struct stat st; i_assert(log->head->locked); if (MAIL_INDEX_IS_IN_MEMORY(log->index)) { file = mail_transaction_log_file_alloc_in_memory(log); if (reset) { file->hdr.prev_file_seq = 0; file->hdr.prev_file_offset = 0; } } else { /* we're locked, we shouldn't need to worry about ESTALE problems in here. */ if (fstat(log->head->fd, &st) < 0) { mail_index_file_set_syscall_error(log->index, log->head->filepath, "fstat()"); return -1; } file = mail_transaction_log_file_alloc(log, path); file->st_dev = st.st_dev; file->st_ino = st.st_ino; file->last_mtime = st.st_mtime; file->last_size = st.st_size; if (mail_transaction_log_file_create(file, reset) < 0) { mail_transaction_log_file_free(&file); return -1; } } if (--log->head->refcount == 0) mail_transaction_logs_clean(log); else mail_transaction_log_file_unlock(log->head); mail_transaction_log_set_head(log, file); return 0; }
void mail_transaction_log_move_to_memory(struct mail_transaction_log *log) { struct mail_transaction_log_file *file; if (!log->index->initial_mapped && log->files != NULL && log->files->hdr.prev_file_seq != 0) { /* we couldn't read dovecot.index and we don't have the first .log file, so just start from scratch */ mail_transaction_log_close(log); } i_free(log->filepath); i_free(log->filepath2); log->filepath = i_strconcat(log->index->filepath, MAIL_TRANSACTION_LOG_SUFFIX, NULL); log->filepath2 = i_strconcat(log->filepath, ".2", NULL); if (log->head != NULL) mail_transaction_log_file_move_to_memory(log->head); else { file = mail_transaction_log_file_alloc_in_memory(log); mail_transaction_log_set_head(log, file); } }