[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