dovecot-1.2: Added a simple flat file dict backend.

dovecot at dovecot.org dovecot at dovecot.org
Sun Oct 19 02:07:41 EEST 2008


details:   http://hg.dovecot.org/dovecot-1.2/rev/9d963e3bbe65
changeset: 8300:9d963e3bbe65
user:      Timo Sirainen <tss at iki.fi>
date:      Sun Oct 19 02:07:34 2008 +0300
description:
Added a simple flat file dict backend.

diffstat:

10 files changed, 433 insertions(+), 15 deletions(-)
src/deliver/deliver.c            |    6 
src/imap/main.c                  |    6 
src/lib-dict/Makefile.am         |    3 
src/lib-dict/dict-client.h       |    2 
src/lib-dict/dict-file.c         |  401 ++++++++++++++++++++++++++++++++++++++
src/lib-dict/dict-private.h      |    3 
src/lib-dict/dict.c              |   12 +
src/lib-dict/dict.h              |    3 
src/plugins/expire/expire-tool.c |    6 
src/pop3/main.c                  |    6 

diffs (truncated from 596 to 300 lines):

diff -r da848018d760 -r 9d963e3bbe65 src/deliver/deliver.c
--- a/src/deliver/deliver.c	Sun Oct 19 02:01:03 2008 +0300
+++ b/src/deliver/deliver.c	Sun Oct 19 02:07:34 2008 +0300
@@ -24,7 +24,7 @@
 #include "message-address.h"
 #include "mail-namespace.h"
 #include "raw-storage.h"
-#include "dict-client.h"
+#include "dict.h"
 #include "auth-client.h"
 #include "mail-send.h"
 #include "duplicate.h"
@@ -1019,7 +1019,7 @@ int main(int argc, char *argv[])
 	if (deliver_set->log_format == NULL)
 		deliver_set->log_format = DEFAULT_LOG_FORMAT;
 
-	dict_driver_register(&dict_driver_client);
+	dict_drivers_register_builtin();
         duplicate_init();
         mail_storage_init();
 	mail_storage_register_all();
@@ -1147,7 +1147,7 @@ int main(int argc, char *argv[])
 	mail_storage_deinit();
 
 	duplicate_deinit();
-	dict_driver_unregister(&dict_driver_client);
+	dict_drivers_unregister_builtin();
 	lib_signals_deinit();
 
 	io_loop_destroy(&ioloop);
diff -r da848018d760 -r 9d963e3bbe65 src/imap/main.c
--- a/src/imap/main.c	Sun Oct 19 02:01:03 2008 +0300
+++ b/src/imap/main.c	Sun Oct 19 02:07:34 2008 +0300
@@ -12,7 +12,7 @@
 #include "fd-close-on-exec.h"
 #include "process-title.h"
 #include "module-dir.h"
-#include "dict-client.h"
+#include "dict.h"
 #include "mail-storage.h"
 #include "commands.h"
 #include "mail-namespace.h"
@@ -193,7 +193,7 @@ static void main_init(void)
 	capability_string = str_new(default_pool, sizeof(CAPABILITY_STRING)+32);
 	str_append(capability_string, CAPABILITY_STRING);
 
-	dict_driver_register(&dict_driver_client);
+	dict_drivers_register_builtin();
         mail_storage_init();
 	mail_storage_register_all();
 	mailbox_list_register_all();
@@ -272,7 +272,7 @@ static void main_deinit(void)
 	module_dir_unload(&modules);
 	commands_deinit();
         mail_storage_deinit();
-	dict_driver_unregister(&dict_driver_client);
+	dict_drivers_unregister_builtin();
 
 	str_free(&capability_string);
 
diff -r da848018d760 -r 9d963e3bbe65 src/lib-dict/Makefile.am
--- a/src/lib-dict/Makefile.am	Sun Oct 19 02:01:03 2008 +0300
+++ b/src/lib-dict/Makefile.am	Sun Oct 19 02:07:34 2008 +0300
@@ -11,7 +11,8 @@ AM_CPPFLAGS = \
 
 base_sources = \
 	dict.c \
-	dict-client.c
+	dict-client.c \
+	dict-file.c
 
 backend_sources = \
 	dict-db.c \
diff -r da848018d760 -r 9d963e3bbe65 src/lib-dict/dict-client.h
--- a/src/lib-dict/dict-client.h	Sun Oct 19 02:01:03 2008 +0300
+++ b/src/lib-dict/dict-client.h	Sun Oct 19 02:07:34 2008 +0300
@@ -33,8 +33,6 @@ enum {
 	DICT_PROTOCOL_REPLY_FAIL = 'F'
 };
 
-extern struct dict dict_driver_client;
-
 const char *dict_client_escape(const char *src);
 const char *dict_client_unescape(const char *src);
 
diff -r da848018d760 -r 9d963e3bbe65 src/lib-dict/dict-file.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-dict/dict-file.c	Sun Oct 19 02:07:34 2008 +0300
@@ -0,0 +1,401 @@
+/* Copyright (c) 2008 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "array.h"
+#include "hash.h"
+#include "file-dotlock.h"
+#include "nfs-workarounds.h"
+#include "istream.h"
+#include "ostream.h"
+#include "dict-private.h"
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+struct file_dict {
+	struct dict dict;
+	pool_t hash_pool;
+
+	char *path;
+	struct hash_table *hash;
+	int fd;
+};
+
+struct file_dict_iterate_context {
+	struct dict_iterate_context ctx;
+
+	struct hash_iterate_context *iter;
+	char *path;
+	unsigned int path_len;
+
+	enum dict_iterate_flags flags;
+	unsigned int failed:1;
+};
+
+enum file_dict_change_type {
+	FILE_DICT_CHANGE_TYPE_SET,
+	FILE_DICT_CHANGE_TYPE_UNSET,
+	FILE_DICT_CHANGE_TYPE_INC
+};
+
+struct file_dict_change {
+	enum file_dict_change_type type;
+	const char *key;
+	union {
+		const char *str;
+		long long diff;
+	} value;
+};
+
+struct file_dict_transaction_context {
+	struct dict_transaction_context ctx;
+
+	pool_t pool;
+	ARRAY_DEFINE(changes, struct file_dict_change);
+};
+
+static struct dotlock_settings file_dict_dotlock_settings = {
+	MEMBER(temp_prefix) NULL,
+	MEMBER(lock_suffix) NULL,
+
+	MEMBER(timeout) 30,
+	MEMBER(stale_timeout) 5
+};
+
+static struct dict *file_dict_init(struct dict *driver, const char *uri,
+				   enum dict_data_type value_type ATTR_UNUSED,
+				   const char *username ATTR_UNUSED)
+{
+	struct file_dict *dict;
+	
+	dict = i_new(struct file_dict, 1);
+	dict->dict = *driver;
+	dict->path = i_strdup(uri);
+	dict->hash_pool = pool_alloconly_create("file dict", 1024);
+	dict->hash = hash_create(default_pool, dict->hash_pool, 0, str_hash,
+				 (hash_cmp_callback_t *)strcmp);
+	dict->fd = -1;
+	return &dict->dict;
+}
+
+static void file_dict_deinit(struct dict *_dict)
+{
+	struct file_dict *dict = (struct file_dict *)_dict;
+
+	hash_destroy(&dict->hash);
+	pool_unref(&dict->hash_pool);
+	i_free(dict->path);
+	i_free(dict);
+}
+
+static bool file_dict_need_refresh(struct file_dict *dict)
+{
+	struct stat st1, st2;
+
+	if (dict->fd == -1)
+		return TRUE;
+
+	nfs_flush_file_handle_cache(dict->path);
+	if (nfs_safe_stat(dict->path, &st1) < 0) {
+		i_error("stat(%s) failed: %m", dict->path);
+		return FALSE;
+	}
+
+	if (fstat(dict->fd, &st2) < 0) {
+		if (errno != ESTALE)
+			i_error("fstat(%s) failed: %m", dict->path);
+		return TRUE;
+	}
+	if (st1.st_ino != st2.st_ino ||
+	    !CMP_DEV_T(st1.st_dev, st2.st_dev)) {
+		/* file changed */
+		return TRUE;
+	}
+	return FALSE;
+}
+
+static int file_dict_refresh(struct file_dict *dict)
+{
+	struct istream *input;
+	char *key, *value;
+
+	if (!file_dict_need_refresh(dict))
+		return 0;
+
+	if (dict->fd != -1) {
+		if (close(dict->fd) < 0)
+			i_error("close(%s) failed: %m", dict->path);
+	}
+	dict->fd = open(dict->path, O_RDONLY);
+	if (dict->fd == -1) {
+		if (errno == ENOENT)
+			return 0;
+		i_error("open(%s) failed: %m", dict->path);
+		return -1;
+	}
+
+	hash_clear(dict->hash, TRUE);
+	p_clear(dict->hash_pool);
+
+	input = i_stream_create_fd(dict->fd, (size_t)-1, FALSE);
+	while ((key = i_stream_read_next_line(input)) != NULL &&
+	       (value = i_stream_read_next_line(input)) != NULL) {
+		key = p_strdup(dict->hash_pool, key);
+		value = p_strdup(dict->hash_pool, value);
+		hash_insert(dict->hash, key, value);
+	}
+	i_stream_destroy(&input);
+	return 0;
+}
+
+static int file_dict_lookup(struct dict *_dict, pool_t pool,
+			    const char *key, const char **value_r)
+{
+	struct file_dict *dict = (struct file_dict *)_dict;
+
+	if (file_dict_refresh(dict) < 0)
+		return -1;
+
+	*value_r = p_strdup(pool, hash_lookup(dict->hash, key));
+	return *value_r == NULL ? 0 : 1;
+}
+
+static struct dict_iterate_context *
+file_dict_iterate_init(struct dict *_dict, const char *path,
+		       enum dict_iterate_flags flags)
+{
+        struct file_dict_iterate_context *ctx;
+	struct file_dict *dict = (struct file_dict *)_dict;
+
+	ctx = i_new(struct file_dict_iterate_context, 1);
+	ctx->path = i_strdup(path);
+	ctx->path_len = strlen(path);
+	ctx->flags = flags;
+	ctx->iter = hash_iterate_init(dict->hash);
+
+	if (file_dict_refresh(dict) < 0)
+		ctx->failed = TRUE;
+	return &ctx->ctx;
+}
+
+static int file_dict_iterate(struct dict_iterate_context *_ctx,
+			     const char **key_r, const char **value_r)
+{
+	struct file_dict_iterate_context *ctx =
+		(struct file_dict_iterate_context *)_ctx;
+	void *key, *value;
+
+	while (hash_iterate(ctx->iter, &key, &value)) {
+		if (strncmp(ctx->path, key, ctx->path_len) != 0)
+			continue;
+
+		if ((ctx->flags & DICT_ITERATE_FLAG_RECURSE) == 0 &&
+		    strchr(key + ctx->path_len, '/') != NULL)
+			continue;
+
+		*key_r = key;
+		*value_r = value;
+		return 1;
+	}
+	return ctx->failed ? -1 : 0;
+}
+
+static void file_dict_iterate_deinit(struct dict_iterate_context *_ctx)
+{
+	struct file_dict_iterate_context *ctx =
+		(struct file_dict_iterate_context *)_ctx;
+
+	hash_iterate_deinit(&ctx->iter);
+	i_free(ctx->path);


More information about the dovecot-cvs mailing list