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