dovecot-2.2: lib-fs: Added "dict" backend, which is a wrapper to...
dovecot at dovecot.org
dovecot at dovecot.org
Mon Aug 31 20:55:20 UTC 2015
details: http://hg.dovecot.org/dovecot-2.2/rev/6adcfddd354d
changeset: 19053:6adcfddd354d
user: Timo Sirainen <tss at iki.fi>
date: Mon Aug 31 23:54:24 2015 +0300
description:
lib-fs: Added "dict" backend, which is a wrapper to using lib-dict.
diffstat:
src/lib-fs/Makefile.am | 2 +
src/lib-fs/fs-api-private.h | 1 +
src/lib-fs/fs-api.c | 1 +
src/lib-fs/fs-dict.c | 312 ++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 316 insertions(+), 0 deletions(-)
diffs (truncated from 355 to 300 lines):
diff -r 55cab04ef2af -r 6adcfddd354d src/lib-fs/Makefile.am
--- a/src/lib-fs/Makefile.am Mon Aug 31 23:46:05 2015 +0300
+++ b/src/lib-fs/Makefile.am Mon Aug 31 23:54:24 2015 +0300
@@ -2,11 +2,13 @@
AM_CPPFLAGS = \
-I$(top_srcdir)/src/lib \
+ -I$(top_srcdir)/src/lib-dict \
-I$(top_srcdir)/src/lib-ssl-iostream \
-DMODULE_DIR=\""$(moduledir)"\"
libfs_la_SOURCES = \
fs-api.c \
+ fs-dict.c \
fs-metawrap.c \
fs-randomfail.c \
fs-posix.c \
diff -r 55cab04ef2af -r 6adcfddd354d src/lib-fs/fs-api-private.h
--- a/src/lib-fs/fs-api-private.h Mon Aug 31 23:46:05 2015 +0300
+++ b/src/lib-fs/fs-api-private.h Mon Aug 31 23:54:24 2015 +0300
@@ -151,6 +151,7 @@
void *async_context;
};
+extern const struct fs fs_class_dict;
extern const struct fs fs_class_posix;
extern const struct fs fs_class_randomfail;
extern const struct fs fs_class_metawrap;
diff -r 55cab04ef2af -r 6adcfddd354d src/lib-fs/fs-api.c
--- a/src/lib-fs/fs-api.c Mon Aug 31 23:46:05 2015 +0300
+++ b/src/lib-fs/fs-api.c Mon Aug 31 23:54:24 2015 +0300
@@ -63,6 +63,7 @@
static void fs_classes_init(void)
{
i_array_init(&fs_classes, 8);
+ fs_class_register(&fs_class_dict);
fs_class_register(&fs_class_posix);
fs_class_register(&fs_class_randomfail);
fs_class_register(&fs_class_metawrap);
diff -r 55cab04ef2af -r 6adcfddd354d src/lib-fs/fs-dict.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-fs/fs-dict.c Mon Aug 31 23:54:24 2015 +0300
@@ -0,0 +1,312 @@
+/* Copyright (c) 2015 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "buffer.h"
+#include "str.h"
+#include "guid.h"
+#include "base64.h"
+#include "istream.h"
+#include "ostream.h"
+#include "dict.h"
+#include "fs-api-private.h"
+
+enum fs_dict_value_encoding {
+ FS_DICT_VALUE_ENCODING_RAW,
+ FS_DICT_VALUE_ENCODING_BASE64
+};
+
+struct dict_fs {
+ struct fs fs;
+ struct dict *dict;
+ char *path_prefix;
+ enum fs_dict_value_encoding encoding;
+};
+
+struct dict_fs_file {
+ struct fs_file file;
+ pool_t pool;
+ const char *key, *value;
+ buffer_t *write_buffer;
+};
+
+struct dict_fs_iter {
+ struct fs_iter iter;
+ struct dict_iterate_context *dict_iter;
+};
+
+static struct fs *fs_dict_alloc(void)
+{
+ struct dict_fs *fs;
+
+ fs = i_new(struct dict_fs, 1);
+ fs->fs = fs_class_dict;
+ return &fs->fs;
+}
+
+static int
+fs_dict_init(struct fs *_fs, const char *args, const struct fs_settings *set)
+{
+ struct dict_fs *fs = (struct dict_fs *)_fs;
+ struct dict_settings dict_set;
+ const char *p, *encoding_str, *error;
+
+ p = strchr(args, ':');
+ if (p == NULL) {
+ fs_set_error(_fs, "':' missing in args");
+ return -1;
+ }
+ encoding_str = t_strdup_until(args, p++);
+ if (strcmp(encoding_str, "raw") == 0)
+ fs->encoding = FS_DICT_VALUE_ENCODING_RAW;
+ else if (strcmp(encoding_str, "base64") == 0)
+ fs->encoding = FS_DICT_VALUE_ENCODING_BASE64;
+ else {
+ fs_set_error(_fs, "Unknown value encoding '%s'", encoding_str);
+ return -1;
+ }
+
+ memset(&dict_set, 0, sizeof(dict_set));
+ dict_set.username = set->username;
+ dict_set.base_dir = set->base_dir;
+
+ if (dict_init_full(p, &dict_set, &fs->dict, &error) < 0) {
+ fs_set_error(_fs, "dict_init(%s) failed: %s", args, error);
+ return -1;
+ }
+ return 0;
+}
+
+static void fs_dict_deinit(struct fs *_fs)
+{
+ struct dict_fs *fs = (struct dict_fs *)_fs;
+
+ dict_deinit(&fs->dict);
+ i_free(fs);
+}
+
+static enum fs_properties fs_dict_get_properties(struct fs *fs ATTR_UNUSED)
+{
+ return FS_PROPERTY_ITER | FS_PROPERTY_RELIABLEITER;
+}
+
+static struct fs_file *
+fs_dict_file_init(struct fs *_fs, const char *path,
+ enum fs_open_mode mode, enum fs_open_flags flags ATTR_UNUSED)
+{
+ struct dict_fs *fs = (struct dict_fs *)_fs;
+ struct dict_fs_file *file;
+ guid_128_t guid;
+ pool_t pool;
+
+ i_assert(mode != FS_OPEN_MODE_APPEND); /* not supported */
+ i_assert(mode != FS_OPEN_MODE_CREATE); /* not supported */
+
+ pool = pool_alloconly_create("fs dict file", 128);
+ file = p_new(pool, struct dict_fs_file, 1);
+ file->pool = pool;
+ file->file.fs = _fs;
+ if (mode != FS_OPEN_MODE_CREATE_UNIQUE_128)
+ file->file.path = p_strdup(pool, path);
+ else {
+ guid_128_generate(guid);
+ file->file.path = p_strdup_printf(pool, "%s/%s", path,
+ guid_128_to_string(guid));
+ }
+ file->key = fs->path_prefix == NULL ?
+ p_strdup(pool, file->file.path) :
+ p_strconcat(pool, fs->path_prefix, file->file.path, NULL);
+ return &file->file;
+}
+
+static void fs_dict_file_deinit(struct fs_file *_file)
+{
+ struct dict_fs_file *file = (struct dict_fs_file *)_file;
+
+ i_assert(_file->output == NULL);
+
+ pool_unref(&file->pool);
+}
+
+static bool fs_dict_prefetch(struct fs_file *_file ATTR_UNUSED,
+ uoff_t length ATTR_UNUSED)
+{
+ /* once async dict_lookup() is implemented, we want to start it here */
+ return TRUE;
+}
+
+static int fs_dict_lookup(struct dict_fs_file *file)
+{
+ struct dict_fs *fs = (struct dict_fs *)file->file.fs;
+ int ret;
+
+ if (file->value != NULL)
+ return 0;
+
+ ret = dict_lookup(fs->dict, file->pool, file->key, &file->value);
+ if (ret > 0)
+ return 0;
+ else if (ret < 0) {
+ errno = EIO;
+ fs_set_error(&fs->fs, "Dict lookup failed");
+ return -1;
+ } else {
+ errno = ENOENT;
+ fs_set_error(&fs->fs, "Dict key doesn't exist");
+ return -1;
+ }
+}
+
+static struct istream *
+fs_dict_read_stream(struct fs_file *_file, size_t max_buffer_size ATTR_UNUSED)
+{
+ struct dict_fs_file *file = (struct dict_fs_file *)_file;
+ struct istream *input;
+
+ if (fs_dict_lookup(file) < 0)
+ input = i_stream_create_error_str(errno, "%s", fs_last_error(_file->fs));
+ else
+ input = i_stream_create_from_data(file->value, strlen(file->value));
+ i_stream_set_name(input, file->key);
+ return input;
+}
+
+static void fs_dict_write_stream(struct fs_file *_file)
+{
+ struct dict_fs_file *file = (struct dict_fs_file *)_file;
+
+ i_assert(_file->output == NULL);
+
+ file->write_buffer = buffer_create_dynamic(file->pool, 128);
+ _file->output = o_stream_create_buffer(file->write_buffer);
+ o_stream_set_name(_file->output, file->key);
+}
+
+static int fs_dict_write_stream_finish(struct fs_file *_file, bool success)
+{
+ struct dict_fs_file *file = (struct dict_fs_file *)_file;
+ struct dict_fs *fs = (struct dict_fs *)_file->fs;
+ struct dict_transaction_context *trans;
+
+ o_stream_destroy(&_file->output);
+ if (!success)
+ return -1;
+
+ trans = dict_transaction_begin(fs->dict);
+ switch (fs->encoding) {
+ case FS_DICT_VALUE_ENCODING_RAW:
+ dict_set(trans, file->key, str_c(file->write_buffer));
+ break;
+ case FS_DICT_VALUE_ENCODING_BASE64: {
+ const unsigned int base64_size =
+ MAX_BASE64_ENCODED_SIZE(file->write_buffer->used);
+ string_t *base64 = t_str_new(base64_size);
+ base64_encode(file->write_buffer->data,
+ file->write_buffer->used, base64);
+ dict_set(trans, file->key, str_c(base64));
+ }
+ }
+ if (dict_transaction_commit(&trans) < 0) {
+ errno = EIO;
+ fs_set_error(_file->fs, "Dict transaction commit failed");
+ return -1;
+ }
+ return 1;
+}
+
+static int fs_dict_stat(struct fs_file *_file, struct stat *st_r)
+{
+ struct dict_fs_file *file = (struct dict_fs_file *)_file;
+
+ memset(st_r, 0, sizeof(*st_r));
+
+ if (fs_dict_lookup(file) < 0)
+ return -1;
+ st_r->st_size = strlen(file->value);
+ return 0;
+}
+
+static int fs_dict_delete(struct fs_file *_file)
+{
+ struct dict_fs_file *file = (struct dict_fs_file *)_file;
+ struct dict_fs *fs = (struct dict_fs *)_file->fs;
+ struct dict_transaction_context *trans;
+
+ trans = dict_transaction_begin(fs->dict);
+ dict_unset(trans, file->key);
+ if (dict_transaction_commit(&trans) < 0) {
+ errno = EIO;
+ fs_set_error(_file->fs, "Dict transaction commit failed");
+ return -1;
+ }
+ return 0;
+}
+
+static struct fs_iter *
+fs_dict_iter_init(struct fs *_fs, const char *path, enum fs_iter_flags flags)
+{
+ struct dict_fs *fs = (struct dict_fs *)_fs;
+ struct dict_fs_iter *iter;
+
+ iter = i_new(struct dict_fs_iter, 1);
+ iter->iter.fs = _fs;
+ iter->iter.flags = flags;
+ if (fs->path_prefix != NULL)
+ path = t_strconcat(fs->path_prefix, path, NULL);
+
+ iter->dict_iter = dict_iterate_init(fs->dict, path, 0);
+ return &iter->iter;
More information about the dovecot-cvs
mailing list