dovecot-2.0-sslstream: Moved mail_index lookup cache from lib-st...
dovecot at dovecot.org
dovecot at dovecot.org
Sat Feb 13 03:00:51 EET 2010
details: http://hg.dovecot.org/dovecot-2.0-sslstream/rev/9d3b5cbef222
changeset: 10657:9d3b5cbef222
user: Timo Sirainen <tss at iki.fi>
date: Sun Feb 07 04:50:40 2010 +0200
description:
Moved mail_index lookup cache from lib-storage to lib-index.
Removed some code duplication as a result.
diffstat:
16 files changed, 248 insertions(+), 252 deletions(-)
src/lib-index/Makefile.am | 2
src/lib-index/mail-index-alloc-cache.c | 203 +++++++++++++++++++
src/lib-index/mail-index-alloc-cache.h | 15 +
src/lib-index/mail-index.c | 2
src/lib-storage/index/cydir/cydir-storage.c | 8
src/lib-storage/index/dbox-multi/mdbox-storage.c | 7
src/lib-storage/index/dbox-single/sdbox-storage.c | 8
src/lib-storage/index/index-storage.c | 217 ---------------------
src/lib-storage/index/index-storage.h | 4
src/lib-storage/index/maildir/maildir-storage.c | 8
src/lib-storage/index/mbox/mbox-storage.c | 3
src/lib-storage/index/raw/raw-storage.c | 2
src/lib-storage/index/shared/shared-storage.c | 2
src/lib-storage/mail-storage.c | 3
src/lib-storage/mailbox-list.c | 8
src/plugins/virtual/virtual-storage.c | 8
diffs (truncated from 765 to 300 lines):
diff -r fc0ac73f0b36 -r 9d3b5cbef222 src/lib-index/Makefile.am
--- a/src/lib-index/Makefile.am Sun Feb 07 03:25:32 2010 +0200
+++ b/src/lib-index/Makefile.am Sun Feb 07 04:50:40 2010 +0200
@@ -14,6 +14,7 @@ libindex_la_SOURCES = \
mail-cache-transaction.c \
mail-cache-sync-update.c \
mail-index.c \
+ mail-index-alloc-cache.c \
mail-index-dummy-view.c \
mail-index-fsck.c \
mail-index-lock.c \
@@ -48,6 +49,7 @@ headers = \
mail-cache.h \
mail-cache-private.h \
mail-index.h \
+ mail-index-alloc-cache.h \
mail-index-modseq.h \
mail-index-private.h \
mail-index-strmap.h \
diff -r fc0ac73f0b36 -r 9d3b5cbef222 src/lib-index/mail-index-alloc-cache.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-index/mail-index-alloc-cache.c Sun Feb 07 04:50:40 2010 +0200
@@ -0,0 +1,203 @@
+/* Copyright (c) 2010 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "ioloop.h"
+#include "module-context.h"
+#include "eacces-error.h"
+#include "mail-index-private.h"
+#include "mail-index-alloc-cache.h"
+
+#define MAIL_INDEX_ALLOC_CACHE_CONTEXT(obj) \
+ MODULE_CONTEXT(obj, mail_index_alloc_cache_index_module)
+
+/* How many seconds to keep index opened for reuse after it's been closed */
+#define INDEX_CACHE_TIMEOUT 10
+/* How many closed indexes to keep */
+#define INDEX_CACHE_MAX 3
+
+struct mail_index_alloc_cache_list {
+ union mail_index_module_context module_ctx;
+ struct mail_index_alloc_cache_list *next;
+
+ struct mail_index *index;
+ char *mailbox_path;
+ int refcount;
+
+ dev_t index_dir_dev;
+ ino_t index_dir_ino;
+
+ time_t destroy_time;
+};
+
+static MODULE_CONTEXT_DEFINE_INIT(mail_index_alloc_cache_index_module,
+ &mail_index_module_register);
+static struct mail_index_alloc_cache_list *indexes = NULL;
+static struct timeout *to_index = NULL;
+
+static struct mail_index_alloc_cache_list *
+mail_index_alloc_cache_add(struct mail_index *index,
+ const char *mailbox_path, struct stat *st)
+{
+ struct mail_index_alloc_cache_list *list;
+
+ list = i_new(struct mail_index_alloc_cache_list, 1);
+ list->refcount = 1;
+ list->index = index;
+
+ list->mailbox_path = i_strdup(mailbox_path);
+ list->index_dir_dev = st->st_dev;
+ list->index_dir_ino = st->st_ino;
+
+ list->next = indexes;
+ indexes = list;
+
+ MODULE_CONTEXT_SET(index, mail_index_alloc_cache_index_module, list);
+ return list;
+}
+
+static void
+mail_index_alloc_cache_list_free(struct mail_index_alloc_cache_list *list)
+{
+ mail_index_free(&list->index);
+ i_free(list->mailbox_path);
+ i_free(list);
+}
+
+struct mail_index *
+mail_index_alloc_cache_get(const char *mailbox_path,
+ const char *index_dir, const char *prefix)
+{
+ struct mail_index_alloc_cache_list **indexp, *rec, *match;
+ struct stat st, st2;
+ unsigned int destroy_count;
+
+ /* compare index_dir inodes so we don't break even with symlinks.
+ if index_dir doesn't exist yet or if using in-memory indexes, just
+ compare mailbox paths */
+ memset(&st, 0, sizeof(st));
+ if (index_dir == NULL) {
+ /* in-memory indexes */
+ } else if (stat(index_dir, &st) < 0) {
+ if (errno == ENOENT) {
+ /* it'll be created later */
+ } else if (errno == EACCES) {
+ i_error("%s", eacces_error_get("stat", index_dir));
+ } else {
+ i_error("stat(%s) failed: %m", index_dir);
+ }
+ }
+
+ destroy_count = 0; match = NULL;
+ for (indexp = &indexes; *indexp != NULL;) {
+ rec = *indexp;
+
+ if (match != NULL) {
+ /* already found the index. we're just going through
+ the rest of them to drop 0 refcounts */
+ } else if (index_dir != NULL && rec->index_dir_ino != 0) {
+ if (st.st_ino == rec->index_dir_ino &&
+ CMP_DEV_T(st.st_dev, rec->index_dir_dev)) {
+ /* make sure the directory still exists.
+ it might have been renamed and we're trying
+ to access it via its new path now. */
+ if (stat(rec->index->dir, &st2) < 0 ||
+ st2.st_ino != st.st_ino ||
+ !CMP_DEV_T(st2.st_dev, st.st_dev))
+ rec->destroy_time = 0;
+ else
+ match = rec;
+ }
+ } else {
+ if (strcmp(mailbox_path, rec->mailbox_path) == 0)
+ match = rec;
+ }
+
+ if (rec->refcount == 0 && rec != match) {
+ if (rec->destroy_time <= ioloop_time ||
+ destroy_count >= INDEX_CACHE_MAX) {
+ *indexp = rec->next;
+ mail_index_alloc_cache_list_free(rec);
+ continue;
+ } else {
+ destroy_count++;
+ }
+ }
+
+ indexp = &(*indexp)->next;
+ }
+
+ if (match == NULL) {
+ struct mail_index *index = mail_index_alloc(index_dir, prefix);
+ match = mail_index_alloc_cache_add(index, mailbox_path, &st);
+ } else {
+ match->refcount++;
+ }
+ i_assert(match->index != NULL);
+ return match->index;
+}
+
+static void destroy_unrefed(bool all)
+{
+ struct mail_index_alloc_cache_list **list, *rec;
+
+ for (list = &indexes; *list != NULL;) {
+ rec = *list;
+
+ if (rec->refcount == 0 &&
+ (all || rec->destroy_time <= ioloop_time)) {
+ *list = rec->next;
+ mail_index_alloc_cache_list_free(rec);
+ } else {
+ list = &(*list)->next;
+ }
+ }
+
+ if (indexes == NULL && to_index != NULL)
+ timeout_remove(&to_index);
+}
+
+static void index_removal_timeout(void *context ATTR_UNUSED)
+{
+ destroy_unrefed(FALSE);
+}
+
+void mail_index_alloc_cache_unref(struct mail_index *index)
+{
+ struct mail_index_alloc_cache_list *list;
+
+ for (list = indexes; list != NULL; list = list->next) {
+ if (list->index == index)
+ break;
+ }
+
+ i_assert(list != NULL);
+ i_assert(list->refcount > 0);
+
+ list->refcount--;
+ list->destroy_time = ioloop_time + INDEX_CACHE_TIMEOUT;
+ if (to_index == NULL) {
+ to_index = timeout_add(INDEX_CACHE_TIMEOUT*1000/2,
+ index_removal_timeout, NULL);
+ }
+}
+
+void mail_index_alloc_cache_destroy_unrefed(void)
+{
+ destroy_unrefed(TRUE);
+}
+
+void mail_index_alloc_cache_index_opened(struct mail_index *index)
+{
+ struct mail_index_alloc_cache_list *list =
+ MAIL_INDEX_ALLOC_CACHE_CONTEXT(index);
+ struct stat st;
+
+ if (list != NULL && list->index_dir_ino == 0 &&
+ !MAIL_INDEX_IS_IN_MEMORY(index)) {
+ /* newly created index directory. update its stat. */
+ if (stat(index->dir, &st) == 0) {
+ list->index_dir_ino = st.st_ino;
+ list->index_dir_dev = st.st_dev;
+ }
+ }
+}
diff -r fc0ac73f0b36 -r 9d3b5cbef222 src/lib-index/mail-index-alloc-cache.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-index/mail-index-alloc-cache.h Sun Feb 07 04:50:40 2010 +0200
@@ -0,0 +1,15 @@
+#ifndef MAIL_INDEX_ALLOC_CACHE_H
+#define MAIL_INDEX_ALLOC_CACHE_H
+
+/* If using in-memory indexes, give index_dir=NULL. */
+struct mail_index *
+mail_index_alloc_cache_get(const char *mailbox_path,
+ const char *index_dir, const char *prefix);
+void mail_index_alloc_cache_unref(struct mail_index *index);
+
+void mail_index_alloc_cache_destroy_unrefed(void);
+
+/* internal: */
+void mail_index_alloc_cache_index_opened(struct mail_index *index);
+
+#endif
diff -r fc0ac73f0b36 -r 9d3b5cbef222 src/lib-index/mail-index.c
--- a/src/lib-index/mail-index.c Sun Feb 07 03:25:32 2010 +0200
+++ b/src/lib-index/mail-index.c Sun Feb 07 04:50:40 2010 +0200
@@ -11,6 +11,7 @@
#include "nfs-workarounds.h"
#include "read-full.h"
#include "write-full.h"
+#include "mail-index-alloc-cache.h"
#include "mail-index-private.h"
#include "mail-index-view-private.h"
#include "mail-index-sync-private.h"
@@ -527,6 +528,7 @@ int mail_index_open(struct mail_index *i
i_assert(index->map != NULL);
index->opened = TRUE;
+ mail_index_alloc_cache_index_opened(index);
return 1;
}
diff -r fc0ac73f0b36 -r 9d3b5cbef222 src/lib-storage/index/cydir/cydir-storage.c
--- a/src/lib-storage/index/cydir/cydir-storage.c Sun Feb 07 03:25:32 2010 +0200
+++ b/src/lib-storage/index/cydir/cydir-storage.c Sun Feb 07 04:50:40 2010 +0200
@@ -201,12 +201,6 @@ cydir_list_delete_mailbox(struct mailbox
struct cydir_mailbox_list *mlist = CYDIR_LIST_CONTEXT(list);
struct stat st;
const char *src;
-
- /* Make sure the indexes are closed before trying to delete the
- directory that contains them. It can still fail with some NFS
- implementations if indexes are opened by another session, but
- that can't really be helped. */
- index_storage_destroy_unrefed();
/* delete the index and control directories */
if (mlist->module_ctx.super.delete_mailbox(list, name) < 0)
@@ -309,7 +303,7 @@ struct mail_storage cydir_storage = {
NULL,
cydir_storage_alloc,
NULL,
- index_storage_destroy,
+ NULL,
cydir_storage_add_list,
cydir_storage_get_list_settings,
NULL,
diff -r fc0ac73f0b36 -r 9d3b5cbef222 src/lib-storage/index/dbox-multi/mdbox-storage.c
--- a/src/lib-storage/index/dbox-multi/mdbox-storage.c Sun Feb 07 03:25:32 2010 +0200
+++ b/src/lib-storage/index/dbox-multi/mdbox-storage.c Sun Feb 07 04:50:40 2010 +0200
@@ -97,7 +97,6 @@ static void mdbox_storage_destroy(struct
mdbox_files_free(storage);
dbox_map_deinit(&storage->map);
array_free(&storage->open_files);
- index_storage_destroy(_storage);
}
struct mailbox *
More information about the dovecot-cvs
mailing list