dovecot-2.2: Added io_add_istream() and related functionality fo...
dovecot at dovecot.org
dovecot at dovecot.org
Thu Apr 3 16:52:23 UTC 2014
details: http://hg.dovecot.org/dovecot-2.2/rev/fd186eff7325
changeset: 17188:fd186eff7325
user: Timo Sirainen <tss at iki.fi>
date: Thu Apr 03 19:51:52 2014 +0300
description:
Added io_add_istream() and related functionality for combining the ioloop/istream.
The idea here is that it's possible to implement asynchronous istreams when
there isn't a file descriptor that can be used to reliably receive updates.
diffstat:
src/lib/ioloop-private.h | 3 ++
src/lib/ioloop.c | 63 ++++++++++++++++++++++++++++++++++++++--------
src/lib/ioloop.h | 7 +++++
src/lib/istream-private.h | 8 +++++
src/lib/istream.c | 44 ++++++++++++++++++++++++++++++++
src/lib/istream.h | 6 ++++
6 files changed, 120 insertions(+), 11 deletions(-)
diffs (252 lines):
diff -r d2a6f57e174f -r fd186eff7325 src/lib/ioloop-private.h
--- a/src/lib/ioloop-private.h Thu Apr 03 19:47:49 2014 +0300
+++ b/src/lib/ioloop-private.h Thu Apr 03 19:51:52 2014 +0300
@@ -52,6 +52,9 @@
int refcount;
int fd;
+
+ /* only for io_add_istream(), a bit kludgy to be here.. */
+ struct istream *istream;
};
struct timeout {
diff -r d2a6f57e174f -r fd186eff7325 src/lib/ioloop.c
--- a/src/lib/ioloop.c Thu Apr 03 19:47:49 2014 +0300
+++ b/src/lib/ioloop.c Thu Apr 03 19:51:52 2014 +0300
@@ -3,6 +3,7 @@
#include "lib.h"
#include "array.h"
#include "time-util.h"
+#include "istream-private.h"
#include "ioloop-private.h"
#include <unistd.h>
@@ -28,10 +29,10 @@
io_loop_handler_init(ioloop, initial_fd_count);
}
-#undef io_add
-struct io *io_add(int fd, enum io_condition condition,
- unsigned int source_linenum,
- io_callback_t *callback, void *context)
+static struct io_file *
+io_add_file(int fd, enum io_condition condition,
+ unsigned int source_linenum,
+ io_callback_t *callback, void *context)
{
struct io_file *io;
@@ -62,6 +63,31 @@
io->next = io->io.ioloop->io_files;
}
io->io.ioloop->io_files = io;
+ return io;
+}
+
+#undef io_add
+struct io *io_add(int fd, enum io_condition condition,
+ unsigned int source_linenum,
+ io_callback_t *callback, void *context)
+{
+ struct io_file *io;
+
+ io = io_add_file(fd, condition, source_linenum, callback, context);
+ return &io->io;
+}
+
+#undef io_add_istream
+struct io *io_add_istream(struct istream *input, unsigned int source_linenum,
+ io_callback_t *callback, void *context)
+{
+ struct io_file *io;
+
+ io = io_add_file(i_stream_get_fd(input), IO_READ, source_linenum,
+ callback, context);
+ io->istream = input;
+ i_stream_ref(io->istream);
+ i_stream_set_io(io->istream, &io->io);
return &io->io;
}
@@ -106,6 +132,12 @@
else {
struct io_file *io_file = (struct io_file *)io;
+ if (io_file->istream != NULL) {
+ i_stream_unset_io(io_file->istream, io);
+ i_stream_unref(&io_file->istream);
+ io_file->istream = NULL;
+ }
+
io_file_unlink(io_file);
io_loop_handle_remove(io_file, closed);
}
@@ -714,8 +746,8 @@
struct io *io_loop_move_io(struct io **_io)
{
- struct io *new_io, *old_io = *_io;
- struct io_file *old_io_file;
+ struct io *old_io = *_io;
+ struct io_file *old_io_file, *new_io_file;
i_assert((old_io->condition & IO_NOTIFY) == 0);
@@ -723,13 +755,22 @@
return old_io;
old_io_file = (struct io_file *)old_io;
- new_io = io_add(old_io_file->fd, old_io->condition,
- old_io->source_linenum,
- old_io->callback, old_io->context);
+ new_io_file = io_add_file(old_io_file->fd, old_io->condition,
+ old_io->source_linenum,
+ old_io->callback, old_io->context);
+ if (old_io_file->istream != NULL) {
+ /* reference before io_remove() */
+ new_io_file->istream = old_io_file->istream;
+ i_stream_ref(new_io_file->istream);
+ }
if (old_io->pending)
- io_set_pending(new_io);
+ io_set_pending(&new_io_file->io);
io_remove(_io);
- return new_io;
+ if (new_io_file->istream != NULL) {
+ /* update istream io after it was removed with io_remove() */
+ i_stream_set_io(new_io_file->istream, &new_io_file->io);
+ }
+ return &new_io_file->io;
}
struct timeout *io_loop_move_timeout(struct timeout **_timeout)
diff -r d2a6f57e174f -r fd186eff7325 src/lib/ioloop.h
--- a/src/lib/ioloop.h Thu Apr 03 19:47:49 2014 +0300
+++ b/src/lib/ioloop.h Thu Apr 03 19:51:52 2014 +0300
@@ -7,6 +7,7 @@
struct io;
struct timeout;
struct ioloop;
+struct istream;
enum io_condition {
IO_READ = 0x01,
@@ -60,6 +61,12 @@
io_add_notify(path + \
CALLBACK_TYPECHECK(callback, void (*)(typeof(context))), \
(io_callback_t *)callback, context, io_r)
+struct io *io_add_istream(struct istream *input, unsigned int source_linenum,
+ io_callback_t *callback, void *context) ATTR_NULL(3);
+#define io_add_istream(input, callback, context) \
+ io_add_istream(input, __LINE__ + \
+ CALLBACK_TYPECHECK(callback, void (*)(typeof(context))), \
+ (io_callback_t *)callback, context)
/* Remove I/O handler, and set io pointer to NULL. */
void io_remove(struct io **io);
diff -r d2a6f57e174f -r fd186eff7325 src/lib/istream-private.h
--- a/src/lib/istream-private.h Thu Apr 03 19:47:49 2014 +0300
+++ b/src/lib/istream-private.h Thu Apr 03 19:51:52 2014 +0300
@@ -6,6 +6,8 @@
#define I_STREAM_MIN_SIZE IO_BLOCK_SIZE
+struct io;
+
struct istream_private {
/* inheritance: */
struct iostream_private iostream;
@@ -17,6 +19,7 @@
void (*sync)(struct istream_private *stream);
int (*stat)(struct istream_private *stream, bool exact);
int (*get_size)(struct istream_private *stream, bool exact, uoff_t *size_r);
+ void (*switch_ioloop)(struct istream_private *stream);
/* data: */
struct istream istream;
@@ -24,6 +27,8 @@
int fd;
uoff_t abs_start_offset;
struct stat statbuf;
+ /* added by io_add_istream() -> i_stream_set_io() */
+ struct io *io;
const unsigned char *buffer;
unsigned char *w_buffer; /* may be NULL */
@@ -66,4 +71,7 @@
void i_stream_default_seek_nonseekable(struct istream_private *stream,
uoff_t v_offset, bool mark);
+void i_stream_set_io(struct istream *stream, struct io *io);
+void i_stream_unset_io(struct istream *stream, struct io *io);
+
#endif
diff -r d2a6f57e174f -r fd186eff7325 src/lib/istream.c
--- a/src/lib/istream.c Thu Apr 03 19:47:49 2014 +0300
+++ b/src/lib/istream.c Thu Apr 03 19:51:52 2014 +0300
@@ -608,6 +608,50 @@
return TRUE;
}
+void i_stream_set_input_pending(struct istream *stream, bool pending)
+{
+ if (!pending)
+ return;
+
+ while (stream->real_stream->parent != NULL) {
+ i_assert(stream->real_stream->io == NULL);
+ stream = stream->real_stream->parent;
+ }
+ if (stream->real_stream->io != NULL)
+ io_set_pending(stream->real_stream->io);
+}
+
+void i_stream_switch_ioloop(struct istream *stream)
+{
+ do {
+ if (stream->real_stream->switch_ioloop != NULL)
+ stream->real_stream->switch_ioloop(stream->real_stream);
+ stream = stream->real_stream->parent;
+ } while (stream != NULL);
+}
+
+void i_stream_set_io(struct istream *stream, struct io *io)
+{
+ while (stream->real_stream->parent != NULL) {
+ i_assert(stream->real_stream->io == NULL);
+ stream = stream->real_stream->parent;
+ }
+
+ i_assert(stream->real_stream->io == NULL);
+ stream->real_stream->io = io;
+}
+
+void i_stream_unset_io(struct istream *stream, struct io *io)
+{
+ while (stream->real_stream->parent != NULL) {
+ i_assert(stream->real_stream->io == NULL);
+ stream = stream->real_stream->parent;
+ }
+
+ i_assert(stream->real_stream->io == io);
+ stream->real_stream->io = NULL;
+}
+
static void
i_stream_default_set_max_buffer_size(struct iostream_private *stream,
size_t max_size)
diff -r d2a6f57e174f -r fd186eff7325 src/lib/istream.h
--- a/src/lib/istream.h Thu Apr 03 19:47:49 2014 +0300
+++ b/src/lib/istream.h Thu Apr 03 19:51:52 2014 +0300
@@ -157,4 +157,10 @@
bool i_stream_add_data(struct istream *stream, const unsigned char *data,
size_t size);
+void i_stream_set_input_pending(struct istream *stream, bool pending);
+
+/* If there are any I/O loop items associated with the stream, move all of
+ them to current_ioloop. */
+void i_stream_switch_ioloop(struct istream *stream);
+
#endif
More information about the dovecot-cvs
mailing list