changeset 404:f25e575bf1ca HEAD

Created datastack_mempool which is used by at least a few temporary IOBuffers. Some other minor speedups/cleanups in IOBuffer and elsewhere..
author Timo Sirainen <tss@iki.fi>
date Thu, 10 Oct 2002 05:01:34 +0300
parents c3c7f9345f83
children 576967cbd064
files src/lib-index/maildir/maildir-build.c src/lib-index/maildir/maildir-index.h src/lib-index/maildir/maildir-open.c src/lib-index/maildir/maildir-sync.c src/lib-index/maildir/maildir-update.c src/lib-index/mbox/mbox-index.c src/lib-index/mbox/mbox-rewrite.c src/lib-storage/index/mbox/mbox-expunge.c src/lib/iobuffer.c src/lib/iobuffer.h src/lib/ioloop.c src/lib/mempool-datastack.c src/lib/network.c
diffstat 13 files changed, 324 insertions(+), 124 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-index/maildir/maildir-build.c	Thu Oct 10 04:45:42 2002 +0300
+++ b/src/lib-index/maildir/maildir-build.c	Thu Oct 10 05:01:34 2002 +0300
@@ -69,7 +69,7 @@
 			    MAILDIR_LOCATION_EXTRA_SPACE);
 
 	/* parse the header and update record's fields */
-	failed = !maildir_record_update(update, fd, path);
+	failed = !maildir_record_update(update, fd, st.st_size);
 
 	if (!index->update_end(update) || failed)
 		return FALSE;
--- a/src/lib-index/maildir/maildir-index.h	Thu Oct 10 04:45:42 2002 +0300
+++ b/src/lib-index/maildir/maildir-index.h	Thu Oct 10 05:01:34 2002 +0300
@@ -22,6 +22,6 @@
 
 IOBuffer *maildir_open_mail(MailIndex *index, MailIndexRecord *rec);
 
-int maildir_record_update(MailIndexUpdate *update, int fd, const char *path);
+int maildir_record_update(MailIndexUpdate *update, int fd, off_t file_size);
 
 #endif
--- a/src/lib-index/maildir/maildir-open.c	Thu Oct 10 04:45:42 2002 +0300
+++ b/src/lib-index/maildir/maildir-open.c	Thu Oct 10 05:01:34 2002 +0300
@@ -28,13 +28,12 @@
 	}
 
 	path = t_strconcat(index->dir, "/cur/", fname, NULL);
-
 	fd = open(path, O_RDONLY);
 	if (fd == -1) {
 		index_set_error(index, "Error opening mail file %s: %m", path);
 		return NULL;
 	}
 
-	return io_buffer_create_mmap(fd, default_pool, MAIL_MMAP_BLOCK_SIZE,
-				     0, 0, TRUE);
+	return io_buffer_create_mmap(fd, default_pool, MAIL_MMAP_BLOCK_SIZE, 0,
+				     0, IOBUFFER_FLAG_AUTOCLOSE);
 }
--- a/src/lib-index/maildir/maildir-sync.c	Thu Oct 10 04:45:42 2002 +0300
+++ b/src/lib-index/maildir/maildir-sync.c	Thu Oct 10 05:01:34 2002 +0300
@@ -14,9 +14,9 @@
 #include <utime.h>
 #include <sys/stat.h>
 
-static int maildir_index_sync_file(MailIndex *index,
-				   MailIndexRecord *rec, unsigned int seq,
-				   const char *fname, const char *path,
+static int maildir_index_sync_file(MailIndex *index, MailIndexRecord *rec,
+				   unsigned int seq, const char *fname,
+				   const char *path, off_t file_size,
 				   int fname_changed, int file_changed)
 {
 	MailIndexUpdate *update;
@@ -41,7 +41,7 @@
 			index_file_set_syscall_error(index, path, "open()");
 			failed = TRUE;
 		} else {
-			if (!maildir_record_update(update, fd, path))
+			if (!maildir_record_update(update, fd, file_size))
 				failed = TRUE;
 			if (close(fd) < 0) {
 				index_file_set_syscall_error(index, path,
@@ -124,7 +124,8 @@
 		fname_changed = strcmp(value, fname) != 0;
 		if (fname_changed || file_changed) {
 			if (!maildir_index_sync_file(index, rec, seq, value,
-						     str, fname_changed,
+						     str, st.st_size,
+						     fname_changed,
 						     file_changed))
 				return FALSE;
 		}
--- a/src/lib-index/maildir/maildir-update.c	Thu Oct 10 04:45:42 2002 +0300
+++ b/src/lib-index/maildir/maildir-update.c	Thu Oct 10 05:01:34 2002 +0300
@@ -4,15 +4,15 @@
 #include "iobuffer.h"
 #include "maildir-index.h"
 
-int maildir_record_update(MailIndexUpdate *update, int fd, const char *path)
+int maildir_record_update(MailIndexUpdate *update, int fd, off_t file_size)
 {
 	IOBuffer *inbuf;
 
-	i_assert(path != NULL);
-
-	inbuf = io_buffer_create_mmap(fd, default_pool,
-				      MAIL_MMAP_BLOCK_SIZE, 0, 0, FALSE);
+	t_push();
+	inbuf = io_buffer_create_mmap(fd, data_stack_pool,
+				      MAIL_MMAP_BLOCK_SIZE, 0, file_size, 0);
 	mail_index_update_headers(update, inbuf, 0, NULL, NULL);
 	io_buffer_unref(inbuf);
+	t_pop();
 	return TRUE;
 }
--- a/src/lib-index/mbox/mbox-index.c	Thu Oct 10 04:45:42 2002 +0300
+++ b/src/lib-index/mbox/mbox-index.c	Thu Oct 10 05:01:34 2002 +0300
@@ -39,7 +39,7 @@
 
 	return io_buffer_create_mmap(index->mbox_fd, default_pool,
 				     MAIL_MMAP_BLOCK_SIZE,
-				     (uoff_t)offset, 0, FALSE);
+				     (uoff_t)offset, 0, 0);
 }
 
 void mbox_file_close(MailIndex *index)
--- a/src/lib-index/mbox/mbox-rewrite.c	Thu Oct 10 04:45:42 2002 +0300
+++ b/src/lib-index/mbox/mbox-rewrite.c	Thu Oct 10 05:01:34 2002 +0300
@@ -362,8 +362,11 @@
 	if (lseek(out_fd, (off_t)out_offset, SEEK_SET) < 0)
 		return -1;
 
-	inbuf = io_buffer_create_mmap(in_fd, default_pool, 65536, 0, 0, FALSE);
-	outbuf = io_buffer_create_file(out_fd, default_pool, 1024, FALSE);
+	t_push();
+
+	inbuf = io_buffer_create_mmap(in_fd, data_stack_pool,
+				      1024*256, 0, 0, 0);
+	outbuf = io_buffer_create_file(out_fd, data_stack_pool, 1024, FALSE);
 
 	ret = io_buffer_send_iobuffer(outbuf, inbuf, inbuf->size);
 	if (ret < 0)
@@ -376,6 +379,7 @@
 
 	io_buffer_unref(outbuf);
 	io_buffer_unref(inbuf);
+	t_pop();
 
 	return ret;
 }
@@ -447,7 +451,8 @@
 	}
 	dirty_offset = 0;
 
-	outbuf = io_buffer_create_file(tmp_fd, default_pool, 8192, FALSE);
+	t_push();
+	outbuf = io_buffer_create_file(tmp_fd, data_stack_pool, 8192, FALSE);
 
 	failed = FALSE; seq = 1;
 	rec = index->lookup(index, 1);
@@ -522,6 +527,7 @@
 
 	io_buffer_unref(inbuf);
 	io_buffer_unref(outbuf);
+	t_pop();
 
 	if (!failed) {
 		/* POSSIBLE DATA LOSS HERE. We're writing to the mbox file,
--- a/src/lib-storage/index/mbox/mbox-expunge.c	Thu Oct 10 04:45:42 2002 +0300
+++ b/src/lib-storage/index/mbox/mbox-expunge.c	Thu Oct 10 05:01:34 2002 +0300
@@ -126,7 +126,8 @@
 		return FALSE;
 	}
 
-	outbuf = io_buffer_create_file(inbuf->fd, default_pool, 4096, FALSE);
+	t_push();
+	outbuf = io_buffer_create_file(inbuf->fd, data_stack_pool, 4096, FALSE);
 
 	failed = !expunge_real(ibox, rec, seq, inbuf, outbuf,
 			       expunge_func, context);
@@ -148,6 +149,7 @@
 
 	(void)mbox_unlock(ibox->index);
 	io_buffer_unref(outbuf);
+	t_pop();
 
 	return !failed;
 }
--- a/src/lib/iobuffer.c	Thu Oct 10 04:45:42 2002 +0300
+++ b/src/lib/iobuffer.c	Thu Oct 10 05:01:34 2002 +0300
@@ -31,6 +31,9 @@
 #include "network.h"
 
 #include <unistd.h>
+#include <sys/stat.h>
+
+#define IO_BUFFER_MIN_SIZE 4096
 
 #define MAX_SSIZE_T(size) ((size) < SSIZE_T_MAX ? (size_t)(size) : SSIZE_T_MAX)
 
@@ -57,6 +60,7 @@
         i_assert(fd >= 0);
         i_assert(pool != NULL);
 
+	pool_ref(pool);
 	buf = p_new(pool, IOBuffer, 1);
 	buf->refcount = 1;
 	buf->fd = fd;
@@ -67,22 +71,22 @@
 }
 
 IOBuffer *io_buffer_create_file(int fd, Pool pool, size_t max_buffer_size,
-				int autoclose_fd)
+				int flags)
 {
 	IOBuffer *buf;
 
 	buf = io_buffer_create(fd, pool, IO_PRIORITY_DEFAULT, max_buffer_size);
 	buf->file = TRUE;
-	buf->close_file = autoclose_fd;
+	buf->close_file = (flags & IOBUFFER_FLAG_AUTOCLOSE) != 0;
         return buf;
 }
 
 IOBuffer *io_buffer_create_mmap(int fd, Pool pool, size_t block_size,
-				uoff_t start_offset, uoff_t size,
-				int autoclose_fd)
+				uoff_t start_offset, uoff_t size, int flags)
 {
 	IOBuffer *buf;
-	off_t stop_offset;
+	struct stat st;
+	uoff_t stop_offset;
 
 	i_assert(start_offset < OFF_T_MAX);
 
@@ -99,30 +103,33 @@
 		block_size += mmap_pagesize;
 	}
 
-	buf = io_buffer_create_file(fd, pool, block_size, autoclose_fd);
+	buf = io_buffer_create_file(fd, pool, block_size, flags);
 	buf->mmaped = TRUE;
 	buf->receive = TRUE;
 
-	stop_offset = lseek(fd, 0, SEEK_END);
-	if (stop_offset < 0) {
+	if (fstat(fd, &st) == 0)
+		stop_offset = (uoff_t)st.st_size;
+	else {
 		i_error("io_buffer_create_mmap(): lseek() failed: %m");
 		stop_offset = 0;
-		buf->size = 0;
 	}
 
-	if (start_offset > (uoff_t)stop_offset)
+	if (start_offset > stop_offset)
 		start_offset = stop_offset;
 
-	if (size > (uoff_t)stop_offset-start_offset) {
-		i_warning("Trying to create IOBuffer with size %"PRIuUOFF_T
-			  " but we have only %"PRIuUOFF_T" bytes available "
-			  "in file", size, stop_offset-start_offset);
+	if (size > stop_offset-start_offset) {
+		i_warning("Trying to create IOBuffer with size "
+			  "%"PRIuUOFF_T" but we have only %"PRIuUOFF_T
+			  " bytes available in file", size,
+			  stop_offset-start_offset);
 		size = stop_offset-start_offset;
 	}
 
+	if (size == 0)
+		size = stop_offset - start_offset;
+
 	buf->start_offset = start_offset;
-	buf->size = size > 0 ? size : stop_offset - start_offset;
-	buf->limit = buf->size;
+	buf->limit = buf->size = size;
 
 	buf->skip = buf->pos = buf->start_offset;
 	return buf;
@@ -156,6 +163,7 @@
 	}
 	io_buffer_close(buf);
         p_free(buf->pool, buf);
+	pool_unref(buf->pool);
 }
 
 void io_buffer_close(IOBuffer *buf)
@@ -238,11 +246,6 @@
 {
 	ssize_t ret;
 
-	i_assert(size <= SSIZE_T_MAX);
-
-	if (size == 0)
-		return 0;
-
 	ret = write(fd, buf, size);
 	if (ret < 0 && (errno == EINTR || errno == EAGAIN))
 		ret = 0;
@@ -250,38 +253,52 @@
 	return ret;
 }
 
-static void buf_send_real(IOBuffer *buf)
+static ssize_t io_buffer_write(IOBuffer *buf, const void *data, size_t size)
 {
-	int ret;
+	ssize_t ret;
 
-	if (!buf->file) {
-		ret = net_transmit(buf->fd, buf->buffer + buf->skip,
-				   buf->pos - buf->skip);
-	} else {
-		ret = my_write(buf->fd, buf->buffer + buf->skip,
-			       buf->pos - buf->skip);
-	}
+	if (size > SSIZE_T_MAX)
+		size = SSIZE_T_MAX;
+	if (size == 0)
+		return 0;
 
+	ret = buf->file ? my_write(buf->fd, data, size) :
+		net_transmit(buf->fd, data, size);
 	if (ret < 0) {
+		/* disconnected */
 		buf->buf_errno = errno;
 		io_buffer_close(buf);
-	} else {
-		buf->offset += ret;
-		buf->skip += ret;
-		if (buf->skip == buf->pos) {
-			/* everything sent */
-			buf->skip = buf->pos = 0;
+		return -1;
+	}
+
+	buf->offset += ret;
+	return ret;
+}
+
+static void buf_send_real(IOBuffer *buf)
+{
+	ssize_t ret;
+
+	ret = io_buffer_write(buf, buf->buffer + buf->skip,
+			      buf->pos - buf->skip);
+	if (ret < 0)
+		return;
 
-			/* call flush function */
-			if (buf->flush_func != NULL) {
-				buf->flush_func(buf->flush_context, buf);
-				buf->flush_func = NULL;
+	buf->skip += ret;
+	if (buf->skip == buf->pos) {
+		/* everything sent */
+		buf->skip = buf->pos = 0;
 
-				if (buf->corked) {
-					/* remove cork */
+		/* call flush function */
+		if (buf->flush_func != NULL) {
+			buf->flush_func(buf->flush_context, buf);
+			buf->flush_func = NULL;
+
+			if (buf->corked) {
+				/* remove cork */
+				if (!buf->file)
 					net_set_cork(buf->fd, FALSE);
-					buf->corked = FALSE;
-				}
+				buf->corked = FALSE;
 			}
 		}
 	}
@@ -300,32 +317,56 @@
         return TRUE;
 }
 
+#define IOBUFFER_IS_FULL(buf) \
+	((buf)->pos == (buf)->buffer_size)
+
+/* write only as much as needed, put the rest into buffer.
+   write() only full buffers. */
 static void block_loop_send(IOBufferBlockContext *ctx)
 {
-	size_t size;
+	size_t size, buffer_space_left;
 	ssize_t ret;
 
-	if (ctx->outbuf->skip != ctx->outbuf->pos) {
-		buf_send_real(ctx->outbuf);
-	} else {
-		/* send the data */
-		size = MAX_SSIZE_T(ctx->size);
+	size = MAX_SSIZE_T(ctx->size);
+
+	buffer_space_left = ctx->outbuf->buffer_size - ctx->outbuf->pos;
+	if (ctx->outbuf->pos != 0 || ctx->size < buffer_space_left) {
+		if (buffer_space_left > 0) {
+			/* we have space in the buffer, fill it before
+			   writing */
+			if (size > buffer_space_left)
+				size = buffer_space_left;
 
-		ret = !ctx->outbuf->file ?
-			net_transmit(ctx->outbuf->fd, ctx->data, size) :
-			my_write(ctx->outbuf->fd, ctx->data, size);
+			memcpy(ctx->outbuf->buffer + ctx->outbuf->pos,
+			       ctx->data, size);
+			ctx->outbuf->pos += size;
 
-		if (ret < 0) {
-			ctx->outbuf->buf_errno = errno;
-                        io_buffer_close(ctx->outbuf);
-		} else {
-			ctx->outbuf->offset += ret;
+			ctx->data += size;
+			ctx->size -= size;
+		}
+
+		if (IOBUFFER_IS_FULL(ctx->outbuf))
+			buf_send_real(ctx->outbuf);
+	} else {
+		ret = io_buffer_write(ctx->outbuf, ctx->data, size);
+		if (ret > 0) {
 			ctx->data += ret;
 			ctx->size -= ret;
 		}
 	}
 
-	if (ctx->outbuf->closed || (ctx->size == 0 && ctx->last_block))
+	if (ctx->outbuf->closed || (ctx->size == 0 && ctx->last_block &&
+				    !IOBUFFER_IS_FULL(ctx->outbuf)))
+		io_loop_stop(ctx->ioloop);
+}
+
+/* write out all data from buffer */
+static void block_loop_flush(IOBufferBlockContext *ctx)
+{
+	if (ctx->outbuf->skip != ctx->outbuf->pos)
+		buf_send_real(ctx->outbuf);
+
+	if (ctx->outbuf->closed || ctx->outbuf->skip == ctx->outbuf->pos)
 		io_loop_stop(ctx->ioloop);
 }
 
@@ -342,7 +383,6 @@
 static int io_buffer_ioloop(IOBuffer *buf, IOBufferBlockContext *ctx,
 			    void (*send_func)(IOBufferBlockContext *ctx))
 {
-	Pool pool;
 	Timeout to;
 	int save_errno;
 
@@ -350,9 +390,10 @@
 	if (buf->io != NULL)
 		io_remove(buf->io);
 
+	t_push();
+
 	/* create a new I/O loop */
-	pool = pool_create("io_buffer_ioloop", 1024, FALSE);
-	ctx->ioloop = io_loop_create(pool);
+	ctx->ioloop = io_loop_create(data_stack_pool);
 	ctx->outbuf = buf;
 
 	buf->io = io_add(buf->fd, IO_WRITE, (IOFunc) send_func, ctx);
@@ -362,12 +403,6 @@
 	io_loop_run(ctx->ioloop);
 	save_errno = errno;
 
-	if (buf->corked) {
-		/* remove cork */
-		net_set_cork(buf->fd, FALSE);
-		buf->corked = FALSE;
-	}
-
 	if (buf->io != NULL) {
 		io_remove(buf->io);
 		buf->io = NULL;
@@ -382,7 +417,8 @@
 	}
 
 	io_loop_destroy(ctx->ioloop);
-	pool_unref(pool);
+
+	t_pop();
 
 	errno = save_errno;
 	return ctx->size > 0 ? -1 : 1;
@@ -402,13 +438,38 @@
         return io_buffer_ioloop(buf, &ctx, block_loop_send);
 }
 
+static int io_buffer_flush(IOBuffer *buf)
+{
+        IOBufferBlockContext ctx;
+	ssize_t ret;
+
+	if (buf->skip == buf->pos)
+		return 1;
+
+	ret = io_buffer_write(buf, buf->buffer + buf->skip,
+			      buf->pos - buf->skip);
+	if (ret < 0)
+		return -1;
+
+	buf->skip += ret;
+	if (buf->skip == buf->pos)
+		return 1;
+
+	memset(&ctx, 0, sizeof(ctx));
+	ctx.last_block = TRUE;
+
+        return io_buffer_ioloop(buf, &ctx, block_loop_flush);
+}
+
 void io_buffer_cork(IOBuffer *buf)
 {
 	i_assert(!buf->receive);
 
-	if (!buf->file && !buf->corked)
-		net_set_cork(buf->fd, TRUE);
-	buf->corked = TRUE;
+	if (!buf->corked) {
+		if (!buf->file)
+			net_set_cork(buf->fd, TRUE);
+		buf->corked = TRUE;
+	}
 }
 
 static void buffer_alloc_more(IOBuffer *buf, size_t size)
@@ -446,7 +507,8 @@
 
 int io_buffer_send(IOBuffer *buf, const void *data, size_t size)
 {
-	int i, corked, ret;
+	ssize_t ret;
+	int i, corked;
 
 	i_assert(!buf->receive);
         i_assert(data != NULL);
@@ -462,16 +524,10 @@
 	for (i = 0; i < 2; i++) {
 		if (buf->pos == 0 && !corked) {
 			/* buffer is empty, try to send the data immediately */
-			ret = buf->file ? my_write(buf->fd, data, size) :
-				net_transmit(buf->fd, data, size);
-			if (ret < 0) {
-				/* disconnected */
-				buf->buf_errno = errno;
-				io_buffer_close(buf);
+			ret = io_buffer_write(buf, data, size);
+			if (ret < 0)
 				return -1;
-			}
 
-			buf->offset += ret;
 			data = (const char *) data + ret;
 			size -= ret;
 		}
@@ -501,7 +557,7 @@
 	memcpy(buf->buffer + buf->pos, data, size);
 	buf->pos += size;
 
-	if (buf->io == NULL) {
+	if (buf->io == NULL && !buf->corked) {
 		buf->io = io_add_priority(buf->fd, buf->priority, IO_WRITE,
 					  (IOFunc) buf_send, buf);
 	}
@@ -543,7 +599,9 @@
 
 	i_assert(inbuf->offset < OFF_T_MAX);
 
-	io_buffer_send_flush(outbuf);
+	/* flush out any data in buffer */
+	if (io_buffer_flush(outbuf) < 0)
+		return -1;
 
 	/* first try if we can do it with a single sendfile() call */
 	offset = inbuf->offset;
@@ -636,15 +694,15 @@
 {
 	i_assert(!buf->receive);
 
-	if (buf->closed || buf->io == NULL)
+	if (buf->closed)
                 return;
 
-	if (buf->skip != buf->pos)
-		io_buffer_send_blocking(buf, NULL, 0);
+	io_buffer_flush(buf);
 
 	if (buf->corked) {
 		/* remove cork */
-		net_set_cork(buf->fd, FALSE);
+		if (!buf->file)
+			net_set_cork(buf->fd, FALSE);
 		buf->corked = FALSE;
 	}
 }
@@ -661,6 +719,12 @@
 
 	buf->flush_func = func;
 	buf->flush_context = context;
+
+	/* if we're corked, the io wasn't set */
+	if (buf->io == NULL) {
+		buf->io = io_add_priority(buf->fd, buf->priority, IO_WRITE,
+					  (IOFunc) buf_send, buf);
+	}
 }
 
 static ssize_t io_buffer_set_mmaped_pos(IOBuffer *buf)
@@ -721,7 +785,11 @@
 		return -1;
 	}
 
-	(void)madvise((void *) buf->buffer, buf->buffer_size, MADV_SEQUENTIAL);
+	/* madvise() only if the mmap()ed area was larger than page size */
+	if (buf->buffer_size > mmap_pagesize) {
+		(void)madvise((void *) buf->buffer, buf->buffer_size,
+			      MADV_SEQUENTIAL);
+	}
 
 	return io_buffer_set_mmaped_pos(buf);
 }
@@ -1064,16 +1132,10 @@
 
 	if (buf->pos == 0 && !buf->corked) {
 		/* buffer is empty, try to send the data immediately */
-		ret = buf->file ? my_write(buf->fd, buf->buffer, size) :
-			net_transmit(buf->fd, buf->buffer, size);
-		if (ret < 0) {
-			/* disconnected */
-			buf->buf_errno = errno;
-			io_buffer_close(buf);
+		ret = io_buffer_write(buf, buf->buffer, size);
+		if (ret < 0)
 			return -1;
-		}
 
-		buf->offset += ret;
 		if ((size_t)ret == size) {
                         /* all sent */
 			return 1;
@@ -1084,7 +1146,7 @@
 
 	buf->pos += size;
 
-	if (buf->io == NULL) {
+	if (buf->io == NULL && !buf->corked) {
 		buf->io = io_add_priority(buf->fd, buf->priority, IO_WRITE,
 					  (IOFunc) buf_send, buf);
 	}
--- a/src/lib/iobuffer.h	Thu Oct 10 04:45:42 2002 +0300
+++ b/src/lib/iobuffer.h	Thu Oct 10 05:01:34 2002 +0300
@@ -3,9 +3,11 @@
 
 #include "ioloop.h"
 
-#define IO_BUFFER_MIN_SIZE		512
+typedef void (*IOBufferFlushFunc) (void *context, IOBuffer *buf);
 
-typedef void (*IOBufferFlushFunc) (void *context, IOBuffer *buf);
+enum {
+        IOBUFFER_FLAG_AUTOCLOSE		= 0x01
+};
 
 struct _IOBuffer {
 	int fd;
@@ -52,12 +54,12 @@
 			   size_t max_buffer_size);
 /* Same as io_buffer_create(), but specify that we're reading/writing file. */
 IOBuffer *io_buffer_create_file(int fd, Pool pool, size_t max_buffer_size,
-				int autoclose_fd);
+				int flags);
 /* Read the file by mmap()ing it in blocks. stop_offset specifies where to
    stop reading, or 0 to end of file. */
 IOBuffer *io_buffer_create_mmap(int fd, Pool pool, size_t block_size,
 				uoff_t start_offset, uoff_t size,
-				int autoclose_fd);
+				int flags);
 
 /* Reference counting. References start from 1, so calling io_buffer_unref()
    destroys the buffer if io_buffer_ref() is never used. */
--- a/src/lib/ioloop.c	Thu Oct 10 04:45:42 2002 +0300
+++ b/src/lib/ioloop.c	Thu Oct 10 05:01:34 2002 +0300
@@ -35,7 +35,7 @@
 	 ((tvp)->tv_sec == (uvp)->tv_sec && \
 	  (tvp)->tv_usec > (uvp)->tv_usec))
 
-time_t ioloop_time;
+time_t ioloop_time = 0;
 struct timeval ioloop_timeval;
 
 static IOLoop current_ioloop = NULL;
@@ -192,7 +192,8 @@
 	timeout->func = func;
 	timeout->context = context;
 
-        timeout_update_next(timeout, NULL);
+	timeout_update_next(timeout, current_ioloop->running ?
+			    NULL : &ioloop_timeval);
         timeout_list_insert(current_ioloop, timeout);
 	return timeout;
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/mempool-datastack.c	Thu Oct 10 05:01:34 2002 +0300
@@ -0,0 +1,126 @@
+/*
+ mempool-data-stack.c : Memory pool wrapper for data stack
+
+    Copyright (c) 2002 Timo Sirainen
+
+    Permission is hereby granted, free of charge, to any person obtaining
+    a copy of this software and associated documentation files (the
+    "Software"), to deal in the Software without restriction, including
+    without limitation the rights to use, copy, modify, merge, publish,
+    distribute, sublicense, and/or sell copies of the Software, and to
+    permit persons to whom the Software is furnished to do so, subject to
+    the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "lib.h"
+#include "mempool.h"
+
+#include <stdlib.h>
+
+#define MAX_ALLOC_SIZE SSIZE_T_MAX
+
+typedef struct {
+	union {
+		size_t size;
+		unsigned char alignment[MEM_ALIGN_SIZE];
+	} size;
+	/* void data[]; */
+} PoolAlloc;
+
+static void pool_data_stack_ref(Pool pool);
+static void pool_data_stack_unref(Pool pool);
+static void *pool_data_stack_malloc(Pool pool, size_t size);
+static void pool_data_stack_free(Pool pool, void *mem);
+static void *pool_data_stack_realloc(Pool pool, void *mem, size_t size);
+static void *pool_data_stack_realloc_min(Pool pool, void *mem, size_t size);
+static void pool_data_stack_clear(Pool pool);
+
+static struct Pool static_data_stack_pool = {
+	pool_data_stack_ref,
+	pool_data_stack_unref,
+
+	pool_data_stack_malloc,
+	pool_data_stack_free,
+
+	pool_data_stack_realloc,
+	pool_data_stack_realloc_min,
+
+	pool_data_stack_clear
+};
+
+Pool data_stack_pool = &static_data_stack_pool;
+
+static void pool_data_stack_ref(Pool pool __attr_unused__)
+{
+}
+
+static void pool_data_stack_unref(Pool pool __attr_unused__)
+{
+}
+
+static void *pool_data_stack_malloc(Pool pool __attr_unused__, size_t size)
+{
+	PoolAlloc *alloc;
+
+	if (size > MAX_ALLOC_SIZE)
+		i_panic("Trying to allocate too much memory");
+
+	alloc = t_malloc0(sizeof(PoolAlloc) + size);
+	alloc->size.size = size;
+
+	return (char *) alloc + sizeof(PoolAlloc);
+}
+
+static void pool_data_stack_free(Pool pool __attr_unused__,
+				 void *mem __attr_unused__)
+{
+}
+
+static void *pool_data_stack_realloc(Pool pool, void *mem, size_t size)
+{
+	return pool_data_stack_realloc_min(pool, mem, size);
+}
+
+static void *pool_data_stack_realloc_min(Pool pool __attr_unused__,
+					 void *mem, size_t size)
+{
+	PoolAlloc *alloc, *new_alloc;
+        size_t old_size;
+	unsigned char *rmem;
+
+	if (mem == NULL)
+		return pool_data_stack_malloc(pool, size);
+
+	/* get old size */
+	alloc = (PoolAlloc *) ((char *) mem - sizeof(PoolAlloc));
+	old_size = alloc->size.size;
+
+	if (old_size >= size)
+		return mem;
+
+	if (!t_try_realloc(alloc, sizeof(PoolAlloc) + size)) {
+		new_alloc = t_malloc(sizeof(PoolAlloc) + size);
+		memcpy(new_alloc, alloc, old_size + sizeof(PoolAlloc));
+		alloc = new_alloc;
+	}
+	alloc->size.size = size;
+
+        rmem = (unsigned char *) alloc + sizeof(PoolAlloc);
+	memset(rmem + old_size, 0, size-old_size);
+	return rmem;
+}
+
+static void pool_data_stack_clear(Pool pool __attr_unused__)
+{
+}
--- a/src/lib/network.c	Thu Oct 10 04:45:42 2002 +0300
+++ b/src/lib/network.c	Thu Oct 10 05:01:34 2002 +0300
@@ -228,7 +228,8 @@
 void net_set_cork(int fd __attr_unused__, int cork __attr_unused__)
 {
 #ifdef TCP_CORK
-	setsockopt(fd, SOL_TCP, TCP_CORK, &cork, sizeof(cork));
+	if (setsockopt(fd, SOL_TCP, TCP_CORK, &cork, sizeof(cork)) < 0)
+		i_error("setsockopt(TCP_CORK) failed: %m");
 #endif
 }