Mercurial > dovecot > core-2.2
changeset 15729:8515223e4766
lib-fs: Added FS_OPEN_FLAG_SEEKABLE. Globally handle fs_read_stream() seekability and waits.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Mon, 04 Feb 2013 20:18:22 +0200 |
parents | 5462dbd46703 |
children | a1598c03c940 |
files | src/lib-fs/fs-api-private.h src/lib-fs/fs-api.c src/lib-fs/fs-api.h src/lib-fs/fs-metawrap.c |
diffstat | 4 files changed, 63 insertions(+), 3 deletions(-) [+] |
line wrap: on
line diff
--- 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;
--- 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)
--- 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 {
--- 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;