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