dovecot: o_stream_send_istream(): Don't fstat() the stream unles...
dovecot at dovecot.org
dovecot at dovecot.org
Thu Nov 8 01:58:09 EET 2007
details: http://hg.dovecot.org/dovecot/rev/ba048bb01842
changeset: 6723:ba048bb01842
user: Timo Sirainen <tss at iki.fi>
date: Thu Nov 08 01:58:04 2007 +0200
description:
o_stream_send_istream(): Don't fstat() the stream unless we have to.
diffstat:
1 file changed, 33 insertions(+), 37 deletions(-)
src/lib/ostream-file.c | 70 ++++++++++++++++++++++--------------------------
diffs (134 lines):
diff -r a9739ce5a7e4 -r ba048bb01842 src/lib/ostream-file.c
--- a/src/lib/ostream-file.c Thu Nov 08 01:56:57 2007 +0200
+++ b/src/lib/ostream-file.c Thu Nov 08 01:58:04 2007 +0200
@@ -530,13 +530,20 @@ static ssize_t o_stream_file_sendv(struc
}
static off_t io_stream_sendfile(struct ostream_private *outstream,
- struct istream *instream,
- int in_fd, uoff_t in_size)
+ struct istream *instream, int in_fd)
{
struct file_ostream *foutstream = (struct file_ostream *)outstream;
+ const struct stat *st;
uoff_t start_offset;
- uoff_t offset, send_size, v_offset;
+ uoff_t in_size, offset, send_size, v_offset;
ssize_t ret;
+
+ st = i_stream_stat(instream, TRUE);
+ if (st == NULL) {
+ outstream->ostream.stream_errno = instream->stream_errno;
+ return -1;
+ }
+ in_size = st->st_size;
o_stream_socket_cork(foutstream);
@@ -580,14 +587,14 @@ static off_t io_stream_sendfile(struct o
}
static off_t io_stream_copy(struct ostream_private *outstream,
- struct istream *instream, uoff_t in_size)
+ struct istream *instream)
{
struct file_ostream *foutstream = (struct file_ostream *)outstream;
uoff_t start_offset;
struct const_iovec iov[3];
int iov_len;
const unsigned char *data;
- size_t size, skip_size, block_size;
+ size_t size, skip_size;
ssize_t ret;
int pos;
@@ -598,12 +605,9 @@ static off_t io_stream_copy(struct ostre
skip_size += iov[pos].iov_len;
start_offset = instream->v_offset;
- in_size -= instream->v_offset;
- while (in_size > 0) {
- block_size = I_MIN(foutstream->optimal_block_size, in_size);
- (void)i_stream_read_data(instream, &data, &size, block_size-1);
- in_size -= size;
-
+ for (;;) {
+ (void)i_stream_read_data(instream, &data, &size,
+ foutstream->optimal_block_size-1);
if (size == 0) {
/* all sent */
break;
@@ -721,30 +725,21 @@ static off_t o_stream_file_send_istream(
{
struct file_ostream *foutstream = (struct file_ostream *)outstream;
const struct stat *st;
- uoff_t in_size;
off_t ret;
- int in_fd, overlapping;
-
- st = i_stream_stat(instream, TRUE);
- if (st == NULL) {
- outstream->ostream.stream_errno = instream->stream_errno;
- return -1;
- }
+ int in_fd;
in_fd = i_stream_get_fd(instream);
- in_size = st->st_size;
- i_assert(instream->v_offset <= in_size);
outstream->ostream.stream_errno = 0;
- if (in_fd != foutstream->fd)
- overlapping = 0;
- else {
+ if (in_fd == foutstream->fd) {
/* copying data within same fd. we'll have to be careful with
seeks and overlapping writes. */
- if (in_size == (uoff_t)-1) {
- outstream->ostream.stream_errno = EINVAL;
+ st = i_stream_stat(instream, TRUE);
+ if (st == NULL) {
+ outstream->ostream.stream_errno = instream->stream_errno;
return -1;
}
+ i_assert(instream->v_offset <= (uoff_t)st->st_size);
ret = (off_t)outstream->ostream.offset -
(off_t)(instream->real_stream->abs_start_offset +
@@ -752,13 +747,17 @@ static off_t o_stream_file_send_istream(
if (ret == 0) {
/* copying data over itself. we don't really
need to do that, just fake it. */
- return in_size - instream->v_offset;
- }
- overlapping = ret < 0 ? -1 : 1;
- }
-
- if (!foutstream->no_sendfile && in_fd != -1 && overlapping <= 0) {
- ret = io_stream_sendfile(outstream, instream, in_fd, in_size);
+ return st->st_size - instream->v_offset;
+ }
+ if (ret > 0) {
+ /* overlapping */
+ return io_stream_copy_backwards(outstream, instream,
+ st->st_size);
+ }
+ }
+
+ if (!foutstream->no_sendfile && in_fd != -1 && instream->seekable) {
+ ret = io_stream_sendfile(outstream, instream, in_fd);
if (ret >= 0 || outstream->ostream.stream_errno != EINVAL)
return ret;
@@ -768,10 +767,7 @@ static off_t o_stream_file_send_istream(
foutstream->no_sendfile = TRUE;
}
- if (overlapping <= 0)
- return io_stream_copy(outstream, instream, in_size);
- else
- return io_stream_copy_backwards(outstream, instream, in_size);
+ return io_stream_copy(outstream, instream);
}
static struct file_ostream *
More information about the dovecot-cvs
mailing list