[dovecot-cvs] dovecot: Moved mail transaction log file related code to its own...
dovecot at dovecot.org
dovecot at dovecot.org
Mon Jun 11 06:22:17 EEST 2007
details: http://hg.dovecot.org/dovecot/rev/d28185a3131a
changeset: 5687:d28185a3131a
user: Timo Sirainen <tss at iki.fi>
date: Mon Jun 11 06:21:46 2007 +0300
description:
Moved mail transaction log file related code to its own file.
diffstat:
4 files changed, 970 insertions(+), 952 deletions(-)
src/lib-index/Makefile.am | 1
src/lib-index/mail-transaction-log-file.c | 942 +++++++++++++++++++++++++
src/lib-index/mail-transaction-log-private.h | 27
src/lib-index/mail-transaction-log.c | 952 --------------------------
diffs (truncated from 1976 to 300 lines):
diff -r 0d2a6a7f2a1b -r d28185a3131a src/lib-index/Makefile.am
--- a/src/lib-index/Makefile.am Mon Jun 11 06:07:40 2007 +0300
+++ b/src/lib-index/Makefile.am Mon Jun 11 06:21:46 2007 +0300
@@ -28,6 +28,7 @@ libindex_a_SOURCES = \
mail-index-view-sync.c \
mail-transaction-log.c \
mail-transaction-log-append.c \
+ mail-transaction-log-file.c \
mail-transaction-log-view.c \
mail-transaction-util.c \
mailbox-list-index.c \
diff -r 0d2a6a7f2a1b -r d28185a3131a src/lib-index/mail-transaction-log-file.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-index/mail-transaction-log-file.c Mon Jun 11 06:21:46 2007 +0300
@@ -0,0 +1,942 @@
+/* Copyright (C) 2003-2007 Timo Sirainen */
+
+#include "lib.h"
+#include "ioloop.h"
+#include "buffer.h"
+#include "file-dotlock.h"
+#include "nfs-workarounds.h"
+#include "read-full.h"
+#include "write-full.h"
+#include "mmap-util.h"
+#include "mail-index-private.h"
+#include "mail-transaction-log-private.h"
+
+#define LOG_PREFETCH 1024
+
+void
+mail_transaction_log_file_set_corrupted(struct mail_transaction_log_file *file,
+ const char *fmt, ...)
+{
+ va_list va;
+
+ file->hdr.indexid = 0;
+ if (!MAIL_TRANSACTION_LOG_FILE_IN_MEMORY(file)) {
+ if (pwrite_full(file->fd, &file->hdr.indexid,
+ sizeof(file->hdr.indexid),
+ offsetof(struct mail_transaction_log_header,
+ indexid)) < 0) {
+ mail_index_file_set_syscall_error(file->log->index,
+ file->filepath, "pwrite()");
+ }
+ }
+
+ va_start(va, fmt);
+ t_push();
+ mail_index_set_error(file->log->index,
+ "Corrupted transaction log file %s: %s",
+ file->filepath, t_strdup_vprintf(fmt, va));
+ t_pop();
+ va_end(va);
+
+ if (file->log->index->log != NULL && file->log->index->map != NULL) {
+ /* this may have happened because of broken index.
+ make sure it's ok. */
+ (void)mail_index_fsck(file->log->index);
+ }
+}
+
+struct mail_transaction_log_file *
+mail_transaction_log_file_alloc(struct mail_transaction_log *log,
+ const char *path)
+{
+ struct mail_transaction_log_file *file;
+
+ file = i_new(struct mail_transaction_log_file, 1);
+ file->log = log;
+ file->filepath = i_strdup(path);
+ file->fd = -1;
+ return file;
+}
+
+void mail_transaction_log_file_free(struct mail_transaction_log_file *file)
+{
+ struct mail_transaction_log_file **p;
+ int old_errno = errno;
+
+ mail_transaction_log_file_unlock(file);
+
+ for (p = &file->log->files; *p != NULL; p = &(*p)->next) {
+ if (*p == file) {
+ *p = file->next;
+ break;
+ }
+ }
+
+ if (file == file->log->head)
+ file->log->head = NULL;
+
+ if (file->buffer != NULL)
+ buffer_free(file->buffer);
+
+ if (file->mmap_base != NULL) {
+ if (munmap(file->mmap_base, file->mmap_size) < 0) {
+ mail_index_file_set_syscall_error(file->log->index,
+ file->filepath,
+ "munmap()");
+ }
+ }
+
+ if (file->fd != -1) {
+ if (close(file->fd) < 0) {
+ mail_index_file_set_syscall_error(file->log->index,
+ file->filepath,
+ "close()");
+ }
+ }
+
+ i_free(file->filepath);
+ i_free(file);
+
+ errno = old_errno;
+}
+
+void
+mail_transaction_log_file_add_to_list(struct mail_transaction_log_file *file)
+{
+ struct mail_transaction_log *log = file->log;
+ struct mail_transaction_log_file **p;
+
+ if (log->index->map != NULL &&
+ file->hdr.file_seq == log->index->map->hdr.log_file_seq &&
+ log->index->map->hdr.log_file_int_offset != 0) {
+ /* we can get a valid log offset from index file. initialize
+ sync_offset from it so we don't have to read the whole log
+ file from beginning. */
+ file->sync_offset = log->index->map->hdr.log_file_int_offset;
+ } else {
+ file->sync_offset = file->hdr.hdr_size;
+ }
+
+ /* insert it to correct position */
+ for (p = &log->files; *p != NULL; p = &(*p)->next) {
+ if ((*p)->hdr.file_seq > file->hdr.file_seq)
+ break;
+ i_assert((*p)->hdr.file_seq < file->hdr.file_seq);
+ }
+
+ file->next = *p;
+ *p = file;
+}
+
+static int
+mail_transaction_log_init_hdr(struct mail_transaction_log *log,
+ struct mail_transaction_log_header *hdr)
+{
+ struct mail_index *index = log->index;
+ unsigned int lock_id;
+
+ memset(hdr, 0, sizeof(*hdr));
+ hdr->major_version = MAIL_TRANSACTION_LOG_MAJOR_VERSION;
+ hdr->minor_version = MAIL_TRANSACTION_LOG_MINOR_VERSION;
+ hdr->hdr_size = sizeof(struct mail_transaction_log_header);
+ hdr->indexid = log->index->indexid;
+ hdr->create_stamp = ioloop_time;
+
+ if (index->fd != -1) {
+ /* not creating index - make sure we have latest header */
+ if (mail_index_lock_shared(index, TRUE, &lock_id) < 0)
+ return -1;
+ if (mail_index_map(index, FALSE) <= 0) {
+ mail_index_unlock(index, lock_id);
+ return -1;
+ }
+ }
+ hdr->prev_file_seq = index->hdr->log_file_seq;
+ hdr->prev_file_offset = index->hdr->log_file_int_offset;
+ hdr->file_seq = index->hdr->log_file_seq+1;
+
+ if (index->fd != -1)
+ mail_index_unlock(index, lock_id);
+
+ if (log->head != NULL && hdr->file_seq <= log->head->hdr.file_seq) {
+ /* make sure the sequence grows */
+ hdr->file_seq = log->head->hdr.file_seq+1;
+ }
+ return 0;
+}
+
+struct mail_transaction_log_file *
+mail_transaction_log_file_alloc_in_memory(struct mail_transaction_log *log)
+{
+ struct mail_transaction_log_file *file;
+
+ file = i_new(struct mail_transaction_log_file, 1);
+ file->log = log;
+ file->filepath = i_strdup("(in-memory transaction log file)");
+ file->fd = -1;
+
+ if (mail_transaction_log_init_hdr(log, &file->hdr) < 0) {
+ i_free(file);
+ return NULL;
+ }
+
+ file->buffer = buffer_create_dynamic(default_pool, 4096);
+ file->buffer_offset = sizeof(file->hdr);
+
+ mail_transaction_log_file_add_to_list(file);
+ return file;
+}
+
+static int
+mail_transaction_log_file_dotlock(struct mail_transaction_log_file *file)
+{
+ int ret;
+
+ if (file->log->dotlock_count > 0)
+ ret = 1;
+ else {
+ ret = file_dotlock_create(&file->log->dotlock_settings,
+ file->filepath, 0,
+ &file->log->dotlock);
+ }
+ if (ret > 0) {
+ file->log->dotlock_count++;
+ file->locked = TRUE;
+ return 0;
+ }
+ if (ret < 0) {
+ mail_index_file_set_syscall_error(file->log->index,
+ file->filepath,
+ "file_dotlock_create()");
+ return -1;
+ }
+
+ mail_index_set_error(file->log->index,
+ "Timeout while waiting for release of "
+ "dotlock for transaction log file %s",
+ file->filepath);
+ file->log->index->index_lock_timeout = TRUE;
+ return -1;
+}
+
+static int
+mail_transaction_log_file_undotlock(struct mail_transaction_log_file *file)
+{
+ int ret;
+
+ if (--file->log->dotlock_count > 0)
+ return 0;
+
+ ret = file_dotlock_delete(&file->log->dotlock);
+ if (ret < 0) {
+ mail_index_file_set_syscall_error(file->log->index,
+ file->filepath, "file_dotlock_delete()");
+ return -1;
+ }
+
+ if (ret == 0) {
+ mail_index_set_error(file->log->index,
+ "Dotlock was lost for transaction log file %s",
+ file->filepath);
+ return -1;
+ }
+ return 0;
+}
+
+int mail_transaction_log_file_lock(struct mail_transaction_log_file *file)
+{
+ int ret;
+
+ if (file->locked)
+ return 0;
+
+ if (MAIL_TRANSACTION_LOG_FILE_IN_MEMORY(file)) {
+ file->locked = TRUE;
+ return 0;
+ }
+
+ if (file->log->index->lock_method == FILE_LOCK_METHOD_DOTLOCK)
+ return mail_transaction_log_file_dotlock(file);
+
+ i_assert(file->file_lock == NULL);
+ ret = mail_index_lock_fd(file->log->index, file->filepath, file->fd,
+ F_WRLCK, MAIL_INDEX_LOCK_SECS,
+ &file->file_lock);
+ if (ret > 0) {
+ file->locked = TRUE;
+ return 0;
+ }
+ if (ret < 0) {
+ mail_index_file_set_syscall_error(file->log->index,
+ file->filepath,
+ "mail_index_wait_lock_fd()");
+ return -1;
+ }
+
+ mail_index_set_error(file->log->index,
+ "Timeout while waiting for lock for transaction log file %s",
+ file->filepath);
+ file->log->index->index_lock_timeout = TRUE;
+ return -1;
+}
+
+void mail_transaction_log_file_unlock(struct mail_transaction_log_file *file)
+{
+ if (!file->locked)
More information about the dovecot-cvs
mailing list