Skip to content

Commit

Permalink
lib-storage: Allow LISTINDEX to point to a different directory
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
sirainen authored and cmouse committed Jul 24, 2017
1 parent 9ab2df6 commit 49c4863
Show file tree
Hide file tree
Showing 8 changed files with 80 additions and 7 deletions.
14 changes: 11 additions & 3 deletions src/lib-storage/index/mbox/mbox-storage.c
Expand Up @@ -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:
Expand All @@ -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;
}
Expand Down
2 changes: 2 additions & 0 deletions src/lib-storage/list/mailbox-list-fs.c
Expand Up @@ -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 ||
Expand Down
2 changes: 2 additions & 0 deletions src/lib-storage/list/mailbox-list-index-backend.c
Expand Up @@ -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;
}
Expand Down
4 changes: 2 additions & 2 deletions src/lib-storage/list/mailbox-list-index.c
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions src/lib-storage/list/mailbox-list-maildir.c
Expand Up @@ -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 ||
Expand Down
1 change: 1 addition & 0 deletions src/lib-storage/mailbox-list-private.h
Expand Up @@ -139,6 +139,7 @@ struct mailbox_list {
ARRAY(union mailbox_list_module_context *) module_contexts;

bool index_root_dir_created:1;
bool list_index_root_dir_created:1;
bool guid_cache_updated:1;
bool guid_cache_invalidated:1;
bool last_error_is_internal:1;
Expand Down
51 changes: 50 additions & 1 deletion src/lib-storage/mailbox-list.c
Expand Up @@ -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 =
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -373,6 +375,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;
}

Expand Down Expand Up @@ -1416,6 +1430,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') {
Expand Down Expand Up @@ -1630,6 +1658,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)
Expand Down
11 changes: 10 additions & 1 deletion src/lib-storage/mailbox-list.h
Expand Up @@ -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 {
Expand All @@ -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:
Expand Down Expand Up @@ -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 */
Expand Down

0 comments on commit 49c4863

Please sign in to comment.