bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2010-2018 Dovecot authors, see the included COPYING file */
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen MODULE_CONTEXT(obj, mail_index_alloc_cache_index_module)
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen/* How many seconds to keep index opened for reuse after it's been closed */
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen/* How many closed indexes to keep */
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(mail_index_alloc_cache_index_module,
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainenstatic struct mail_index_alloc_cache_list *indexes = NULL;
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainenstatic unsigned int indexes_cache_references_count = 0;
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainenmail_index_alloc_cache_add(struct mail_index *index,
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen list = i_new(struct mail_index_alloc_cache_list, 1);
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen MODULE_CONTEXT_SET(index, mail_index_alloc_cache_index_module, list);
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainenmail_index_alloc_cache_list_unref(struct mail_index_alloc_cache_list *list)
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainenmail_index_alloc_cache_list_free(struct mail_index_alloc_cache_list *list)
3aa84b022e0e24f468371ee813a4cd8acfd57052Timo Sirainenmail_index_alloc_cache_find(const char *mailbox_path, const char *index_dir,
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen struct mail_index_alloc_cache_list **indexp, *rec, *match;
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen /* already found the index. we're just going through
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen the rest of them to drop 0 refcounts */
04dff721d2a63566a4dbe1c856f8218b6550aa3eTimo Sirainen } else if (rec->refcount == 0 && rec->index->open_count == 0) {
04dff721d2a63566a4dbe1c856f8218b6550aa3eTimo Sirainen /* index is already closed. don't even try to
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen } else if (index_dir != NULL && rec->index_dir_ino != 0) {
3aa84b022e0e24f468371ee813a4cd8acfd57052Timo Sirainen CMP_DEV_T(index_st->st_dev, rec->index_dir_dev)) {
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen /* make sure the directory still exists.
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen it might have been renamed and we're trying
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen to access it via its new path now. */
561049f25e47e45589e5da295112526b1431a9e0Timo Sirainen } else if (mailbox_path != NULL && rec->mailbox_path != NULL &&
561049f25e47e45589e5da295112526b1431a9e0Timo Sirainen index_dir == NULL && rec->index_dir_ino == 0) {
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen if (strcmp(mailbox_path, rec->mailbox_path) == 0)
82d158d37db5cfb4e26affe4bc2f2a235901d1b9Timo Sirainenmail_index_alloc_cache_get(struct event *parent_event, const char *mailbox_path,
3aa84b022e0e24f468371ee813a4cd8acfd57052Timo Sirainen /* compare index_dir inodes so we don't break even with symlinks.
3aa84b022e0e24f468371ee813a4cd8acfd57052Timo Sirainen if index_dir doesn't exist yet or if using in-memory indexes, just
3aa84b022e0e24f468371ee813a4cd8acfd57052Timo Sirainen compare mailbox paths */
3aa84b022e0e24f468371ee813a4cd8acfd57052Timo Sirainen /* in-memory indexes */
3aa84b022e0e24f468371ee813a4cd8acfd57052Timo Sirainen /* it'll be created later */
3aa84b022e0e24f468371ee813a4cd8acfd57052Timo Sirainen i_error("%s", eacces_error_get("stat", index_dir));
3aa84b022e0e24f468371ee813a4cd8acfd57052Timo Sirainen match = mail_index_alloc_cache_find(mailbox_path, index_dir, &st);
82d158d37db5cfb4e26affe4bc2f2a235901d1b9Timo Sirainen mail_index_alloc(parent_event, index_dir, prefix);
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen match = mail_index_alloc_cache_add(index, mailbox_path, &st);
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainenstatic bool destroy_unrefed(unsigned int min_destroy_count)
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen struct mail_index_alloc_cache_list **list, *rec;
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainen (min_destroy_count > 0 || rec->destroy_time <= ioloop_time)) {
4bed2aacac5ad4bb86ab034cd9adee8a565a4f1bTimo Sirainen /* we're the only one keeping this index open.
4bed2aacac5ad4bb86ab034cd9adee8a565a4f1bTimo Sirainen we might be here, because the caller is
4bed2aacac5ad4bb86ab034cd9adee8a565a4f1bTimo Sirainen deleting this mailbox and wants its indexes
4bed2aacac5ad4bb86ab034cd9adee8a565a4f1bTimo Sirainen to be closed. so close it. */
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainenindex_removal_timeout(void *context ATTR_UNUSED)
e10d8b1291090c26b9ef499637e6e632485ca5beTimo Sirainenvoid mail_index_alloc_cache_unref(struct mail_index **_index)
04dff721d2a63566a4dbe1c856f8218b6550aa3eTimo Sirainen struct mail_index_alloc_cache_list *list, **listp;
04dff721d2a63566a4dbe1c856f8218b6550aa3eTimo Sirainen for (listp = &indexes; *listp != NULL; listp = &(*listp)->next) {
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen list->destroy_time = ioloop_time + INDEX_CACHE_TIMEOUT;
04dff721d2a63566a4dbe1c856f8218b6550aa3eTimo Sirainen if (list->refcount == 0 && index->open_count == 0) {
04dff721d2a63566a4dbe1c856f8218b6550aa3eTimo Sirainen /* index was already closed. don't even try to cache it. */
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen to_index = timeout_add(INDEX_CACHE_TIMEOUT*1000/2,
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainenvoid mail_index_alloc_cache_destroy_unrefed(void)
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainenvoid mail_index_alloc_cache_index_opened(struct mail_index *index)
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen if (list != NULL && list->index_dir_ino == 0 &&
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen /* newly created index directory. update its stat. */
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainenvoid mail_index_alloc_cache_index_closing(struct mail_index *index)
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainen /* we're closing our referenced index */
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainen while (indexes_cache_references_count > INDEX_CACHE_MAX) {
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainen /* our cache is full already, don't keep more */
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainen /* keep the index referenced for caching */