changeset 3336:a3a72d5bdfce HEAD

o_stream_uncork() was previously always setting IO_WRITE handler even if there was no reason for it. This was relied on in imap/pop3 code when a handler could just send as much data as it can without actually buffering anything. So, removed the IO_WRITE handler forcing. It's only set if there's actually data in buffer or if flush_pending is set (via o_stream_set_flush_pending() or by returning 0 from flush callback handler). All in all, a minor optimization.
author Timo Sirainen <tss@iki.fi>
date Tue, 26 Apr 2005 13:43:54 +0300
parents ae6f1b54cd59
children b47043d0d131
files src/imap/client.c src/imap/imap-fetch-body.c src/lib/ostream-crlf.c src/lib/ostream-file.c src/lib/ostream-internal.h src/lib/ostream.c src/lib/ostream.h src/pop3/client.c
diffstat 8 files changed, 45 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/src/imap/client.c	Tue Apr 26 12:42:59 2005 +0300
+++ b/src/imap/client.c	Tue Apr 26 13:43:54 2005 +0300
@@ -337,6 +337,10 @@
 			_client_reset_command(client);
 		} else {
 			/* unfinished */
+			if (client->command_pending) {
+				o_stream_set_flush_pending(client->output,
+							   TRUE);
+			}
 			return FALSE;
 		}
 	}
--- a/src/imap/imap-fetch-body.c	Tue Apr 26 12:42:59 2005 +0300
+++ b/src/imap/imap-fetch-body.c	Tue Apr 26 13:43:54 2005 +0300
@@ -174,7 +174,7 @@
 	}
 
 	if ((uoff_t)sent != virtual_size && !blocks) {
-		/* Input stream gave less data then we expected. Two choices
+		/* Input stream gave less data than we expected. Two choices
 		   here: either we fill the missing data with spaces or we
 		   disconnect the client.
 
--- a/src/lib/ostream-crlf.c	Tue Apr 26 12:42:59 2005 +0300
+++ b/src/lib/ostream-crlf.c	Tue Apr 26 13:43:54 2005 +0300
@@ -55,6 +55,13 @@
 	return o_stream_flush(cstream->output);
 }
 
+static void _flush_pending(struct _ostream *stream, int set)
+{
+	struct crlf_ostream *cstream = (struct crlf_ostream *)stream;
+
+	o_stream_set_flush_pending(cstream->output, set);
+}
+
 static size_t _get_used_size(struct _ostream *stream)
 {
 	struct crlf_ostream *cstream = (struct crlf_ostream *)stream;
@@ -352,6 +359,7 @@
 
 	cstream->ostream.cork = _cork;
 	cstream->ostream.flush = _flush;
+	cstream->ostream.flush_pending = _flush_pending;
 	cstream->ostream.get_used_size = _get_used_size;
 	cstream->ostream.seek = _seek;
 	cstream->ostream.send_istream = _send_istream;
--- a/src/lib/ostream-file.c	Tue Apr 26 12:42:59 2005 +0300
+++ b/src/lib/ostream-file.c	Tue Apr 26 13:43:54 2005 +0300
@@ -45,6 +45,7 @@
 	unsigned int full:1; /* if head == tail, is buffer empty or full? */
 	unsigned int file:1;
 	unsigned int corked:1;
+	unsigned int flush_pending:1;
 	unsigned int no_socket_cork:1;
 	unsigned int no_sendfile:1;
 	unsigned int autoclose_fd:1;
@@ -226,10 +227,12 @@
 		if (set && fstream->io != NULL) {
 			io_remove(fstream->io);
 			fstream->io = NULL;
-		} else if (!set && fstream->io == NULL) {
+		} else if (!set) {
 			if (fstream->file)
 				buffer_flush(fstream);
-			else {
+			else if (fstream->io == NULL &&
+				 (!IS_STREAM_EMPTY(fstream) ||
+				  fstream->flush_pending)) {
 				fstream->io = io_add(fstream->fd, IO_WRITE,
 						     stream_send_io, fstream);
 			}
@@ -244,6 +247,17 @@
 	return buffer_flush(fstream);
 }
 
+static void _flush_pending(struct _ostream *stream, int set)
+{
+	struct file_ostream *fstream = (struct file_ostream *) stream;
+
+	fstream->flush_pending = set;
+	if (set && !fstream->corked && fstream->io == NULL) {
+		fstream->io = io_add(fstream->fd, IO_WRITE,
+				     stream_send_io, fstream);
+	}
+}
+
 static size_t get_unused_space(struct file_ostream *fstream)
 {
 	if (fstream->head > fstream->tail) {
@@ -347,6 +361,8 @@
 		io_remove(fstream->io);
 		fstream->io = NULL;
 	}
+	fstream->flush_pending = ret <= 0;
+
 	o_stream_unref(&fstream->ostream.ostream);
 }
 
@@ -711,6 +727,7 @@
 
 	fstream->ostream.cork = _cork;
 	fstream->ostream.flush = _flush;
+	fstream->ostream.flush_pending = _flush_pending;
 	fstream->ostream.get_used_size = _get_used_size;
 	fstream->ostream.seek = _seek;
 	fstream->ostream.sendv = _sendv;
--- a/src/lib/ostream-internal.h	Tue Apr 26 12:42:59 2005 +0300
+++ b/src/lib/ostream-internal.h	Tue Apr 26 13:43:54 2005 +0300
@@ -11,6 +11,7 @@
 /* methods: */
 	void (*cork)(struct _ostream *stream, int set);
 	int (*flush)(struct _ostream *stream);
+	void (*flush_pending)(struct _ostream *stream, int set);
 	size_t (*get_used_size)(struct _ostream *stream);
 	int (*seek)(struct _ostream *stream, uoff_t offset);
 	ssize_t (*sendv)(struct _ostream *stream, const struct const_iovec *iov,
--- a/src/lib/ostream.c	Tue Apr 26 12:42:59 2005 +0300
+++ b/src/lib/ostream.c	Tue Apr 26 13:43:54 2005 +0300
@@ -66,6 +66,13 @@
 	return _stream->flush(_stream);
 }
 
+void o_stream_set_flush_pending(struct ostream *stream, int set)
+{
+	struct _ostream *_stream = stream->real_stream;
+
+	_stream->flush_pending(_stream, set);
+}
+
 size_t o_stream_get_buffer_used_size(struct ostream *stream)
 {
 	struct _ostream *_stream = stream->real_stream;
--- a/src/lib/ostream.h	Tue Apr 26 12:42:59 2005 +0300
+++ b/src/lib/ostream.h	Tue Apr 26 13:43:54 2005 +0300
@@ -46,6 +46,9 @@
 /* Flush the output stream, blocks until everything is sent.
    Returns 1 if ok, -1 if error. */
 int o_stream_flush(struct ostream *stream);
+/* Set "flush pending" state of stream. If set, the flush callback is called
+   when more data is allowed to be sent, even if the buffer itself is empty. */
+void o_stream_set_flush_pending(struct ostream *stream, int set);
 /* Returns number of bytes currently in buffer. */
 size_t o_stream_get_buffer_used_size(struct ostream *stream);
 
--- a/src/pop3/client.c	Tue Apr 26 12:42:59 2005 +0300
+++ b/src/pop3/client.c	Tue Apr 26 13:43:54 2005 +0300
@@ -310,6 +310,8 @@
 		if (client_command_execute(client, line, args)) {
 			client->bad_counter = 0;
 			if (client->cmd != NULL) {
+				o_stream_set_flush_pending(client->output,
+							   TRUE);
 				client->waiting_input = TRUE;
 				break;
 			}