dovecot: Initial commit for dbox redesign/rewrite. Currently sup...

dovecot at dovecot.org dovecot at dovecot.org
Sat Sep 1 03:04:07 EEST 2007


details:   http://hg.dovecot.org/dovecot/rev/7b71ba1250e3
changeset: 6340:7b71ba1250e3
user:      Timo Sirainen <tss at iki.fi>
date:      Sat Sep 01 03:04:02 2007 +0300
description:
Initial commit for dbox redesign/rewrite. Currently supports only one
message per file mode.

diffstat:

21 files changed, 3761 insertions(+), 4194 deletions(-)
src/lib-storage/index/dbox/Makefile.am         |   15 
src/lib-storage/index/dbox/dbox-file.c         | 1282 +++++++++++++++++----
src/lib-storage/index/dbox/dbox-file.h         |  232 +++
src/lib-storage/index/dbox/dbox-format.h       |   67 -
src/lib-storage/index/dbox/dbox-index.c        |  890 +++++++++++++++
src/lib-storage/index/dbox/dbox-index.h        |  130 ++
src/lib-storage/index/dbox/dbox-keywords.c     |  214 ---
src/lib-storage/index/dbox/dbox-keywords.h     |   17 
src/lib-storage/index/dbox/dbox-mail.c         |  411 +++----
src/lib-storage/index/dbox/dbox-save.c         |  623 +++++-----
src/lib-storage/index/dbox/dbox-storage.c      |  386 ++----
src/lib-storage/index/dbox/dbox-storage.h      |   87 -
src/lib-storage/index/dbox/dbox-sync-expunge.c |  503 --------
src/lib-storage/index/dbox/dbox-sync-file.c    |  291 ++++
src/lib-storage/index/dbox/dbox-sync-full.c    |  237 ----
src/lib-storage/index/dbox/dbox-sync-rebuild.c |  199 +++
src/lib-storage/index/dbox/dbox-sync.c         |  825 +++++---------
src/lib-storage/index/dbox/dbox-sync.h         |   61 -
src/lib-storage/index/dbox/dbox-transaction.c  |   11 
src/lib-storage/index/dbox/dbox-uidlist.c      | 1402 ------------------------
src/lib-storage/index/dbox/dbox-uidlist.h      |   72 -

diffs (truncated from 8577 to 300 lines):

diff -r 301d0f8e4f91 -r 7b71ba1250e3 src/lib-storage/index/dbox/Makefile.am
--- a/src/lib-storage/index/dbox/Makefile.am	Sat Sep 01 01:36:10 2007 +0300
+++ b/src/lib-storage/index/dbox/Makefile.am	Sat Sep 01 03:04:02 2007 +0300
@@ -10,23 +10,20 @@ AM_CPPFLAGS = \
 
 libstorage_dbox_a_SOURCES = \
 	dbox-file.c \
-	dbox-keywords.c \
+	dbox-index.c \
 	dbox-mail.c \
 	dbox-save.c \
 	dbox-sync.c \
-	dbox-sync-expunge.c \
-	dbox-sync-full.c \
+	dbox-sync-file.c \
+	dbox-sync-rebuild.c \
 	dbox-storage.c \
-	dbox-transaction.c \
-	dbox-uidlist.c
+	dbox-transaction.c
 
 headers = \
 	dbox-file.h \
-	dbox-format.h \
-	dbox-keywords.h \
+	dbox-index.h \
 	dbox-storage.h \
-	dbox-sync.h \
-	dbox-uidlist.h
+	dbox-sync.h
 
 if INSTALL_HEADERS
   pkginc_libdir=$(pkgincludedir)/src/lib-storage/index/dbox
diff -r 301d0f8e4f91 -r 7b71ba1250e3 src/lib-storage/index/dbox/dbox-file.c
--- a/src/lib-storage/index/dbox/dbox-file.c	Sat Sep 01 01:36:10 2007 +0300
+++ b/src/lib-storage/index/dbox/dbox-file.c	Sat Sep 01 03:04:02 2007 +0300
@@ -1,311 +1,1053 @@
-/* Copyright (C) 2005-2006 Timo Sirainen */
+/* Copyright (C) 2007 Timo Sirainen */
 
 #include "lib.h"
+#include "ioloop.h"
 #include "array.h"
-#include "bsearch-insert-pos.h"
 #include "hex-dec.h"
+#include "hostpid.h"
 #include "istream.h"
 #include "ostream.h"
-#include "read-full.h"
+#include "write-full.h"
+#include "str.h"
 #include "dbox-storage.h"
+#include "dbox-index.h"
 #include "dbox-file.h"
 
-int dbox_file_lookup_offset(struct dbox_mailbox *mbox,
-			    struct mail_index_view *view, uint32_t seq,
-			    uint32_t *file_seq_r, uoff_t *offset_r)
-{
-	const void *data1, *data2;
-	bool expunged;
-
-	mail_index_lookup_ext(view, seq, mbox->dbox_file_ext_idx,
-			      &data1, &expunged);
-	if (expunged)
-		return 0;
-	mail_index_lookup_ext(view, seq, mbox->dbox_offset_ext_idx,
-			      &data2, &expunged);
-	if (expunged)
-		return 0;
-
-	if (data1 == NULL || data2 == NULL) {
-		*file_seq_r = 0;
-		return 1;
-	}
-
-	/* success */
-	*file_seq_r = *((const uint32_t *)data1);
-	*offset_r = *((const uint64_t *)data2);
-	return 1;
-}
-
-void dbox_file_close(struct dbox_file *file)
-{
-	if (array_is_created(&file->file_idx_keywords)) {
-		array_free(&file->idx_file_keywords);
-		array_free(&file->file_idx_keywords);
-	}
-
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+enum mail_flags dbox_mail_flags_map[DBOX_METADATA_FLAGS_COUNT] = {
+	MAIL_ANSWERED,
+	MAIL_FLAGGED,
+	MAIL_DELETED,
+	MAIL_SEEN,
+	MAIL_DRAFT
+};
+
+char dbox_mail_flag_chars[DBOX_METADATA_FLAGS_COUNT] = {
+	'A', 'F', 'D', 'S', 'T'
+};
+
+static int dbox_file_metadata_skip_header(struct dbox_file *file);
+
+static char *dbox_generate_tmp_filename(const char *path)
+{
+	static unsigned int create_count = 0;
+
+	return i_strdup_printf("%s/temp.%s.P%sQ%uM%s.%s",
+			       path, dec2str(ioloop_timeval.tv_sec), my_pid,
+			       create_count++,
+			       dec2str(ioloop_timeval.tv_usec), my_hostname);
+}
+
+void dbox_file_set_syscall_error(struct dbox_file *file, const char *function)
+{
+	mail_storage_set_critical(file->mbox->ibox.box.storage,
+				  "%s(%s) failed: %m", function, file->path);
+}
+
+static void
+dbox_file_set_corrupted(struct dbox_file *file, const char *reason)
+{
+	mail_storage_set_critical(file->mbox->ibox.box.storage,
+				  "%s corrupted: %s", file->path, reason);
+}
+
+
+static struct dbox_file *
+dbox_find_and_move_open_file(struct dbox_mailbox *mbox, unsigned int file_id)
+{
+	struct dbox_file *const *files, *file;
+	unsigned int i, count;
+
+	files = array_get(&mbox->open_files, &count);
+	for (i = 0; i < count; i++) {
+		if (files[i]->file_id == file_id) {
+			/* move to last in the array */
+			file = files[i];
+			array_delete(&mbox->open_files, i, 1);
+			array_append(&mbox->open_files, &file, 1);
+			return file;
+		}
+	}
+	return NULL;
+}
+
+static void dbox_file_free(struct dbox_file *file)
+{
+	i_assert(file->refcount == 0);
+
+	if (file->metadata_pool != NULL)
+		pool_unref(file->metadata_pool);
 	if (file->input != NULL)
-		i_stream_destroy(&file->input);
+		i_stream_unref(&file->input);
+	if (file->output != NULL)
+		o_stream_unref(&file->output);
 	if (file->fd != -1) {
 		if (close(file->fd) < 0)
-			i_error("close(dbox) failed: %m");
-	}
-	i_free(file->seeked_keywords);
+			dbox_file_set_syscall_error(file, "close");
+		file->fd = -1;
+	}
 	i_free(file->path);
 	i_free(file);
 }
 
-static int
-dbox_file_read_mail_header(struct dbox_mailbox *mbox, struct dbox_file *file,
-			   uoff_t offset)
-{
-	const struct dbox_mail_header *hdr;
+void dbox_files_free(struct dbox_mailbox *mbox)
+{
+	struct dbox_file *const *files;
+	unsigned int i, count;
+
+	files = array_get(&mbox->open_files, &count);
+	for (i = 0; i < count; i++)
+		dbox_file_free(files[i]);
+	array_clear(&mbox->open_files);
+}
+
+static void
+dbox_close_open_files(struct dbox_mailbox *mbox, unsigned int close_count)
+{
+	struct dbox_file *const *files;
+	unsigned int i, count;
+
+	files = array_get(&mbox->open_files, &count);
+	for (i = 0; i < count;) {
+		if (files[i]->refcount == 0) {
+			dbox_file_free(files[i]);
+			array_delete(&mbox->open_files, i, 1);
+
+			if (--close_count == 0)
+				break;
+
+			files = array_get(&mbox->open_files, &count);
+		} else {
+			i++;
+		}
+	}
+}
+
+static char *
+dbox_file_id_get_path(struct dbox_mailbox *mbox, unsigned int file_id)
+{
+	if ((file_id & DBOX_FILE_ID_FLAG_UID) != 0) {
+		file_id &= ~DBOX_FILE_ID_FLAG_UID;
+		return i_strdup_printf("%s/"DBOX_MAIL_FILE_UID_FORMAT,
+				       mbox->path, file_id);
+	} else {
+		return i_strdup_printf("%s/"DBOX_MAIL_FILE_MULTI_FORMAT,
+				       mbox->path, file_id);
+	}
+}
+
+struct dbox_file *
+dbox_file_init(struct dbox_mailbox *mbox, unsigned int file_id)
+{
+	struct dbox_file *file;
+	unsigned int count;
+
+	file = file_id == 0 ? NULL :
+		dbox_find_and_move_open_file(mbox, file_id);
+	if (file != NULL) {
+		file->refcount++;
+		return file;
+	}
+
+	count = array_count(&mbox->open_files);
+	if (count > mbox->max_open_files)
+		dbox_close_open_files(mbox, count - mbox->max_open_files);
+
+	file = i_new(struct dbox_file, 1);
+	file->refcount = 1;
+	file->mbox = mbox;
+	if (file_id != 0) {
+		file->file_id = file_id;
+		file->path = dbox_file_id_get_path(mbox, file_id);
+	} else {
+		file->path = dbox_generate_tmp_filename(mbox->path);
+	}
+	file->fd = -1;
+
+	if (file_id != 0)
+		array_append(&file->mbox->open_files, &file, 1);
+	return file;
+}
+
+int dbox_file_assign_id(struct dbox_file *file, unsigned int file_id)
+{
+	char *new_path;
+
+	i_assert(file->file_id == 0);
+	i_assert(file_id != 0);
+
+	new_path = dbox_file_id_get_path(file->mbox, file_id);
+	if (rename(file->path, new_path) < 0) {
+		mail_storage_set_critical(file->mbox->ibox.box.storage,
+			"rename(%s, %s) failed: %m", file->path, new_path);
+		i_free(new_path);
+		return -1;
+	}
+
+	i_free(file->path);
+	file->path = new_path;
+
+	file->file_id = file_id;
+	array_append(&file->mbox->open_files, &file, 1);
+	return 0;
+}
+
+void dbox_file_unref(struct dbox_file **_file)
+{
+	struct dbox_file *file = *_file;
+	struct dbox_file *const *files;
+	unsigned int i, count;
+
+	*_file = NULL;
+
+	i_assert(file->refcount > 0);
+	if (--file->refcount > 0)
+		return;
+
+	/* don't cache metadata seeks while file isn't being referenced */
+	file->metadata_read_offset = 0;
+
+	if (file->file_id != 0) {
+		files = array_get(&file->mbox->open_files, &count);
+		if (!file->deleted && count <= file->mbox->max_open_files) {
+			/* we can leave this file open for now */


More information about the dovecot-cvs mailing list