changeset 22380:b83a0ed2793a

lib-storage: Allow LISTINDEX to point to a different directory Most importantly because the mailbox list index is only a cache, it could be safely pointed to e.g. tmpfs to save disk I/O.
author Timo Sirainen <timo.sirainen@dovecot.fi>
date Sat, 22 Jul 2017 18:39:19 +0300
parents 55c0069fec20
children 97c212d6dd64
files src/lib-storage/index/mbox/mbox-storage.c src/lib-storage/list/mailbox-list-fs.c src/lib-storage/list/mailbox-list-index-backend.c src/lib-storage/list/mailbox-list-index.c src/lib-storage/list/mailbox-list-maildir.c src/lib-storage/mailbox-list-private.h src/lib-storage/mailbox-list.c src/lib-storage/mailbox-list.h
diffstat 8 files changed, 80 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-storage/index/mbox/mbox-storage.c	Fri Jul 21 19:52:23 2017 +0300
+++ b/src/lib-storage/index/mbox/mbox-storage.c	Sat Jul 22 18:39:19 2017 +0300
@@ -98,8 +98,10 @@
 	if (ret <= 0)
 		return ret;
 
-	if (type == MAILBOX_LIST_PATH_TYPE_CONTROL ||
-	    type == MAILBOX_LIST_PATH_TYPE_INDEX) {
+	switch (type) {
+	case MAILBOX_LIST_PATH_TYPE_CONTROL:
+	case MAILBOX_LIST_PATH_TYPE_INDEX:
+	case MAILBOX_LIST_PATH_TYPE_LIST_INDEX:
 		if (name == NULL && type == MAILBOX_LIST_PATH_TYPE_CONTROL &&
 		    list->set.control_dir != NULL) {
 			/* kind of a kludge for backwards compatibility:
@@ -119,8 +121,14 @@
 
 		*path_r = t_strconcat(t_strdup_until(path, p),
 				      "/"MBOX_INDEX_DIR_NAME"/", p+1, NULL);
-	} else {
+		break;
+	case MAILBOX_LIST_PATH_TYPE_DIR:
+	case MAILBOX_LIST_PATH_TYPE_ALT_DIR:
+	case MAILBOX_LIST_PATH_TYPE_MAILBOX:
+	case MAILBOX_LIST_PATH_TYPE_ALT_MAILBOX:
+	case MAILBOX_LIST_PATH_TYPE_INDEX_PRIVATE:
 		*path_r = path;
+		break;
 	}
 	return 1;
 }
--- a/src/lib-storage/list/mailbox-list-fs.c	Fri Jul 21 19:52:23 2017 +0300
+++ b/src/lib-storage/list/mailbox-list-fs.c	Sat Jul 22 18:39:19 2017 +0300
@@ -129,6 +129,8 @@
 			return 0;
 		*path_r = fs_list_get_path_to(set, set->index_pvt_dir, name);
 		return 1;
+	case MAILBOX_LIST_PATH_TYPE_LIST_INDEX:
+		i_unreached();
 	}
 
 	if (type == MAILBOX_LIST_PATH_TYPE_ALT_DIR ||
--- a/src/lib-storage/list/mailbox-list-index-backend.c	Fri Jul 21 19:52:23 2017 +0300
+++ b/src/lib-storage/list/mailbox-list-index-backend.c	Sat Jul 22 18:39:19 2017 +0300
@@ -137,6 +137,8 @@
 	case MAILBOX_LIST_PATH_TYPE_ALT_MAILBOX:
 		type = MAILBOX_LIST_PATH_TYPE_ALT_DIR;
 		break;
+	case MAILBOX_LIST_PATH_TYPE_LIST_INDEX:
+		i_unreached();
 	default:
 		break;
 	}
--- a/src/lib-storage/list/mailbox-list-index.c	Fri Jul 21 19:52:23 2017 +0300
+++ b/src/lib-storage/list/mailbox-list-index.c	Sat Jul 22 18:39:19 2017 +0300
@@ -63,7 +63,7 @@
 	if (ilist->opened)
 		return 0;
 
-	if (mailbox_list_mkdir_missing_index_root(list) < 0)
+	if (mailbox_list_mkdir_missing_list_index_root(list) < 0)
 		return -1;
 
 	i_assert(ilist->index != NULL);
@@ -872,7 +872,7 @@
 
 	/* we've delayed this part of the initialization so that mbox format
 	   can override the index root directory path */
-	if (!mailbox_list_get_root_path(list, MAILBOX_LIST_PATH_TYPE_INDEX,
+	if (!mailbox_list_get_root_path(list, MAILBOX_LIST_PATH_TYPE_LIST_INDEX,
 					&dir)) {
 		/* in-memory indexes */
 		dir = NULL;
--- a/src/lib-storage/list/mailbox-list-maildir.c	Fri Jul 21 19:52:23 2017 +0300
+++ b/src/lib-storage/list/mailbox-list-maildir.c	Sat Jul 22 18:39:19 2017 +0300
@@ -151,6 +151,8 @@
 		*path_r = maildir_list_get_dirname_path(_list,
 					_list->set.index_pvt_dir, name);
 		return 1;
+	case MAILBOX_LIST_PATH_TYPE_LIST_INDEX:
+		i_unreached();
 	}
 
 	if (type == MAILBOX_LIST_PATH_TYPE_ALT_DIR ||
--- a/src/lib-storage/mailbox-list-private.h	Fri Jul 21 19:52:23 2017 +0300
+++ b/src/lib-storage/mailbox-list-private.h	Sat Jul 22 18:39:19 2017 +0300
@@ -139,6 +139,7 @@
 	ARRAY(union mailbox_list_module_context *) module_contexts;
 
 	unsigned int index_root_dir_created:1;
+	unsigned int list_index_root_dir_created:1;
 	unsigned int guid_cache_updated:1;
 	unsigned int guid_cache_invalidated:1;
 	unsigned int last_error_is_internal:1;
--- a/src/lib-storage/mailbox-list.c	Fri Jul 21 19:52:23 2017 +0300
+++ b/src/lib-storage/mailbox-list.c	Sat Jul 22 18:39:19 2017 +0300
@@ -166,6 +166,8 @@
 		p_strdup(list->pool, set->subscription_fname);
 	list->set.list_index_fname =
 		p_strdup(list->pool, set->list_index_fname);
+	list->set.list_index_dir =
+		p_strdup(list->pool, set->list_index_dir);
 	list->set.maildir_name =
 		p_strdup(list->pool, set->maildir_name);
 	list->set.mailbox_dir_name =
@@ -280,7 +282,7 @@
 				 struct mailbox_list_settings *set_r,
 				 const char **error_r)
 {
-	const char *const *tmp, *key, *value, **dest, *str, *error;
+	const char *const *tmp, *key, *value, **dest, *str, *fname, *error;
 
 	*error_r = NULL;
 
@@ -366,6 +368,18 @@
 		*error_r = "ITERINDEX requires INDEX to be explicitly set";
 		return -1;
 	}
+	if (set_r->list_index_fname != NULL &&
+	    (fname = strrchr(set_r->list_index_fname, '/')) != NULL) {
+		/* non-default LISTINDEX directory */
+		set_r->list_index_dir =
+			t_strdup_until(set_r->list_index_fname, fname);
+		set_r->list_index_fname = fname+1;
+		if (set_r->list_index_dir[0] != '/' &&
+		    set_r->index_dir != NULL && set_r->index_dir[0] == '\0') {
+			*error_r = "LISTINDEX directory is relative but INDEX=MEMORY";
+			return -1;
+		}
+	}
 	return 0;
 }
 
@@ -1411,6 +1425,20 @@
 		path = set->control_dir != NULL ?
 			set->control_dir : set->root_dir;
 		break;
+	case MAILBOX_LIST_PATH_TYPE_LIST_INDEX:
+		if (set->list_index_dir != NULL) {
+			if (set->list_index_dir[0] == '/') {
+				path = set->list_index_dir;
+				break;
+			}
+			/* relative path */
+			if (!mailbox_list_set_get_root_path(set,
+					MAILBOX_LIST_PATH_TYPE_INDEX, &path))
+				i_unreached();
+			path = t_strconcat(path, "/", set->list_index_dir, NULL);
+			break;
+		}
+		/* fall through - default to index directory */
 	case MAILBOX_LIST_PATH_TYPE_INDEX:
 		if (set->index_dir != NULL) {
 			if (set->index_dir[0] == '\0') {
@@ -1628,6 +1656,27 @@
 	return 1;
 }
 
+int mailbox_list_mkdir_missing_list_index_root(struct mailbox_list *list)
+{
+	const char *index_dir;
+
+	if (list->set.list_index_dir == NULL)
+		return mailbox_list_mkdir_missing_index_root(list);
+
+	/* LISTINDEX points outside the index root directory */
+	if (list->list_index_root_dir_created)
+		return 1;
+
+	if (!mailbox_list_get_root_path(list, MAILBOX_LIST_PATH_TYPE_LIST_INDEX,
+					&index_dir))
+		return 0;
+	if (mailbox_list_mkdir_root(list, index_dir,
+				    MAILBOX_LIST_PATH_TYPE_LIST_INDEX) < 0)
+		return -1;
+	list->list_index_root_dir_created = TRUE;
+	return 1;
+}
+
 void mailbox_list_add_change(struct mailbox_list *list,
 			     enum mailbox_log_record_type type,
 			     const guid_128_t mailbox_guid)
--- a/src/lib-storage/mailbox-list.h	Fri Jul 21 19:52:23 2017 +0300
+++ b/src/lib-storage/mailbox-list.h	Sat Jul 22 18:39:19 2017 +0300
@@ -82,7 +82,10 @@
 	/* Return index directory ("" for in-memory) */
 	MAILBOX_LIST_PATH_TYPE_INDEX,
 	/* Return the private index directory (NULL if none) */
-	MAILBOX_LIST_PATH_TYPE_INDEX_PRIVATE
+	MAILBOX_LIST_PATH_TYPE_INDEX_PRIVATE,
+	/* Return mailbox list index directory (usually same as
+	   MAILBOX_LIST_PATH_TYPE_INDEX) */
+	MAILBOX_LIST_PATH_TYPE_LIST_INDEX,
 };
 
 enum mailbox_list_file_type {
@@ -109,6 +112,9 @@
 	const char *inbox_path;
 	const char *subscription_fname;
 	const char *list_index_fname;
+	/* Mailbox list index directory. NULL defaults to index directory.
+	   The path may be relative to the index directory. */
+	const char *list_index_dir;
 	/* If non-empty, it means that mails exist in a maildir_name
 	   subdirectory. eg. if you have a directory containing directories:
 
@@ -217,6 +223,9 @@
    same as mailbox root. Returns 1 if ok, 0 if there are no indexes, -1 if
    error. Calling this multiple times does the check only once. */
 int mailbox_list_mkdir_missing_index_root(struct mailbox_list *list);
+/* Like mailbox_list_mkdir_missing_index_root(), but for mailbox list
+   index root. */
+int mailbox_list_mkdir_missing_list_index_root(struct mailbox_list *list);
 
 /* Returns TRUE if name is ok, FALSE if it can't be safely passed to
    mailbox_list_*() functions */