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