dovecot-2.2: lib-fs: Added "metawrap" wrapper to implement metad...
dovecot at dovecot.org
dovecot at dovecot.org
Mon Jan 21 14:43:14 EET 2013
details: http://hg.dovecot.org/dovecot-2.2/rev/5818d8f488c1
changeset: 15655:5818d8f488c1
user: Timo Sirainen <tss at iki.fi>
date: Mon Jan 21 14:43:09 2013 +0200
description:
lib-fs: Added "metawrap" wrapper to implement metadata as headers in the file content.
diffstat:
src/lib-fs/Makefile.am | 3 +
src/lib-fs/fs-api-private.h | 15 +
src/lib-fs/fs-api.c | 96 ++++++++-
src/lib-fs/fs-metawrap.c | 429 ++++++++++++++++++++++++++++++++++++++++++
src/lib-fs/istream-metawrap.c | 79 +++++++
src/lib-fs/istream-metawrap.h | 14 +
6 files changed, 625 insertions(+), 11 deletions(-)
diffs (truncated from 765 to 300 lines):
diff -r ee177df07178 -r 5818d8f488c1 src/lib-fs/Makefile.am
--- a/src/lib-fs/Makefile.am Mon Jan 21 14:42:10 2013 +0200
+++ b/src/lib-fs/Makefile.am Mon Jan 21 14:43:09 2013 +0200
@@ -8,16 +8,19 @@
libfs_la_SOURCES = \
fs-api.c \
+ fs-metawrap.c \
fs-posix.c \
fs-sis.c \
fs-sis-common.c \
fs-sis-queue.c \
+ istream-metawrap.c \
ostream-cmp.c
headers = \
fs-api.h \
fs-api-private.h \
fs-sis-common.h \
+ istream-metawrap.h \
ostream-cmp.h
fs_test_SOURCES = fs-test.c
diff -r ee177df07178 -r 5818d8f488c1 src/lib-fs/fs-api-private.h
--- a/src/lib-fs/fs-api-private.h Mon Jan 21 14:42:10 2013 +0200
+++ b/src/lib-fs/fs-api-private.h Mon Jan 21 14:43:09 2013 +0200
@@ -69,6 +69,13 @@
struct istream *pending_read_input;
bool write_pending;
+
+ pool_t metadata_pool;
+ ARRAY_TYPE(fs_metadata) metadata;
+
+ struct fs_file *copy_src;
+ struct istream *copy_input;
+ struct ostream *copy_output;
};
struct fs_lock {
@@ -81,6 +88,7 @@
};
extern const struct fs fs_class_posix;
+extern const struct fs fs_class_metawrap;
extern const struct fs fs_class_sis;
extern const struct fs fs_class_sis_queue;
@@ -89,4 +97,11 @@
void fs_set_error_async(struct fs *fs);
+ssize_t fs_read_via_stream(struct fs_file *file, void *buf, size_t size);
+int fs_write_via_stream(struct fs_file *file, const void *data, size_t size);
+void fs_metadata_init(struct fs_file *file);
+void fs_default_set_metadata(struct fs_file *file,
+ const char *key, const char *value);
+int fs_default_copy(struct fs_file *src, struct fs_file *dest);
+
#endif
diff -r ee177df07178 -r 5818d8f488c1 src/lib-fs/fs-api.c
--- a/src/lib-fs/fs-api.c Mon Jan 21 14:42:10 2013 +0200
+++ b/src/lib-fs/fs-api.c Mon Jan 21 14:43:09 2013 +0200
@@ -46,6 +46,7 @@
{
i_array_init(&fs_classes, 8);
fs_class_register(&fs_class_posix);
+ fs_class_register(&fs_class_metawrap);
fs_class_register(&fs_class_sis);
fs_class_register(&fs_class_sis_queue);
}
@@ -146,6 +147,7 @@
void fs_file_deinit(struct fs_file **_file)
{
struct fs_file *file = *_file;
+ pool_t metadata_pool = file->metadata_pool;
i_assert(file->fs->files_open_count > 0);
@@ -153,6 +155,9 @@
file->fs->files_open_count--;
file->fs->v.file_deinit(file);
+
+ if (metadata_pool != NULL)
+ pool_unref(&metadata_pool);
}
enum fs_properties fs_get_properties(struct fs *fs)
@@ -160,6 +165,25 @@
return fs->v.get_properties(fs);
}
+void fs_metadata_init(struct fs_file *file)
+{
+ if (file->metadata_pool == NULL) {
+ file->metadata_pool = pool_alloconly_create("fs metadata", 1024);
+ p_array_init(&file->metadata, file->metadata_pool, 8);
+ }
+}
+
+void fs_default_set_metadata(struct fs_file *file,
+ const char *key, const char *value)
+{
+ struct fs_metadata *metadata;
+
+ fs_metadata_init(file);
+ metadata = array_append_space(&file->metadata);
+ metadata->key = p_strdup(file->metadata_pool, key);
+ metadata->value = p_strdup(file->metadata_pool, value);
+}
+
void fs_set_metadata(struct fs_file *file, const char *key, const char *value)
{
if (file->fs->v.set_metadata != NULL)
@@ -199,17 +223,14 @@
return file->fs->v.prefetch(file, length);
}
-ssize_t fs_read(struct fs_file *file, void *buf, size_t size)
+ssize_t fs_read_via_stream(struct fs_file *file, void *buf, size_t size)
{
const unsigned char *data;
size_t data_size;
ssize_t ret;
- if (file->fs->v.read != NULL)
- return file->fs->v.read(file, buf, size);
+ i_assert(size > 0);
- /* backend didn't bother to implement read(), but we can do it with
- streams. */
if (file->pending_read_input == NULL)
file->pending_read_input = fs_read_stream(file, size+1);
ret = i_stream_read_data(file->pending_read_input,
@@ -229,22 +250,27 @@
return ret;
}
+ssize_t fs_read(struct fs_file *file, void *buf, size_t size)
+{
+ if (file->fs->v.read != NULL)
+ return file->fs->v.read(file, buf, size);
+
+ /* backend didn't bother to implement read(), but we can do it with
+ streams. */
+ return fs_read_via_stream(file, buf, size);
+}
+
struct istream *fs_read_stream(struct fs_file *file, size_t max_buffer_size)
{
return file->fs->v.read_stream(file, max_buffer_size);
}
-int fs_write(struct fs_file *file, const void *data, size_t size)
+int fs_write_via_stream(struct fs_file *file, const void *data, size_t size)
{
struct ostream *output;
ssize_t ret;
int err;
- if (file->fs->v.write != NULL)
- return file->fs->v.write(file, data, size);
-
- /* backend didn't bother to implement write(), but we can do it with
- streams. */
if (!file->write_pending) {
output = fs_write_stream(file);
if ((ret = o_stream_send(output, data, size)) < 0) {
@@ -269,6 +295,16 @@
return ret < 0 ? -1 : 0;
}
+int fs_write(struct fs_file *file, const void *data, size_t size)
+{
+ if (file->fs->v.write != NULL)
+ return file->fs->v.write(file, data, size);
+
+ /* backend didn't bother to implement write(), but we can do it with
+ streams. */
+ return fs_write_via_stream(file, data, size);
+}
+
struct ostream *fs_write_stream(struct fs_file *file)
{
file->fs->v.write_stream(file);
@@ -338,6 +374,44 @@
return file->fs->v.stat(file, st_r);
}
+int fs_default_copy(struct fs_file *src, struct fs_file *dest)
+{
+ if (dest->copy_src != NULL) {
+ i_assert(src == NULL || src == dest->copy_src);
+ if (dest->copy_output == NULL) {
+ i_assert(dest->copy_input == NULL);
+ if (fs_write_stream_finish_async(dest) < 0)
+ return -1;
+ dest->copy_src = NULL;
+ return 0;
+ }
+ } else {
+ dest->copy_src = src;
+ dest->copy_input = fs_read_stream(src, IO_BLOCK_SIZE);
+ dest->copy_output = fs_write_stream(dest);
+ }
+ while (o_stream_send_istream(dest->copy_output, dest->copy_input) > 0) ;
+ if (dest->copy_input->stream_errno != 0) {
+ fs_set_error(dest->fs, "read(%s) failed: %m",
+ i_stream_get_name(dest->copy_input));
+ return -1;
+ }
+ if (dest->copy_output->stream_errno != 0) {
+ fs_set_error(dest->fs, "write(%s) failed: %m",
+ o_stream_get_name(dest->copy_output));
+ return -1;
+ }
+ if (!dest->copy_input->eof) {
+ fs_set_error_async(dest->fs);
+ return -1;
+ }
+ i_stream_unref(&dest->copy_input);
+ if (fs_write_stream_finish(dest, &dest->copy_output) < 0)
+ return -1;
+ dest->copy_src = NULL;
+ return 0;
+}
+
int fs_copy(struct fs_file *src, struct fs_file *dest)
{
i_assert(src->fs == dest->fs);
diff -r ee177df07178 -r 5818d8f488c1 src/lib-fs/fs-metawrap.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-fs/fs-metawrap.c Mon Jan 21 14:43:09 2013 +0200
@@ -0,0 +1,429 @@
+/* Copyright (c) 2013 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "array.h"
+#include "str.h"
+#include "strescape.h"
+#include "istream.h"
+#include "istream-private.h"
+#include "istream-metawrap.h"
+#include "ostream.h"
+#include "fs-api-private.h"
+
+struct metawrap_fs {
+ struct fs fs;
+ struct fs *super;
+ bool wrap_metadata;
+};
+
+struct metawrap_fs_file {
+ struct fs_file file;
+ struct metawrap_fs *fs;
+ struct fs_file *super;
+ enum fs_open_mode open_mode;
+};
+
+static void fs_metawrap_copy_error(struct metawrap_fs *fs)
+{
+ fs_set_error(&fs->fs, "%s", fs_last_error(fs->super));
+}
+
+static void fs_metawrap_file_copy_error(struct metawrap_fs_file *file)
+{
+ struct metawrap_fs *fs = (struct metawrap_fs *)file->file.fs;
+
+ fs_metawrap_copy_error(fs);
+}
+
+static struct fs *fs_metawrap_alloc(void)
+{
+ struct metawrap_fs *fs;
+
+ fs = i_new(struct metawrap_fs, 1);
+ fs->fs = fs_class_metawrap;
+ return &fs->fs;
+}
+
+static int
+fs_metawrap_init(struct fs *_fs, const char *args, const
+ struct fs_settings *set)
+{
+ struct metawrap_fs *fs = (struct metawrap_fs *)_fs;
+ const char *parent_name, *parent_args, *error;
+
+ if (*args == '\0') {
+ fs_set_error(_fs, "Parent filesystem not given as parameter");
+ return -1;
+ }
+
+ parent_args = strchr(args, ':');
+ if (parent_args == NULL) {
+ parent_name = args;
+ parent_args = "";
+ } else {
+ parent_name = t_strdup_until(args, parent_args);
+ parent_args++;
More information about the dovecot-cvs
mailing list