bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2010-2018 Dovecot authors, see the included COPYING file */
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen#include "lib.h"
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen#include "ioloop.h"
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen#include "module-context.h"
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen#include "eacces-error.h"
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen#include "mail-index-private.h"
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen#include "mail-index-alloc-cache.h"
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen#define MAIL_INDEX_ALLOC_CACHE_CONTEXT(obj) \
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen MODULE_CONTEXT(obj, mail_index_alloc_cache_index_module)
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen/* How many seconds to keep index opened for reuse after it's been closed */
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen#define INDEX_CACHE_TIMEOUT 10
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen/* How many closed indexes to keep */
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen#define INDEX_CACHE_MAX 3
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainenstruct mail_index_alloc_cache_list {
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen union mail_index_module_context module_ctx;
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen struct mail_index_alloc_cache_list *next;
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen struct mail_index *index;
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen char *mailbox_path;
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen int refcount;
4bed2aacac5ad4bb86ab034cd9adee8a565a4f1bTimo Sirainen bool referenced;
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen dev_t index_dir_dev;
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen ino_t index_dir_ino;
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen time_t destroy_time;
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen};
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(mail_index_alloc_cache_index_module,
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen &mail_index_module_register);
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainenstatic struct mail_index_alloc_cache_list *indexes = NULL;
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainenstatic unsigned int indexes_cache_references_count = 0;
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainenstatic struct timeout *to_index = NULL;
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainenstatic struct mail_index_alloc_cache_list *
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainenmail_index_alloc_cache_add(struct mail_index *index,
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen const char *mailbox_path, struct stat *st)
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen{
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen struct mail_index_alloc_cache_list *list;
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen list = i_new(struct mail_index_alloc_cache_list, 1);
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen list->refcount = 1;
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen list->index = index;
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen list->mailbox_path = i_strdup(mailbox_path);
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen list->index_dir_dev = st->st_dev;
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen list->index_dir_ino = st->st_ino;
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen list->next = indexes;
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen indexes = list;
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen MODULE_CONTEXT_SET(index, mail_index_alloc_cache_index_module, list);
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen return list;
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen}
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainenstatic void
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainenmail_index_alloc_cache_list_unref(struct mail_index_alloc_cache_list *list)
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainen{
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainen i_assert(list->referenced);
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainen i_assert(indexes_cache_references_count > 0);
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainen
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainen indexes_cache_references_count--;
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainen mail_index_close(list->index);
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainen list->referenced = FALSE;
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainen}
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainen
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainenstatic void
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainenmail_index_alloc_cache_list_free(struct mail_index_alloc_cache_list *list)
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen{
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainen i_assert(list->refcount == 0);
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainen
4bed2aacac5ad4bb86ab034cd9adee8a565a4f1bTimo Sirainen if (list->referenced)
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainen mail_index_alloc_cache_list_unref(list);
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen mail_index_free(&list->index);
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen i_free(list->mailbox_path);
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen i_free(list);
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen}
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen
3aa84b022e0e24f468371ee813a4cd8acfd57052Timo Sirainenstatic struct mail_index_alloc_cache_list *
3aa84b022e0e24f468371ee813a4cd8acfd57052Timo Sirainenmail_index_alloc_cache_find(const char *mailbox_path, const char *index_dir,
3aa84b022e0e24f468371ee813a4cd8acfd57052Timo Sirainen const struct stat *index_st)
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen{
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen struct mail_index_alloc_cache_list **indexp, *rec, *match;
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen unsigned int destroy_count;
3aa84b022e0e24f468371ee813a4cd8acfd57052Timo Sirainen struct stat st;
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen destroy_count = 0; match = NULL;
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen for (indexp = &indexes; *indexp != NULL;) {
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen rec = *indexp;
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen if (match != NULL) {
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
04dff721d2a63566a4dbe1c856f8218b6550aa3eTimo Sirainen reuse it. */
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen } else if (index_dir != NULL && rec->index_dir_ino != 0) {
3aa84b022e0e24f468371ee813a4cd8acfd57052Timo Sirainen if (index_st->st_ino == rec->index_dir_ino &&
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. */
3aa84b022e0e24f468371ee813a4cd8acfd57052Timo Sirainen if (stat(rec->index->dir, &st) < 0 ||
3aa84b022e0e24f468371ee813a4cd8acfd57052Timo Sirainen st.st_ino != index_st->st_ino ||
3aa84b022e0e24f468371ee813a4cd8acfd57052Timo Sirainen !CMP_DEV_T(st.st_dev, index_st->st_dev))
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen rec->destroy_time = 0;
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen else
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen match = rec;
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen }
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)
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen match = rec;
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen }
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen if (rec->refcount == 0 && rec != match) {
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen if (rec->destroy_time <= ioloop_time ||
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen destroy_count >= INDEX_CACHE_MAX) {
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen *indexp = rec->next;
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen mail_index_alloc_cache_list_free(rec);
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen continue;
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen } else {
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen destroy_count++;
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen }
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen }
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen indexp = &(*indexp)->next;
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen }
3aa84b022e0e24f468371ee813a4cd8acfd57052Timo Sirainen return match;
3aa84b022e0e24f468371ee813a4cd8acfd57052Timo Sirainen}
3aa84b022e0e24f468371ee813a4cd8acfd57052Timo Sirainen
3aa84b022e0e24f468371ee813a4cd8acfd57052Timo Sirainenstruct mail_index *
82d158d37db5cfb4e26affe4bc2f2a235901d1b9Timo Sirainenmail_index_alloc_cache_get(struct event *parent_event, const char *mailbox_path,
3aa84b022e0e24f468371ee813a4cd8acfd57052Timo Sirainen const char *index_dir, const char *prefix)
3aa84b022e0e24f468371ee813a4cd8acfd57052Timo Sirainen{
3aa84b022e0e24f468371ee813a4cd8acfd57052Timo Sirainen struct mail_index_alloc_cache_list *match;
3aa84b022e0e24f468371ee813a4cd8acfd57052Timo Sirainen struct stat st;
3aa84b022e0e24f468371ee813a4cd8acfd57052Timo Sirainen
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 */
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&st);
3aa84b022e0e24f468371ee813a4cd8acfd57052Timo Sirainen if (index_dir == NULL) {
3aa84b022e0e24f468371ee813a4cd8acfd57052Timo Sirainen /* in-memory indexes */
3aa84b022e0e24f468371ee813a4cd8acfd57052Timo Sirainen } else if (stat(index_dir, &st) < 0) {
3aa84b022e0e24f468371ee813a4cd8acfd57052Timo Sirainen if (errno == ENOENT) {
3aa84b022e0e24f468371ee813a4cd8acfd57052Timo Sirainen /* it'll be created later */
3aa84b022e0e24f468371ee813a4cd8acfd57052Timo Sirainen } else if (errno == EACCES) {
3aa84b022e0e24f468371ee813a4cd8acfd57052Timo Sirainen i_error("%s", eacces_error_get("stat", index_dir));
3aa84b022e0e24f468371ee813a4cd8acfd57052Timo Sirainen } else {
3aa84b022e0e24f468371ee813a4cd8acfd57052Timo Sirainen i_error("stat(%s) failed: %m", index_dir);
3aa84b022e0e24f468371ee813a4cd8acfd57052Timo Sirainen }
3aa84b022e0e24f468371ee813a4cd8acfd57052Timo Sirainen }
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen
3aa84b022e0e24f468371ee813a4cd8acfd57052Timo Sirainen match = mail_index_alloc_cache_find(mailbox_path, index_dir, &st);
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen if (match == NULL) {
82d158d37db5cfb4e26affe4bc2f2a235901d1b9Timo Sirainen struct mail_index *index =
82d158d37db5cfb4e26affe4bc2f2a235901d1b9Timo Sirainen mail_index_alloc(parent_event, index_dir, prefix);
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen match = mail_index_alloc_cache_add(index, mailbox_path, &st);
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen } else {
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen match->refcount++;
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen }
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen i_assert(match->index != NULL);
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen return match->index;
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen}
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainenstatic bool destroy_unrefed(unsigned int min_destroy_count)
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen{
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen struct mail_index_alloc_cache_list **list, *rec;
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainen bool destroyed = FALSE;
ae283d4d463bce538ec78de2554542c9a15be3dcTimo Sirainen bool seen_ref0 = FALSE;
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen for (list = &indexes; *list != NULL;) {
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen rec = *list;
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen if (rec->refcount == 0 &&
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainen (min_destroy_count > 0 || rec->destroy_time <= ioloop_time)) {
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen *list = rec->next;
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainen destroyed = TRUE;
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen mail_index_alloc_cache_list_free(rec);
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainen if (min_destroy_count > 0)
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainen min_destroy_count--;
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen } else {
ae283d4d463bce538ec78de2554542c9a15be3dcTimo Sirainen if (rec->refcount == 0)
ae283d4d463bce538ec78de2554542c9a15be3dcTimo Sirainen seen_ref0 = TRUE;
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainen if (min_destroy_count > 0 &&
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainen rec->index->open_count == 1 &&
4bed2aacac5ad4bb86ab034cd9adee8a565a4f1bTimo Sirainen rec->referenced) {
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. */
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainen destroyed = TRUE;
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainen mail_index_alloc_cache_list_unref(rec);
4bed2aacac5ad4bb86ab034cd9adee8a565a4f1bTimo Sirainen }
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen list = &(*list)->next;
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen }
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen }
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen
ae283d4d463bce538ec78de2554542c9a15be3dcTimo Sirainen if (!seen_ref0 && to_index != NULL)
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen timeout_remove(&to_index);
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainen return destroyed;
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen}
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainenstatic void ATTR_NULL(1)
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainenindex_removal_timeout(void *context ATTR_UNUSED)
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen{
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainen destroy_unrefed(0);
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen}
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen
e10d8b1291090c26b9ef499637e6e632485ca5beTimo Sirainenvoid mail_index_alloc_cache_unref(struct mail_index **_index)
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen{
e10d8b1291090c26b9ef499637e6e632485ca5beTimo Sirainen struct mail_index *index = *_index;
04dff721d2a63566a4dbe1c856f8218b6550aa3eTimo Sirainen struct mail_index_alloc_cache_list *list, **listp;
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen
e10d8b1291090c26b9ef499637e6e632485ca5beTimo Sirainen *_index = NULL;
04dff721d2a63566a4dbe1c856f8218b6550aa3eTimo Sirainen list = NULL;
04dff721d2a63566a4dbe1c856f8218b6550aa3eTimo Sirainen for (listp = &indexes; *listp != NULL; listp = &(*listp)->next) {
04dff721d2a63566a4dbe1c856f8218b6550aa3eTimo Sirainen if ((*listp)->index == index) {
04dff721d2a63566a4dbe1c856f8218b6550aa3eTimo Sirainen list = *listp;
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen break;
04dff721d2a63566a4dbe1c856f8218b6550aa3eTimo Sirainen }
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen }
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen i_assert(list != NULL);
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen i_assert(list->refcount > 0);
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen list->refcount--;
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen list->destroy_time = ioloop_time + INDEX_CACHE_TIMEOUT;
04dff721d2a63566a4dbe1c856f8218b6550aa3eTimo Sirainen
04dff721d2a63566a4dbe1c856f8218b6550aa3eTimo Sirainen if (list->refcount == 0 && index->open_count == 0) {
04dff721d2a63566a4dbe1c856f8218b6550aa3eTimo Sirainen /* index was already closed. don't even try to cache it. */
04dff721d2a63566a4dbe1c856f8218b6550aa3eTimo Sirainen *listp = list->next;
04dff721d2a63566a4dbe1c856f8218b6550aa3eTimo Sirainen mail_index_alloc_cache_list_free(list);
04dff721d2a63566a4dbe1c856f8218b6550aa3eTimo Sirainen } else if (to_index == NULL) {
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen to_index = timeout_add(INDEX_CACHE_TIMEOUT*1000/2,
677b75f90d81eafe742896d6570a2f63ce501d05Josef 'Jeff' Sipek index_removal_timeout, NULL);
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen }
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen}
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainenvoid mail_index_alloc_cache_destroy_unrefed(void)
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen{
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainen destroy_unrefed(UINT_MAX);
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen}
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainenvoid mail_index_alloc_cache_index_opened(struct mail_index *index)
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen{
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen struct mail_index_alloc_cache_list *list =
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen MAIL_INDEX_ALLOC_CACHE_CONTEXT(index);
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen struct stat st;
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen if (list != NULL && list->index_dir_ino == 0 &&
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen !MAIL_INDEX_IS_IN_MEMORY(index)) {
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen /* newly created index directory. update its stat. */
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen if (stat(index->dir, &st) == 0) {
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen list->index_dir_ino = st.st_ino;
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen list->index_dir_dev = st.st_dev;
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen }
ae283d4d463bce538ec78de2554542c9a15be3dcTimo Sirainen }
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainen}
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainen
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainenvoid mail_index_alloc_cache_index_closing(struct mail_index *index)
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainen{
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainen struct mail_index_alloc_cache_list *list =
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainen MAIL_INDEX_ALLOC_CACHE_CONTEXT(index);
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainen
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainen i_assert(index->open_count > 0);
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainen if (index->open_count > 1 || list == NULL)
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainen return;
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainen
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainen if (list->referenced) {
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainen /* we're closing our referenced index */
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainen return;
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainen }
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainen while (indexes_cache_references_count > INDEX_CACHE_MAX) {
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainen if (!destroy_unrefed(1)) {
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainen /* our cache is full already, don't keep more */
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainen return;
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainen }
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen }
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainen /* keep the index referenced for caching */
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainen indexes_cache_references_count++;
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainen list->referenced = TRUE;
0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509Timo Sirainen index->open_count++;
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen}