dovecot-2.2: lib-dict: Added "fs" wrapper dict backend, which us...

dovecot at dovecot.org dovecot at dovecot.org
Sun Dec 8 21:26:49 EET 2013


details:   http://hg.dovecot.org/dovecot-2.2/rev/773e9ce608ed
changeset: 17043:773e9ce608ed
user:      Timo Sirainen <tss at iki.fi>
date:      Sun Dec 08 21:13:22 2013 +0200
description:
lib-dict: Added "fs" wrapper dict backend, which uses lib-fs.
Each dict key is a separate file where the file's contents are the dict
value.

diffstat:

 src/lib-dict/Makefile.am     |    3 +
 src/lib-dict/dict-fs.c       |  201 +++++++++++++++++++++++++++++++++++++++++++
 src/lib-dict/dict-private.h  |    1 +
 src/lib-dict/dict-register.c |   24 +++++
 src/lib-dict/dict.c          |   18 ---
 5 files changed, 229 insertions(+), 18 deletions(-)

diffs (295 lines):

diff -r eeadb7b5045b -r 773e9ce608ed src/lib-dict/Makefile.am
--- a/src/lib-dict/Makefile.am	Sun Dec 08 20:48:03 2013 +0200
+++ b/src/lib-dict/Makefile.am	Sun Dec 08 21:13:22 2013 +0200
@@ -6,6 +6,7 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/lib \
 	-I$(top_srcdir)/src/lib-test \
+	-I$(top_srcdir)/src/lib-fs \
 	-I$(top_srcdir)/src/lib-sql \
 	-I$(top_srcdir)/src/lib-settings \
 	$(SQL_CFLAGS)
@@ -15,9 +16,11 @@
 	dict-client.c \
 	dict-file.c \
 	dict-cdb.c \
+	dict-fs.c \
 	dict-memcached.c \
 	dict-memcached-ascii.c \
 	dict-redis.c \
+	dict-register.c \
 	dict-transaction-memory.c
 
 libdict_la_SOURCES = \
diff -r eeadb7b5045b -r 773e9ce608ed src/lib-dict/dict-fs.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-dict/dict-fs.c	Sun Dec 08 21:13:22 2013 +0200
@@ -0,0 +1,201 @@
+/* Copyright (c) 2013 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "array.h"
+#include "fs-api.h"
+#include "istream.h"
+#include "str.h"
+#include "dict-transaction-memory.h"
+#include "dict-private.h"
+
+struct fs_dict {
+	struct dict dict;
+	struct fs *fs;
+	char *username;
+};
+
+static int
+fs_dict_init(struct dict *driver, const char *uri,
+	     enum dict_data_type value_type ATTR_UNUSED,
+	     const char *username,
+	     const char *base_dir, struct dict **dict_r,
+	     const char **error_r)
+{
+	struct fs_settings fs_set;
+	struct fs *fs;
+	struct fs_dict *dict;
+	const char *p, *fs_driver, *fs_args;
+
+	p = strchr(uri, ':');
+	if (p == NULL) {
+		fs_driver = uri;
+		fs_args = "";
+	} else {
+		fs_driver = t_strdup_until(uri, p);
+		fs_args = p+1;
+	}
+
+	memset(&fs_set, 0, sizeof(fs_set));
+	fs_set.base_dir = base_dir;
+	if (fs_init(fs_driver, fs_args, &fs_set, &fs, error_r) < 0)
+		return -1;
+
+	dict = i_new(struct fs_dict, 1);
+	dict->dict = *driver;
+	dict->fs = fs;
+	dict->username = i_strdup(username);
+
+	*dict_r = &dict->dict;
+	return 0;
+}
+
+static void fs_dict_deinit(struct dict *_dict)
+{
+	struct fs_dict *dict = (struct fs_dict *)_dict;
+
+	fs_deinit(&dict->fs);
+	i_free(dict->username);
+	i_free(dict);
+}
+
+static const char *fs_dict_get_full_key(struct fs_dict *dict, const char *key)
+{
+	if (strncmp(key, DICT_PATH_SHARED, strlen(DICT_PATH_SHARED)) == 0)
+		return key + strlen(DICT_PATH_SHARED);
+	else if (strncmp(key, DICT_PATH_PRIVATE, strlen(DICT_PATH_PRIVATE)) == 0) {
+		return t_strdup_printf("%s/%s", dict->username,
+				       key + strlen(DICT_PATH_PRIVATE));
+	} else {
+		i_unreached();
+	}
+}
+
+static int fs_dict_lookup(struct dict *_dict, pool_t pool,
+			  const char *key, const char **value_r)
+{
+	struct fs_dict *dict = (struct fs_dict *)_dict;
+	struct fs_file *file;
+	struct istream *input;
+	const unsigned char *data;
+	size_t size;
+	string_t *str;
+	int ret;
+
+	file = fs_file_init(dict->fs, fs_dict_get_full_key(dict, key),
+			    FS_OPEN_MODE_READONLY);
+	input = fs_read_stream(file, IO_BLOCK_SIZE);
+	i_stream_read(input);
+
+	str = str_new(pool, i_stream_get_data_size(input)+1);
+	while ((ret = i_stream_read_data(input, &data, &size, 0)) > 0) {
+		str_append_n(str, data, size);
+		i_stream_skip(input, size);
+	}
+	i_assert(ret == -1);
+
+	if (input->stream_errno == 0) {
+		*value_r = str_c(str);
+		ret = 1;
+	} else {
+		*value_r = NULL;
+		if (input->stream_errno == ENOENT)
+			ret = 0;
+	}
+
+	i_stream_unref(&input);
+	fs_file_deinit(&file);
+	return ret;
+}
+
+static struct dict_transaction_context *
+fs_dict_transaction_init(struct dict *_dict)
+{
+	struct dict_transaction_memory_context *ctx;
+	pool_t pool;
+
+	pool = pool_alloconly_create("file dict transaction", 2048);
+	ctx = p_new(pool, struct dict_transaction_memory_context, 1);
+	dict_transaction_memory_init(ctx, _dict, pool);
+	return &ctx->ctx;
+}
+
+static int fs_dict_write_changes(struct dict_transaction_memory_context *ctx)
+{
+	struct fs_dict *dict = (struct fs_dict *)ctx->ctx.dict;
+	struct fs_file *file;
+	const struct dict_transaction_memory_change *change;
+	const char *key;
+	int ret = 0;
+
+	array_foreach(&ctx->changes, change) {
+		key = fs_dict_get_full_key(dict, change->key);
+		switch (change->type) {
+		case DICT_CHANGE_TYPE_SET:
+			file = fs_file_init(dict->fs, key,
+					    FS_OPEN_MODE_REPLACE);
+			if (fs_write(file, change->value.str, strlen(change->value.str)) < 0) {
+				i_error("fs_write(%s) failed: %s", key,
+					fs_file_last_error(file));
+				ret = -1;
+			}
+			fs_file_deinit(&file);
+			break;
+		case DICT_CHANGE_TYPE_UNSET:
+			file = fs_file_init(dict->fs, key, FS_OPEN_MODE_READONLY);
+			if (fs_delete(file) < 0) {
+				i_error("fs_delete(%s) failed: %s", key,
+					fs_file_last_error(file));
+				ret = -1;
+			}
+			fs_file_deinit(&file);
+			break;
+		case DICT_CHANGE_TYPE_APPEND:
+		case DICT_CHANGE_TYPE_INC:
+			i_unreached();
+		}
+		if (ret < 0)
+			return -1;
+	}
+	return 0;
+}
+
+static int
+fs_dict_transaction_commit(struct dict_transaction_context *_ctx,
+			   bool async ATTR_UNUSED,
+			   dict_transaction_commit_callback_t *callback,
+			   void *context)
+{
+	struct dict_transaction_memory_context *ctx =
+		(struct dict_transaction_memory_context *)_ctx;
+	int ret;
+
+	if (fs_dict_write_changes(ctx) < 0)
+		ret = -1;
+	else
+		ret = 1;
+	pool_unref(&ctx->pool);
+
+	if (callback != NULL)
+		callback(ret, context);
+	return ret;
+}
+
+struct dict dict_driver_fs = {
+	.name = "fs",
+	{
+		fs_dict_init,
+		fs_dict_deinit,
+		NULL,
+		fs_dict_lookup,
+		NULL,
+		NULL,
+		NULL,
+		fs_dict_transaction_init,
+		fs_dict_transaction_commit,
+		dict_transaction_memory_rollback,
+		dict_transaction_memory_set,
+		dict_transaction_memory_unset,
+		NULL,
+		NULL
+	}
+};
diff -r eeadb7b5045b -r 773e9ce608ed src/lib-dict/dict-private.h
--- a/src/lib-dict/dict-private.h	Sun Dec 08 20:48:03 2013 +0200
+++ b/src/lib-dict/dict-private.h	Sun Dec 08 21:13:22 2013 +0200
@@ -56,6 +56,7 @@
 
 extern struct dict dict_driver_client;
 extern struct dict dict_driver_file;
+extern struct dict dict_driver_fs;
 extern struct dict dict_driver_memcached;
 extern struct dict dict_driver_memcached_ascii;
 extern struct dict dict_driver_redis;
diff -r eeadb7b5045b -r 773e9ce608ed src/lib-dict/dict-register.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-dict/dict-register.c	Sun Dec 08 21:13:22 2013 +0200
@@ -0,0 +1,24 @@
+/* Copyright (c) 2013 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "dict-private.h"
+
+void dict_drivers_register_builtin(void)
+{
+	dict_driver_register(&dict_driver_client);
+	dict_driver_register(&dict_driver_file);
+	dict_driver_register(&dict_driver_fs);
+	dict_driver_register(&dict_driver_memcached);
+	dict_driver_register(&dict_driver_memcached_ascii);
+	dict_driver_register(&dict_driver_redis);
+}
+
+void dict_drivers_unregister_builtin(void)
+{
+	dict_driver_unregister(&dict_driver_client);
+	dict_driver_unregister(&dict_driver_file);
+	dict_driver_unregister(&dict_driver_fs);
+	dict_driver_unregister(&dict_driver_memcached);
+	dict_driver_unregister(&dict_driver_memcached_ascii);
+	dict_driver_unregister(&dict_driver_redis);
+}
diff -r eeadb7b5045b -r 773e9ce608ed src/lib-dict/dict.c
--- a/src/lib-dict/dict.c	Sun Dec 08 20:48:03 2013 +0200
+++ b/src/lib-dict/dict.c	Sun Dec 08 21:13:22 2013 +0200
@@ -52,24 +52,6 @@
 		array_free(&dict_drivers);
 }
 
-void dict_drivers_register_builtin(void)
-{
-	dict_driver_register(&dict_driver_client);
-	dict_driver_register(&dict_driver_file);
-	dict_driver_register(&dict_driver_memcached);
-	dict_driver_register(&dict_driver_memcached_ascii);
-	dict_driver_register(&dict_driver_redis);
-}
-
-void dict_drivers_unregister_builtin(void)
-{
-	dict_driver_unregister(&dict_driver_client);
-	dict_driver_unregister(&dict_driver_file);
-	dict_driver_unregister(&dict_driver_memcached);
-	dict_driver_unregister(&dict_driver_memcached_ascii);
-	dict_driver_unregister(&dict_driver_redis);
-}
-
 int dict_init(const char *uri, enum dict_data_type value_type,
 	      const char *username, const char *base_dir, struct dict **dict_r,
 	      const char **error_r)


More information about the dovecot-cvs mailing list