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