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