]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-storage: Allow LISTINDEX to point to a different directory
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Sat, 22 Jul 2017 15:39:19 +0000 (18:39 +0300)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Tue, 25 Jul 2017 15:01:01 +0000 (18:01 +0300)
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.

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

index eda0e599063bfed746143c4d4469770d474792a2..b92ff9e767876dab76ac4f32f183290fb96d92f7 100644 (file)
@@ -98,8 +98,10 @@ mbox_list_get_path(struct mailbox_list *list, const char *name,
        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 @@ mbox_list_get_path(struct mailbox_list *list, const char *name,
 
                *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;
 }
index d7784d10ecfd9a1cfbbb309f46d81ae619dd3a2f..12db625813214e3dd5701500786ecf32dc77d943 100644 (file)
@@ -129,6 +129,8 @@ fs_list_get_path(struct mailbox_list *_list, const char *name,
                        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 ||
index 5767f58ad943ae18c0394a494edff38ef7dd2643..5fe8a3837fa0e6eae5074391b07ad31318bee36f 100644 (file)
@@ -137,6 +137,8 @@ index_list_get_path(struct mailbox_list *_list, const char *name,
        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;
        }
index f84be7feb49dcc8735e35f5a917de9c751f47ffe..2a6908c1fdb8e0cd39bad19f1a686db7098798c2 100644 (file)
@@ -63,7 +63,7 @@ int mailbox_list_index_index_open(struct mailbox_list *list)
        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 @@ static void mailbox_list_index_init_finish(struct mailbox_list *list)
 
        /* 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;
index 589e63cc679e04e15737525b38bfe2fdcd4154ff..7e26917d3477e180dd718744a9f6ca19b7b5cd97 100644 (file)
@@ -151,6 +151,8 @@ maildir_list_get_path(struct mailbox_list *_list, const char *name,
                *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 ||
index 4ab18a2b9bd3b5460e5e4ca928b84a8984bf09a0..7de90d389ebcfa9fa183b312ab9683b285c98ab0 100644 (file)
@@ -139,6 +139,7 @@ struct mailbox_list {
        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;
index 3204b787e14cd31b2a0abb9bae8cd011be2ff62a..744261a7c94364b9988c6fa2ffde8d0a1897c346 100644 (file)
@@ -166,6 +166,8 @@ int mailbox_list_create(const char *driver, struct mail_namespace *ns,
                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 @@ mailbox_list_settings_parse_full(struct mail_user *user, const char *data,
                                 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 @@ mailbox_list_settings_parse_full(struct mail_user *user, const char *data,
                *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 @@ bool mailbox_list_set_get_root_path(const struct mailbox_list_settings *set,
                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 @@ int mailbox_list_mkdir_missing_index_root(struct mailbox_list *list)
        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)
index bc9f098a8963856c46cf20c5c61bbf87589b92c4..a816b24189dcec44e05549d59ec55c17b6e46cfb 100644 (file)
@@ -82,7 +82,10 @@ enum mailbox_list_path_type {
        /* 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 @@ struct mailbox_list_settings {
        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 @@ int mailbox_list_try_mkdir_root(struct mailbox_list *list, const char *path,
    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 */