dovecot-2.2: lib-fs: Added FS_OPEN_FLAG_SEEKABLE. Globally handl...

dovecot at dovecot.org dovecot at dovecot.org
Mon Feb 4 20:18:39 EET 2013


details:   http://hg.dovecot.org/dovecot-2.2/rev/8515223e4766
changeset: 15729:8515223e4766
user:      Timo Sirainen <tss at iki.fi>
date:      Mon Feb 04 20:18:22 2013 +0200
description:
lib-fs: Added FS_OPEN_FLAG_SEEKABLE. Globally handle fs_read_stream() seekability and waits.

diffstat:

 src/lib-fs/fs-api-private.h |   2 +
 src/lib-fs/fs-api.c         |  55 +++++++++++++++++++++++++++++++++++++++++++-
 src/lib-fs/fs-api.h         |   4 ++-
 src/lib-fs/fs-metawrap.c    |   5 ++++
 4 files changed, 63 insertions(+), 3 deletions(-)

diffs (148 lines):

diff -r 5462dbd46703 -r 8515223e4766 src/lib-fs/fs-api-private.h
--- a/src/lib-fs/fs-api-private.h	Mon Feb 04 20:17:14 2013 +0200
+++ b/src/lib-fs/fs-api-private.h	Mon Feb 04 20:18:22 2013 +0200
@@ -55,6 +55,7 @@
 struct fs {
 	const char *name;
 	struct fs_vfuncs v;
+	char *temp_path_prefix;
 
 	struct fs_settings set;
 	string_t *last_error;
@@ -66,6 +67,7 @@
 	struct fs *fs;
 	struct ostream *output;
 	char *path;
+	enum fs_open_flags flags;
 
 	struct istream *pending_read_input;
 	bool write_pending;
diff -r 5462dbd46703 -r 8515223e4766 src/lib-fs/fs-api.c
--- a/src/lib-fs/fs-api.c	Mon Feb 04 20:17:14 2013 +0200
+++ b/src/lib-fs/fs-api.c	Mon Feb 04 20:18:22 2013 +0200
@@ -5,6 +5,7 @@
 #include "module-dir.h"
 #include "str.h"
 #include "istream.h"
+#include "istream-seekable.h"
 #include "ostream.h"
 #include "fs-api-private.h"
 
@@ -99,6 +100,7 @@
 	    struct fs **fs_r, const char **error_r)
 {
 	const struct fs *fs_class;
+	const char *temp_file_prefix;
 
 	fs_class = fs_class_find(driver);
 	if (fs_class == NULL) {
@@ -111,7 +113,14 @@
 		*error_r = t_strdup_printf("Unknown fs driver: %s", driver);
 		return -1;
 	}
-	return fs_alloc(fs_class, args, set, fs_r, error_r);
+	if (fs_alloc(fs_class, args, set, fs_r, error_r) < 0)
+		return -1;
+
+	temp_file_prefix = set->temp_file_prefix != NULL ?
+		set->temp_file_prefix : ".temp.dovecot";
+	(*fs_r)->temp_path_prefix = i_strconcat(set->temp_dir, "/",
+						temp_file_prefix, NULL);
+	return 0;
 }
 
 void fs_deinit(struct fs **_fs)
@@ -126,6 +135,7 @@
 			fs->name, fs->files_open_count);
 	}
 
+	i_free(fs->temp_path_prefix);
 	fs->v.deinit(fs);
 	str_free(&last_error);
 }
@@ -140,6 +150,7 @@
 		file = fs->v.file_init(fs, path, mode_flags & FS_OPEN_MODE_MASK,
 				       mode_flags & ~FS_OPEN_MODE_MASK);
 	} T_END;
+	file->flags = mode_flags & ~FS_OPEN_MODE_MASK;
 	fs->files_open_count++;
 	return file;
 }
@@ -262,7 +273,47 @@
 
 struct istream *fs_read_stream(struct fs_file *file, size_t max_buffer_size)
 {
-	return file->fs->v.read_stream(file, max_buffer_size);
+	struct istream *input, *inputs[2];
+	const unsigned char *data;
+	size_t size;
+	ssize_t ret;
+	bool want_seekable = FALSE;
+
+	input = file->fs->v.read_stream(file, max_buffer_size);
+	if (input->stream_errno != 0) {
+		/* read failed already */
+		return input;
+	}
+
+	if ((file->flags & FS_OPEN_FLAG_SEEKABLE) != 0)
+		want_seekable = TRUE;
+	else if ((file->flags & FS_OPEN_FLAG_ASYNC) == 0 && !input->blocking)
+		want_seekable = TRUE;
+
+	if (want_seekable && !input->seekable) {
+		/* need to make the stream seekable */
+		inputs[0] = input;
+		inputs[1] = NULL;
+		input = i_stream_create_seekable_path(inputs, max_buffer_size,
+						file->fs->temp_path_prefix);
+		i_stream_set_name(input, i_stream_get_name(inputs[0]));
+		i_stream_unref(&inputs[0]);
+	}
+	if ((file->flags & FS_OPEN_FLAG_ASYNC) == 0 && !input->blocking) {
+		/* read the whole input stream before returning */
+		while ((ret = i_stream_read_data(input, &data, &size, 0)) >= 0) {
+			i_stream_skip(input, size);
+			if (ret == 0) {
+				if (fs_wait_async(file->fs) < 0) {
+					input->stream_errno = errno;
+					input->eof = TRUE;
+					break;
+				}
+			}
+		}
+		i_stream_seek(input, 0);
+	}
+	return input;
 }
 
 int fs_write_via_stream(struct fs_file *file, const void *data, size_t size)
diff -r 5462dbd46703 -r 8515223e4766 src/lib-fs/fs-api.h
--- a/src/lib-fs/fs-api.h	Mon Feb 04 20:17:14 2013 +0200
+++ b/src/lib-fs/fs-api.h	Mon Feb 04 20:18:22 2013 +0200
@@ -49,7 +49,9 @@
 
 	   Asynchronous reads: fs_read() will fail with EAGAIN if it's not
 	   finished and fs_read_stream() returns a nonblocking stream. */
-	FS_OPEN_FLAG_ASYNC		= 0x20
+	FS_OPEN_FLAG_ASYNC		= 0x20,
+	/* fs_read_stream() must return a seekable input stream */
+	FS_OPEN_FLAG_SEEKABLE		= 0x40
 };
 
 enum fs_iter_flags {
diff -r 5462dbd46703 -r 8515223e4766 src/lib-fs/fs-metawrap.c
--- a/src/lib-fs/fs-metawrap.c	Mon Feb 04 20:17:14 2013 +0200
+++ b/src/lib-fs/fs-metawrap.c	Mon Feb 04 20:18:22 2013 +0200
@@ -109,6 +109,11 @@
 	file->fs = fs;
 	file->open_mode = mode;
 
+	/* avoid unnecessarily creating two seekable streams */
+	flags &= ~FS_OPEN_FLAG_SEEKABLE;
+	if (mode == FS_OPEN_MODE_READONLY)
+		flags |= FS_OPEN_FLAG_ASYNC;
+
 	file->super = fs_file_init(fs->super, path, mode | flags);
 	i_array_init(&file->file.metadata, 8);
 	return &file->file;


More information about the dovecot-cvs mailing list