dovecot-2.2: lib-storage: Added initial implementation for layou...

dovecot at dovecot.org dovecot at dovecot.org
Fri Sep 28 00:11:35 EEST 2012


details:   http://hg.dovecot.org/dovecot-2.2/rev/0fa075f2e85a
changeset: 15167:0fa075f2e85a
user:      Timo Sirainen <tss at iki.fi>
date:      Fri Sep 28 00:11:19 2012 +0300
description:
lib-storage: Added initial implementation for layout=index.
The idea is that all of the mailbox names only exist in the mailbox list
index. Storage directories use mailbox GUIDs. This avoids all kinds of
race conditions with mailbox renames. mailbox_list_index=yes is required for
this layout to work.

There are probably still some race conditions within the indexing code
itself. Also error recovery is missing.

diffstat:

 configure.in                                      |    2 +-
 src/lib-storage/list/Makefile.am                  |    3 +
 src/lib-storage/list/mailbox-list-delete.c        |   11 +-
 src/lib-storage/list/mailbox-list-delete.h        |    2 +-
 src/lib-storage/list/mailbox-list-fs.c            |    9 +-
 src/lib-storage/list/mailbox-list-index-backend.c |  586 ++++++++++++++++++++++
 src/lib-storage/list/mailbox-list-index-iter.c    |   30 +-
 src/lib-storage/list/mailbox-list-index-notify.c  |    8 +-
 src/lib-storage/list/mailbox-list-index-status.c  |   34 +-
 src/lib-storage/list/mailbox-list-index-storage.h |   16 +
 src/lib-storage/list/mailbox-list-index-sync.c    |  191 ++++---
 src/lib-storage/list/mailbox-list-index-sync.h    |   32 +
 src/lib-storage/list/mailbox-list-index.c         |  159 ++++-
 src/lib-storage/list/mailbox-list-index.h         |   14 +-
 src/lib-storage/list/mailbox-list-maildir.c       |    9 +-
 15 files changed, 936 insertions(+), 170 deletions(-)

diffs (truncated from 1541 to 300 lines):

diff -r 55ab35b0cc22 -r 0fa075f2e85a configure.in
--- a/configure.in	Fri Sep 28 00:03:12 2012 +0300
+++ b/configure.in	Fri Sep 28 00:11:19 2012 +0300
@@ -2463,7 +2463,7 @@
 
 LINKED_STORAGE_LIBS=
 
-mailbox_list_drivers="maildir imapdir none fs shared"
+mailbox_list_drivers="maildir imapdir fs index none shared"
 have_sdbox=no
 for storage in $mail_storages; do
   LINKED_STORAGE_LIBS="$LINKED_STORAGE_LIBS `eval echo \\$${storage}_libs`"
diff -r 55ab35b0cc22 -r 0fa075f2e85a src/lib-storage/list/Makefile.am
--- a/src/lib-storage/list/Makefile.am	Fri Sep 28 00:03:12 2012 +0300
+++ b/src/lib-storage/list/Makefile.am	Fri Sep 28 00:11:19 2012 +0300
@@ -14,6 +14,7 @@
 	mailbox-list-fs-flags.c \
 	mailbox-list-fs-iter.c \
 	mailbox-list-index.c \
+	mailbox-list-index-backend.c \
 	mailbox-list-index-iter.c \
 	mailbox-list-index-notify.c \
 	mailbox-list-index-status.c \
@@ -30,6 +31,8 @@
 	mailbox-list-delete.h \
 	mailbox-list-fs.h \
 	mailbox-list-index.h \
+	mailbox-list-index-storage.h \
+	mailbox-list-index-sync.h \
 	mailbox-list-maildir.h \
 	mailbox-list-notify-tree.h \
 	mailbox-list-subscriptions.h \
diff -r 55ab35b0cc22 -r 0fa075f2e85a src/lib-storage/list/mailbox-list-delete.c
--- a/src/lib-storage/list/mailbox-list-delete.c	Fri Sep 28 00:03:12 2012 +0300
+++ b/src/lib-storage/list/mailbox-list-delete.c	Fri Sep 28 00:11:19 2012 +0300
@@ -119,17 +119,8 @@
 }
 
 int mailbox_list_delete_mailbox_file(struct mailbox_list *list,
-				     const char *name)
+				     const char *name, const char *path)
 {
-	const char *path;
-	int ret;
-
-	ret = mailbox_list_get_path(list, name, MAILBOX_LIST_PATH_TYPE_MAILBOX,
-				    &path);
-	if (ret < 0)
-		return -1;
-	i_assert(ret > 0);
-
 	/* we can simply unlink() the file */
 	if (unlink(path) == 0)
 		return 0;
diff -r 55ab35b0cc22 -r 0fa075f2e85a src/lib-storage/list/mailbox-list-delete.h
--- a/src/lib-storage/list/mailbox-list-delete.h	Fri Sep 28 00:03:12 2012 +0300
+++ b/src/lib-storage/list/mailbox-list-delete.h	Fri Sep 28 00:11:19 2012 +0300
@@ -7,7 +7,7 @@
 					  const char *name,
 					  const char *trash_dir);
 int mailbox_list_delete_mailbox_file(struct mailbox_list *list,
-				     const char *name);
+				     const char *name, const char *path);
 int mailbox_list_delete_mailbox_nonrecursive(struct mailbox_list *list,
 					     const char *name, const char *path,
 					     bool rmdir_path);
diff -r 55ab35b0cc22 -r 0fa075f2e85a src/lib-storage/list/mailbox-list-fs.c
--- a/src/lib-storage/list/mailbox-list-fs.c	Fri Sep 28 00:03:12 2012 +0300
+++ b/src/lib-storage/list/mailbox-list-fs.c	Fri Sep 28 00:11:19 2012 +0300
@@ -225,10 +225,17 @@
 
 static int fs_list_delete_mailbox(struct mailbox_list *list, const char *name)
 {
+	const char *path;
 	int ret;
 
 	if ((list->flags & MAILBOX_LIST_FLAG_MAILBOX_FILES) != 0) {
-		ret = mailbox_list_delete_mailbox_file(list, name);
+		ret = mailbox_list_get_path(list, name,
+					    MAILBOX_LIST_PATH_TYPE_MAILBOX,
+					    &path);
+		if (ret < 0)
+			return -1;
+		i_assert(ret > 0);
+		ret = mailbox_list_delete_mailbox_file(list, name, path);
 	} else {
 		ret = fs_list_delete_maildir(list, name);
 	}
diff -r 55ab35b0cc22 -r 0fa075f2e85a src/lib-storage/list/mailbox-list-index-backend.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-storage/list/mailbox-list-index-backend.c	Fri Sep 28 00:11:19 2012 +0300
@@ -0,0 +1,586 @@
+/* Copyright (c) 2012 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "hostpid.h"
+#include "mail-index.h"
+#include "subscription-file.h"
+#include "mailbox-list-delete.h"
+#include "mailbox-list-subscriptions.h"
+#include "mailbox-list-index-storage.h"
+#include "mailbox-list-index-sync.h"
+
+#define GLOBAL_TEMP_PREFIX ".temp."
+
+struct index_mailbox_list {
+	struct mailbox_list list;
+	const char *temp_prefix;
+};
+
+extern struct mailbox_list index_mailbox_list;
+
+static struct mailbox_list *index_list_alloc(void)
+{
+	struct index_mailbox_list *list;
+	pool_t pool;
+
+	pool = pool_alloconly_create("index list", 2048);
+
+	list = p_new(pool, struct index_mailbox_list, 1);
+	list->list = index_mailbox_list;
+	list->list.pool = pool;
+
+	list->temp_prefix = p_strconcat(pool, GLOBAL_TEMP_PREFIX,
+					my_hostname, ".", my_pid, ".", NULL);
+	return &list->list;
+}
+
+static void index_list_deinit(struct mailbox_list *_list)
+{
+	struct index_mailbox_list *list = (struct index_mailbox_list *)_list;
+
+	pool_unref(&list->list.pool);
+}
+
+static char index_list_get_hierarchy_sep(struct mailbox_list *list ATTR_UNUSED)
+{
+	return MAILBOX_LIST_INDEX_HIERARHCY_SEP;
+}
+
+static int
+index_list_get_node(struct index_mailbox_list *list, const char *name,
+		    struct mailbox_list_index_node **node_r)
+{
+	struct mailbox_list_index_node *node;
+
+	if (mailbox_list_index_refresh(&list->list) < 0)
+		return -1;
+
+	node = mailbox_list_index_lookup(&list->list, name);
+	if (node == NULL)
+		return 0;
+	*node_r = node;
+	return 1;
+}
+
+static int
+index_list_get_path(struct mailbox_list *_list, const char *name,
+		    enum mailbox_list_path_type type, const char **path_r)
+{
+	struct index_mailbox_list *list = (struct index_mailbox_list *)_list;
+	struct mailbox_list_index *ilist = INDEX_LIST_CONTEXT(_list);
+	struct mail_index_view *view;
+	struct mailbox_list_index_node *node;
+	struct mailbox_status status;
+	guid_128_t mailbox_guid;
+	const char *root_dir;
+	uint32_t seq;
+	int ret;
+
+	if (name == NULL) {
+		/* return root directories */
+		return mailbox_list_set_get_root_path(&_list->set, type,
+						      path_r) ? 1 : 0;
+	}
+	/* consistently use mailbox_dir_name as part of all mailbox
+	   directories (index/control/etc) */
+	switch (type) {
+	case MAILBOX_LIST_PATH_TYPE_MAILBOX:
+		type = MAILBOX_LIST_PATH_TYPE_DIR;
+		break;
+	case MAILBOX_LIST_PATH_TYPE_ALT_MAILBOX:
+		type = MAILBOX_LIST_PATH_TYPE_ALT_DIR;
+		break;
+	default:
+		break;
+	}
+	if (!mailbox_list_set_get_root_path(&_list->set, type, &root_dir))
+		return 0;
+
+	if ((ret = index_list_get_node(list, name, &node)) <= 0) {
+		if (ret == 0) {
+			mailbox_list_set_error(_list, MAIL_ERROR_NOTFOUND,
+				T_MAIL_ERR_MAILBOX_NOT_FOUND(name));
+		}
+		return -1;
+	}
+	view = mail_index_view_open(ilist->index);
+	if (!mail_index_lookup_seq(view, node->uid, &seq))
+		i_panic("mailbox list index: lost uid=%u", node->uid);
+	if (!mailbox_list_index_status(_list, view, seq, 0,
+				       &status, mailbox_guid)) {
+		mailbox_list_set_error(_list, MAIL_ERROR_NOTFOUND,
+				       T_MAIL_ERR_MAILBOX_NOT_FOUND(name));
+		ret = -1;
+	} else if (_list->set.mailbox_dir_name == '\0') {
+		*path_r = t_strconcat(root_dir, "/",
+				      guid_128_to_string(mailbox_guid), NULL);
+		ret = 1;
+	} else {
+		*path_r = t_strdup_printf("%s/%s%s", root_dir,
+					  _list->set.mailbox_dir_name,
+					  guid_128_to_string(mailbox_guid));
+		ret = 1;
+	}
+	mail_index_view_close(&view);
+	return ret;
+}
+
+static const char *
+index_list_get_temp_prefix(struct mailbox_list *_list, bool global)
+{
+	struct index_mailbox_list *list = (struct index_mailbox_list *)_list;
+
+	return global ? GLOBAL_TEMP_PREFIX : list->temp_prefix;
+}
+
+static int index_list_set_subscribed(struct mailbox_list *_list,
+				     const char *name, bool set)
+{
+	struct index_mailbox_list *list = (struct index_mailbox_list *)_list;
+	const char *path;
+
+	path = t_strconcat(_list->set.control_dir != NULL ?
+			   _list->set.control_dir : _list->set.root_dir,
+			   "/", _list->set.subscription_fname, NULL);
+	return subsfile_set_subscribed(_list, path, list->temp_prefix,
+				       name, set);
+}
+
+static int
+index_list_node_exists(struct index_mailbox_list *list, const char *name,
+		       enum mailbox_existence *existence_r)
+{
+	struct mailbox_list_index_node *node;
+	int ret;
+
+	*existence_r = MAILBOX_EXISTENCE_NONE;
+
+	if ((ret = index_list_get_node(list, name, &node)) < 0)
+		return -1;
+	if (ret == 0)
+		return 0;
+
+	if ((node->flags & (MAILBOX_LIST_INDEX_FLAG_NONEXISTENT |
+			    MAILBOX_LIST_INDEX_FLAG_NOSELECT)) == 0) {
+		/* selectable */
+		*existence_r = MAILBOX_EXISTENCE_SELECT;
+	} else {
+		/* non-selectable */
+		*existence_r = MAILBOX_EXISTENCE_NOSELECT;
+	}
+	return 0;
+}
+
+static int
+index_list_mailbox_create_dir(struct index_mailbox_list *list, const char *name)
+{
+	struct mailbox_list_index_sync_context *sync_ctx;
+	struct mailbox_list_index_node *node;
+	uint32_t seq;
+	bool created;
+	int ret;
+
+	if (mailbox_list_index_sync_begin(&list->list, &sync_ctx) < 0)
+		return -1;
+
+	seq = mailbox_list_index_sync_name(sync_ctx, name, &node, &created);
+	if (created || (node->flags & MAILBOX_LIST_INDEX_FLAG_NONEXISTENT) != 0) {
+		/* didn't already exist */
+		node->flags = MAILBOX_LIST_INDEX_FLAG_NOSELECT;
+		mail_index_update_flags(sync_ctx->trans, seq, MODIFY_REPLACE,
+					(enum mail_flags)node->flags);
+		ret = 1;
+	} else {
+		/* already existed */
+		ret = 0;
+	}
+	if (mailbox_list_index_sync_end(&sync_ctx, TRUE) < 0)
+		ret = -1;
+	return ret;
+}
+
+static int
+index_list_mailbox_create_selectable(struct index_mailbox_list *list,
+				     const char *name, guid_128_t mailbox_guid)
+{
+	struct mailbox_list_index_sync_context *sync_ctx;
+	struct mailbox_list_index_record rec;
+	struct mailbox_list_index_node *node;


More information about the dovecot-cvs mailing list