dovecot-2.2: fs-metawrap: Delay writing the metadata headers unt...
dovecot at dovecot.org
dovecot at dovecot.org
Mon Feb 4 22:03:24 EET 2013
details: http://hg.dovecot.org/dovecot-2.2/rev/a1598c03c940
changeset: 15730:a1598c03c940
user: Timo Sirainen <tss at iki.fi>
date: Mon Feb 04 22:02:42 2013 +0200
description:
fs-metawrap: Delay writing the metadata headers until first data is written.
Also some other read/write fixes.
diffstat:
src/lib-fs/Makefile.am | 2 +
src/lib-fs/fs-metawrap.c | 93 +++++++++++++++++++++++++++---------------
src/lib-fs/ostream-metawrap.c | 58 ++++++++++++++++++++++++++
src/lib-fs/ostream-metawrap.h | 8 +++
4 files changed, 127 insertions(+), 34 deletions(-)
diffs (241 lines):
diff -r 8515223e4766 -r a1598c03c940 src/lib-fs/Makefile.am
--- a/src/lib-fs/Makefile.am Mon Feb 04 20:18:22 2013 +0200
+++ b/src/lib-fs/Makefile.am Mon Feb 04 22:02:42 2013 +0200
@@ -14,6 +14,7 @@
fs-sis-common.c \
fs-sis-queue.c \
istream-metawrap.c \
+ ostream-metawrap.c \
ostream-cmp.c
headers = \
@@ -21,6 +22,7 @@
fs-api-private.h \
fs-sis-common.h \
istream-metawrap.h \
+ ostream-metawrap.h \
ostream-cmp.h
fs_test_SOURCES = fs-test.c
diff -r 8515223e4766 -r a1598c03c940 src/lib-fs/fs-metawrap.c
--- a/src/lib-fs/fs-metawrap.c Mon Feb 04 20:18:22 2013 +0200
+++ b/src/lib-fs/fs-metawrap.c Mon Feb 04 22:02:42 2013 +0200
@@ -8,8 +8,11 @@
#include "istream-private.h"
#include "istream-metawrap.h"
#include "ostream.h"
+#include "ostream-metawrap.h"
#include "fs-api-private.h"
+#define MAX_METADATA_LINE_LEN 8192
+
struct metawrap_fs {
struct fs fs;
struct fs *super;
@@ -21,6 +24,8 @@
struct metawrap_fs *fs;
struct fs_file *super;
enum fs_open_mode open_mode;
+ struct istream *input;
+ struct ostream *super_output;
};
static void fs_metawrap_copy_error(struct metawrap_fs *fs)
@@ -226,15 +231,21 @@
fs_metawrap_read_stream(struct fs_file *_file, size_t max_buffer_size)
{
struct metawrap_fs_file *file = (struct metawrap_fs_file *)_file;
- struct istream *input, *input2;
+ struct istream *input;
if (!file->fs->wrap_metadata)
return fs_read_stream(file->super, max_buffer_size);
- input = fs_read_stream(file->super, max_buffer_size);
- input2 = i_stream_create_metawrap(input, fs_metawrap_callback, file);
+ if (file->input != NULL) {
+ i_stream_seek(file->input, 0);
+ return file->input;
+ }
+
+ input = fs_read_stream(file->super,
+ I_MAX(max_buffer_size, MAX_METADATA_LINE_LEN));
+ file->input = i_stream_create_metawrap(input, fs_metawrap_callback, file);
i_stream_unref(&input);
- return input2;
+ return file->input;
}
static int fs_metawrap_write(struct fs_file *_file, const void *data, size_t size)
@@ -251,36 +262,42 @@
return fs_write_via_stream(_file, data, size);
}
+static void fs_metawrap_write_metadata(void *context)
+{
+ struct metawrap_fs_file *file = context;
+ const struct fs_metadata *metadata;
+ string_t *str = t_str_new(256);
+ ssize_t ret;
+
+ /* FIXME: if fs_set_metadata() is called later the changes are
+ ignored. we'd need to write via temporary file then. */
+ array_foreach(&file->file.metadata, metadata) {
+ str_append_tabescaped(str, metadata->key);
+ str_append_c(str, ':');
+ str_append_tabescaped(str, metadata->value);
+ str_append_c(str, '\n');
+ }
+ str_append_c(str, '\n');
+ ret = o_stream_send(file->file.output, str_data(str), str_len(str));
+ if (ret < 0)
+ o_stream_close(file->file.output);
+ else
+ i_assert((size_t)ret == str_len(str));
+}
+
static void fs_metawrap_write_stream(struct fs_file *_file)
{
struct metawrap_fs_file *file = (struct metawrap_fs_file *)_file;
i_assert(_file->output == NULL);
- _file->output = fs_write_stream(file->super);
- if (file->fs->wrap_metadata) T_BEGIN {
- const struct fs_metadata *metadata;
- string_t *str = t_str_new(256);
- ssize_t ret;
-
- /* FIXME: if fs_set_metadata() is called later the changes are
- ignored. we'd need to write via temporary file then. */
- array_foreach(&_file->metadata, metadata) {
- str_append_tabescaped(str, metadata->key);
- str_append_c(str, ':');
- str_append_tabescaped(str, metadata->value);
- str_append_c(str, '\n');
- }
- str_append_c(str, '\n');
- ret = o_stream_send(_file->output, str_data(str), str_len(str));
- if (ret < 0) {
- int err = _file->output->stream_errno;
- fs_write_stream_abort(file->super, &_file->output);
- _file->output = o_stream_create_error(err);
- } else {
- i_assert((size_t)ret == str_len(str));
- }
- } T_END;
+ file->super_output = fs_write_stream(file->super);
+ if (!file->fs->wrap_metadata)
+ _file->output = file->super_output;
+ else {
+ _file->output = o_stream_create_metawrap(file->super_output,
+ fs_metawrap_write_metadata, file);
+ }
}
static int fs_metawrap_write_stream_finish(struct fs_file *_file, bool success)
@@ -288,16 +305,24 @@
struct metawrap_fs_file *file = (struct metawrap_fs_file *)_file;
int ret;
+ if (_file->output->closed)
+ success = FALSE;
+
if (!success) {
- fs_write_stream_abort(file->super, &_file->output);
- fs_metawrap_file_copy_error(file);
- return -1;
+ fs_write_stream_abort(file->super, &file->super_output);
+ ret = -1;
+ } else {
+ ret = fs_write_stream_finish(file->super, &file->super_output);
}
- if ((ret = fs_write_stream_finish(file->super, &_file->output)) < 0) {
+ if (ret != 0) {
+ if (_file->output == file->super_output)
+ _file->output = NULL;
+ else
+ o_stream_unref(&_file->output);
+ }
+ if (ret < 0)
fs_metawrap_file_copy_error(file);
- return -1;
- }
return ret;
}
diff -r 8515223e4766 -r a1598c03c940 src/lib-fs/ostream-metawrap.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-fs/ostream-metawrap.c Mon Feb 04 22:02:42 2013 +0200
@@ -0,0 +1,58 @@
+/* Copyright (c) 2013 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "ostream-private.h"
+#include "ostream-metawrap.h"
+
+struct metawrap_ostream {
+ struct ostream_private ostream;
+ void (*write_callback)(void *);
+ void *context;
+};
+
+static void o_stream_metawrap_call_callback(struct metawrap_ostream *mstream)
+{
+ void (*write_callback)(void *) = mstream->write_callback;
+
+ if (write_callback != NULL) {
+ mstream->write_callback = NULL;
+ write_callback(mstream->context);
+ }
+}
+
+static ssize_t
+o_stream_metawrap_sendv(struct ostream_private *stream,
+ const struct const_iovec *iov, unsigned int iov_count)
+{
+ struct metawrap_ostream *mstream = (struct metawrap_ostream *)stream;
+
+ o_stream_metawrap_call_callback(mstream);
+ return o_stream_sendv(stream->parent, iov, iov_count);
+}
+
+static off_t
+o_stream_metawrap_send_istream(struct ostream_private *_outstream,
+ struct istream *instream)
+{
+ struct metawrap_ostream *outstream =
+ (struct metawrap_ostream *)_outstream;
+
+ o_stream_metawrap_call_callback(outstream);
+ return o_stream_send_istream(_outstream->parent, instream);
+}
+
+struct ostream *
+o_stream_create_metawrap(struct ostream *output,
+ void (*write_callback)(void *), void *context)
+{
+ struct metawrap_ostream *mstream;
+
+ mstream = i_new(struct metawrap_ostream, 1);
+ mstream->ostream.sendv = o_stream_metawrap_sendv;
+ mstream->ostream.send_istream = o_stream_metawrap_send_istream;
+ mstream->write_callback = write_callback;
+ mstream->context = context;
+
+ return o_stream_create(&mstream->ostream, output,
+ o_stream_get_fd(output));
+}
diff -r 8515223e4766 -r a1598c03c940 src/lib-fs/ostream-metawrap.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-fs/ostream-metawrap.h Mon Feb 04 22:02:42 2013 +0200
@@ -0,0 +1,8 @@
+#ifndef OSTREAM_METAWRAP_H
+#define OSTREAM_METAWRAP_H
+
+struct ostream *
+o_stream_create_metawrap(struct ostream *output,
+ void (*write_callback)(void *), void *context);
+
+#endif
More information about the dovecot-cvs
mailing list