changeset 6163:48dbfdba4e24 HEAD

Delay lseek()s and use pwrite() whenever possible.
author Timo Sirainen <tss@iki.fi>
date Thu, 02 Aug 2007 18:37:31 +0300
parents 896cc473c1f0
children 22398d619cac
files src/lib/ostream-file.c
diffstat 1 files changed, 48 insertions(+), 21 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib/ostream-file.c	Thu Aug 02 18:27:46 2007 +0300
+++ b/src/lib/ostream-file.c	Thu Aug 02 18:37:31 2007 +0300
@@ -33,6 +33,7 @@
 
 	int fd;
 	struct io *io;
+	uoff_t real_offset;
 
 	unsigned char *buffer; /* ring-buffer */
 	size_t buffer_size, max_buffer_size, optimal_block_size;
@@ -133,17 +134,50 @@
 	}
 }
 
+static int o_stream_lseek(struct file_ostream *fstream)
+{
+	uoff_t offset = fstream->ostream.ostream.offset;
+	off_t ret;
+
+	if (fstream->real_offset == offset)
+		return 0;
+
+	ret = lseek(fstream->fd, (off_t)offset, SEEK_SET);
+	if (ret < 0) {
+		fstream->ostream.ostream.stream_errno = errno;
+		return -1;
+	}
+
+	if (ret != (off_t)offset) {
+		fstream->ostream.ostream.stream_errno = EINVAL;
+		return -1;
+	}
+	fstream->real_offset = offset;
+	return 0;
+}
+
 static ssize_t o_stream_writev(struct file_ostream *fstream,
 			       const struct const_iovec *iov, int iov_size)
 {
+	uoff_t offset = fstream->ostream.ostream.offset;
 	ssize_t ret;
 	size_t size, sent;
 	int i;
 
 	o_stream_socket_cork(fstream);
-	if (iov_size == 1)
-		ret = write(fstream->fd, iov->iov_base, iov->iov_len);
-	else {
+	if (iov_size == 1) {
+		if (!fstream->file || fstream->real_offset == offset) {
+			ret = write(fstream->fd, iov->iov_base, iov->iov_len);
+			if (ret > 0)
+				fstream->real_offset += ret;
+		} else {
+			ret = pwrite(fstream->fd, iov->iov_base, iov->iov_len,
+				     offset);
+		}
+	} else {
+		if (o_stream_lseek(fstream) < 0)
+			return -1;
+
 		sent = 0;
 		while (iov_size > IOV_MAX) {
 			size = 0;
@@ -155,6 +189,7 @@
 			if (ret != (ssize_t)size)
 				break;
 
+			fstream->real_offset += ret;
 			sent += ret;
 			iov += IOV_MAX;
 			iov_size -= IOV_MAX;
@@ -164,8 +199,10 @@
 			ret = writev(fstream->fd, (const struct iovec *)iov,
 				     iov_size);
 		}
-		if (ret > 0)
+		if (ret > 0) {
+			fstream->real_offset += ret;
 			ret += sent;
+		}
 	}
 
 	if (ret < 0) {
@@ -292,9 +329,8 @@
 static int _seek(struct _ostream *stream, uoff_t offset)
 {
 	struct file_ostream *fstream = (struct file_ostream *)stream;
-	off_t ret;
 
-	if (offset > OFF_T_MAX) {
+	if (offset > OFF_T_MAX || !fstream->file) {
 		stream->ostream.stream_errno = EINVAL;
 		return -1;
 	}
@@ -302,17 +338,6 @@
 	if (buffer_flush(fstream) < 0)
 		return -1;
 
-	ret = lseek(fstream->fd, (off_t)offset, SEEK_SET);
-	if (ret < 0) {
-		stream->ostream.stream_errno = errno;
-		return -1;
-	}
-
-	if (ret != (off_t)offset) {
-		stream->ostream.stream_errno = EINVAL;
-		return -1;
-	}
-
 	stream->ostream.stream_errno = 0;
 	stream->ostream.offset = offset;
 	return 1;
@@ -506,6 +531,9 @@
 	if ((ret = buffer_flush(foutstream)) <= 0)
 		return ret;
 
+	if (o_stream_lseek(foutstream) < 0)
+		return -1;
+
         start_offset = v_offset = instream->v_offset;
 	do {
 		offset = instream->real_stream->abs_start_offset + v_offset;
@@ -662,10 +690,7 @@
 		}
 		in_limit -= size;
 
-		if (o_stream_seek(&outstream->ostream, out_offset) < 0)
-			return -1;
-
-		ret = write_full(foutstream->fd, data, size);
+		ret = pwrite_full(foutstream->fd, data, size, out_offset);
 		if (ret < 0) {
 			/* error */
 			outstream->ostream.stream_errno = errno;
@@ -792,6 +817,7 @@
 	offset = lseek(fd, 0, SEEK_CUR);
 	if (offset >= 0) {
 		ostream->offset = offset;
+		fstream->real_offset = offset;
 		fstream_init_file(fstream);
 	} else {
 		if (net_getsockname(fd, NULL, NULL) < 0) {
@@ -818,6 +844,7 @@
 	fstream = o_stream_create_fd_common(fd, autoclose_fd);
 	fstream_init_file(fstream);
 	fstream->max_buffer_size = fstream->optimal_block_size;
+	fstream->real_offset = offset;
 
 	ostream = _o_stream_create(&fstream->ostream);
 	ostream->offset = offset;