[dovecot-cvs] dovecot/src/lib Makefile.am, 1.39, 1.40 alarm-hup.c,
1.6, NONE alarm-hup.h, 1.1, NONE file-lock.c, 1.8,
1.9 iostream-internal.h, 1.4, 1.5 iostream.c, 1.5,
1.6 istream-data.c, 1.8, 1.9 istream-file.c, 1.17,
1.18 istream-limit.c, 1.6, 1.7 istream-mmap.c, 1.11,
1.12 istream.c, 1.19, 1.20 istream.h, 1.10, 1.11 lib.c, 1.10,
1.11 ostream-file.c, 1.27, 1.28 ostream-internal.h, 1.2,
1.3 ostream.c, 1.8, 1.9 ostream.h, 1.8, 1.9 strfuncs.c, 1.41,
1.42 strfuncs.h, 1.20, 1.21
cras at dovecot.org
cras at dovecot.org
Sun Aug 15 06:40:34 EEST 2004
- Previous message: [dovecot-cvs]
dovecot/src/lib-storage/index/mbox istream-raw-mbox.c, 1.16,
1.17 mbox-lock.c, 1.9, 1.10 mbox-save.c, 1.56, 1.57
- Next message: [dovecot-cvs] dovecot/src/pop3 client.c, 1.28, 1.29 client.h, 1.5,
1.6 commands.c, 1.19, 1.20
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Update of /home/cvs/dovecot/src/lib
In directory talvi:/tmp/cvs-serv20173/lib
Modified Files:
Makefile.am file-lock.c iostream-internal.h iostream.c
istream-data.c istream-file.c istream-limit.c istream-mmap.c
istream.c istream.h lib.c ostream-file.c ostream-internal.h
ostream.c ostream.h strfuncs.c strfuncs.h
Removed Files:
alarm-hup.c alarm-hup.h
Log Message:
We never do blocking reads/writes to network anymore. Changed imap and pop3
processes to use a single I/O loop.
Not much tested yet, and currently LIST/LSUB may eat too much memory and
APPEND eats all CPU.
Index: Makefile.am
===================================================================
RCS file: /home/cvs/dovecot/src/lib/Makefile.am,v
retrieving revision 1.39
retrieving revision 1.40
diff -u -d -r1.39 -r1.40
--- Makefile.am 30 Jul 2004 01:57:04 -0000 1.39
+++ Makefile.am 15 Aug 2004 03:40:31 -0000 1.40
@@ -1,7 +1,6 @@
noinst_LIBRARIES = liblib.a
liblib_a_SOURCES = \
- alarm-hup.c \
base64.c \
buffer.c \
byteorder.c \
@@ -68,7 +67,6 @@
write-full.c
noinst_HEADERS = \
- alarm-hup.h \
base64.h \
buffer.h \
byteorder.h \
--- alarm-hup.c DELETED ---
--- alarm-hup.h DELETED ---
Index: file-lock.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib/file-lock.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- file-lock.c 27 Apr 2004 20:25:52 -0000 1.8
+++ file-lock.c 15 Aug 2004 03:40:31 -0000 1.9
@@ -1,7 +1,6 @@
/* Copyright (c) 2002-2003 Timo Sirainen */
#include "lib.h"
-#include "alarm-hup.h"
#include "file-lock.h"
#include <time.h>
@@ -24,13 +23,13 @@
{
struct flock fl;
time_t timeout_time, now;
+ unsigned int next_alarm;
if (timeout == 0)
timeout_time = 0;
else {
- alarm_hup_init();
timeout_time = time(NULL) + timeout;
- alarm(timeout);
+ alarm(I_MIN(timeout, 5));
}
fl.l_type = lock_type;
@@ -39,21 +38,32 @@
fl.l_len = 0;
while (fcntl(fd, timeout != 0 ? F_SETLKW : F_SETLK, &fl) < 0) {
- if (timeout == 0 && (errno == EACCES || errno == EAGAIN))
+ if (timeout == 0 && (errno == EACCES || errno == EAGAIN)) {
+ alarm(0);
return 0;
+ }
- if (errno != EINTR)
+ if (errno != EINTR) {
+ alarm(0);
return -1;
+ }
now = time(NULL);
if (timeout != 0 && now >= timeout_time) {
errno = EAGAIN;
+ alarm(0);
return 0;
}
+ next_alarm = (timeout_time - now) % 5;
+ if (next_alarm == 0)
+ next_alarm = 5;
+ alarm(next_alarm);
+
if (callback != NULL)
callback(timeout_time - now, context);
}
+ alarm(0);
return 1;
}
Index: iostream-internal.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib/iostream-internal.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- iostream-internal.h 9 Nov 2003 18:26:25 -0000 1.4
+++ iostream-internal.h 15 Aug 2004 03:40:31 -0000 1.5
@@ -1,7 +1,7 @@
#ifndef __IOSTREAM_INTERNAL_H
#define __IOSTREAM_INTERNAL_H
-/* This file is private to IStream and OStream implementation */
+/* This file is private to input stream and output stream implementations */
struct _iostream {
pool_t pool;
@@ -10,8 +10,6 @@
void (*close)(struct _iostream *stream);
void (*destroy)(struct _iostream *stream);
void (*set_max_buffer_size)(struct _iostream *stream, size_t max_size);
- void (*set_blocking)(struct _iostream *stream, int timeout_msecs,
- void (*timeout_cb)(void *), void *context);
};
void _io_stream_init(pool_t pool, struct _iostream *stream);
@@ -19,13 +17,5 @@
void _io_stream_unref(struct _iostream *stream);
void _io_stream_close(struct _iostream *stream);
void _io_stream_set_max_buffer_size(struct _iostream *stream, size_t max_size);
-void _io_stream_set_blocking(struct _iostream *stream, int timeout_msecs,
- void (*timeout_cb)(void *), void *context);
-
-#define GET_TIMEOUT_TIME(fstream) \
- ((fstream)->timeout_msecs <= 0 ? 0 : \
- time(NULL) + ((fstream)->timeout_msecs / 1000))
-#define STREAM_IS_BLOCKING(fstream) \
- ((fstream)->timeout_msecs != 0)
#endif
Index: iostream.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib/iostream.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- iostream.c 26 Aug 2003 21:18:16 -0000 1.5
+++ iostream.c 15 Aug 2004 03:40:31 -0000 1.6
@@ -40,9 +40,3 @@
{
stream->set_max_buffer_size(stream, max_size);
}
-
-void _io_stream_set_blocking(struct _iostream *stream, int timeout_msecs,
- void (*timeout_cb)(void *), void *context)
-{
- stream->set_blocking(stream, timeout_msecs, timeout_cb, context);
-}
Index: istream-data.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib/istream-data.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- istream-data.c 27 Apr 2004 20:25:53 -0000 1.8
+++ istream-data.c 15 Aug 2004 03:40:31 -0000 1.9
@@ -16,13 +16,6 @@
{
}
-static void _set_blocking(struct _iostream *stream __attr_unused__,
- int timeout_msecs __attr_unused__,
- void (*timeout_cb)(void *) __attr_unused__,
- void *context __attr_unused__)
-{
-}
-
static ssize_t _read(struct _istream *stream __attr_unused__)
{
return -1;
@@ -51,7 +44,6 @@
stream->iostream.close = _close;
stream->iostream.destroy = _destroy;
stream->iostream.set_max_buffer_size = _set_max_buffer_size;
- stream->iostream.set_blocking = _set_blocking;
stream->read = _read;
stream->seek = _seek;
Index: istream-file.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib/istream-file.c,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -d -r1.17 -r1.18
--- istream-file.c 18 Jun 2004 00:32:25 -0000 1.17
+++ istream-file.c 15 Aug 2004 03:40:31 -0000 1.18
@@ -3,7 +3,6 @@
/* @UNSAFE: whole file */
#include "lib.h"
-#include "alarm-hup.h"
#include "istream-internal.h"
#include "network.h"
@@ -13,19 +12,12 @@
#define I_STREAM_MIN_SIZE 4096
-#define STREAM_IS_BLOCKING(fstream) \
- ((fstream)->timeout_msecs != 0)
-
struct file_istream {
struct _istream istream;
size_t max_buffer_size;
uoff_t skip_left;
- int timeout_msecs;
- void (*timeout_cb)(void *);
- void *timeout_context;
-
unsigned int file:1;
unsigned int autoclose_fd:1;
};
@@ -56,21 +48,6 @@
fstream->max_buffer_size = max_size;
}
-static void _set_blocking(struct _iostream *stream, int timeout_msecs,
- void (*timeout_cb)(void *), void *context)
-{
- struct file_istream *fstream = (struct file_istream *) stream;
-
- fstream->timeout_msecs = timeout_msecs;
- fstream->timeout_cb = timeout_cb;
- fstream->timeout_context = context;
-
- net_set_nonblock(fstream->istream.fd, timeout_msecs == 0);
-
- if (timeout_msecs != 0)
- alarm_hup_init();
-}
-
static void i_stream_grow_buffer(struct _istream *stream, size_t bytes)
{
struct file_istream *fstream = (struct file_istream *) stream;
@@ -105,7 +82,6 @@
static ssize_t _read(struct _istream *stream)
{
struct file_istream *fstream = (struct file_istream *) stream;
- time_t timeout_time;
size_t size;
ssize_t ret;
@@ -129,64 +105,52 @@
}
size = stream->buffer_size - stream->pos;
- timeout_time = GET_TIMEOUT_TIME(fstream);
ret = -1;
- do {
- if (ret == 0 && timeout_time > 0 && time(NULL) > timeout_time) {
- /* timeouted */
- if (fstream->timeout_cb != NULL)
- fstream->timeout_cb(fstream->timeout_context);
- stream->istream.stream_errno = EAGAIN;
- return -1;
- }
- if (fstream->file) {
- ret = pread(stream->fd,
- stream->w_buffer + stream->pos, size,
- stream->istream.v_offset +
- (stream->pos - stream->skip));
- } else {
- ret = read(stream->fd,
- stream->w_buffer + stream->pos, size);
- }
- if (ret == 0) {
- /* EOF */
- if (!fstream->file)
- stream->istream.disconnected = TRUE;
+ if (fstream->file) {
+ ret = pread(stream->fd, stream->w_buffer + stream->pos, size,
+ stream->istream.v_offset +
+ (stream->pos - stream->skip));
+ } else {
+ ret = read(stream->fd, stream->w_buffer + stream->pos, size);
+ }
+ if (ret == 0) {
+ /* EOF */
+ if (!fstream->file)
+ stream->istream.disconnected = TRUE;
+ return -1;
+ }
+
+ if (ret < 0) {
+ if (errno == ECONNRESET || errno == ETIMEDOUT) {
+ /* treat as disconnection */
+ stream->istream.disconnected = TRUE;
return -1;
}
- if (ret < 0) {
- if (errno == ECONNRESET || errno == ETIMEDOUT) {
- /* treat as disconnection */
- stream->istream.disconnected = TRUE;
- return -1;
- }
-
- if (errno == EINTR || errno == EAGAIN)
- ret = 0;
- else {
- stream->istream.stream_errno = errno;
- return -1;
- }
+ if (errno == EINTR || errno == EAGAIN)
+ ret = 0;
+ else {
+ stream->istream.stream_errno = errno;
+ return -1;
}
+ }
- if (ret > 0 && fstream->skip_left > 0) {
- i_assert(!fstream->file);
- i_assert(stream->skip == stream->pos);
+ if (ret > 0 && fstream->skip_left > 0) {
+ i_assert(!fstream->file);
+ i_assert(stream->skip == stream->pos);
- if (fstream->skip_left >= (size_t)ret) {
- fstream->skip_left -= ret;
- ret = 0;
- } else {
- ret -= fstream->skip_left;
- stream->pos += fstream->skip_left;
- stream->skip += fstream->skip_left;
- fstream->skip_left = 0;
- }
+ if (fstream->skip_left >= (size_t)ret) {
+ fstream->skip_left -= ret;
+ ret = 0;
+ } else {
+ ret -= fstream->skip_left;
+ stream->pos += fstream->skip_left;
+ stream->skip += fstream->skip_left;
+ fstream->skip_left = 0;
}
- } while (ret == 0 && STREAM_IS_BLOCKING(fstream));
+ }
stream->pos += ret;
return ret;
@@ -233,7 +197,6 @@
fstream->istream.iostream.close = _close;
fstream->istream.iostream.destroy = _destroy;
fstream->istream.iostream.set_max_buffer_size = _set_max_buffer_size;
- fstream->istream.iostream.set_blocking = _set_blocking;
fstream->istream.read = _read;
fstream->istream.seek = _seek;
Index: istream-limit.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib/istream-limit.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- istream-limit.c 7 Jul 2004 13:36:29 -0000 1.6
+++ istream-limit.c 15 Aug 2004 03:40:31 -0000 1.7
@@ -31,15 +31,6 @@
i_stream_set_max_buffer_size(lstream->input, max_size);
}
-static void _set_blocking(struct _iostream *stream, int timeout_msecs,
- void (*timeout_cb)(void *), void *context)
-{
- struct limit_istream *lstream = (struct limit_istream *) stream;
-
- i_stream_set_blocking(lstream->input, timeout_msecs,
- timeout_cb, context);
-}
-
static ssize_t _read(struct _istream *stream)
{
struct limit_istream *lstream = (struct limit_istream *) stream;
@@ -118,7 +109,6 @@
lstream->istream.iostream.close = _close;
lstream->istream.iostream.destroy = _destroy;
lstream->istream.iostream.set_max_buffer_size = _set_max_buffer_size;
- lstream->istream.iostream.set_blocking = _set_blocking;
lstream->istream.read = _read;
lstream->istream.seek = _seek;
Index: istream-mmap.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib/istream-mmap.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- istream-mmap.c 19 Jun 2004 20:29:08 -0000 1.11
+++ istream-mmap.c 15 Aug 2004 03:40:31 -0000 1.12
@@ -68,14 +68,6 @@
}
}
-static void _set_blocking(struct _iostream *stream __attr_unused__,
- int timeout_msecs __attr_unused__,
- void (*timeout_cb)(void *) __attr_unused__,
- void *context __attr_unused__)
-{
- /* we never block */
-}
-
static ssize_t _read(struct _istream *stream)
{
struct mmap_istream *mstream = (struct mmap_istream *) stream;
@@ -140,6 +132,7 @@
}
stream->pos = stream->buffer_size;
+ i_assert(stream->pos - stream->skip != 0);
return stream->pos - stream->skip;
}
@@ -201,7 +194,6 @@
mstream->istream.iostream.close = _close;
mstream->istream.iostream.destroy = _destroy;
mstream->istream.iostream.set_max_buffer_size = _set_max_buffer_size;
- mstream->istream.iostream.set_blocking = _set_blocking;
mstream->istream.read = _read;
mstream->istream.seek = _seek;
Index: istream.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib/istream.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -d -r1.19 -r1.20
--- istream.c 2 Jul 2004 15:36:25 -0000 1.19
+++ istream.c 15 Aug 2004 03:40:31 -0000 1.20
@@ -32,13 +32,6 @@
max_size);
}
-void i_stream_set_blocking(struct istream *stream, int timeout_msecs,
- void (*timeout_cb)(void *), void *context)
-{
- _io_stream_set_blocking(&stream->real_stream->iostream, timeout_msecs,
- timeout_cb, context);
-}
-
ssize_t i_stream_read(struct istream *stream)
{
struct _istream *_stream = stream->real_stream;
Index: istream.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib/istream.h,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- istream.h 18 Jun 2004 00:32:25 -0000 1.10
+++ istream.h 15 Aug 2004 03:40:31 -0000 1.11
@@ -37,12 +37,6 @@
/* Change the maximum size for stream's input buffer to grow. Useful only
for buffered streams (currently only file). */
void i_stream_set_max_buffer_size(struct istream *stream, size_t max_size);
-/* Makes reads blocking until at least one byte is read. timeout_cb is
- called if nothing is read in specified time. Setting timeout_msecs to 0
- makes it non-blocking. This call changes non-blocking state of file
- descriptor. */
-void i_stream_set_blocking(struct istream *stream, int timeout_msecs,
- void (*timeout_cb)(void *), void *context);
/* Returns number of bytes read if read was ok, -1 if EOF or error, -2 if the
input buffer is full. */
Index: lib.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib/lib.c,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- lib.c 26 Aug 2003 21:18:16 -0000 1.10
+++ lib.c 15 Aug 2004 03:40:31 -0000 1.11
@@ -1,7 +1,6 @@
/* Copyright (c) 2001-2003 Timo Sirainen */
#include "lib.h"
-#include "alarm-hup.h"
#include "hostpid.h"
#include <stdlib.h>
@@ -29,8 +28,6 @@
void lib_deinit(void)
{
- alarm_hup_deinit(); /* doesn't harm even if init is never called */
-
imem_deinit();
data_stack_deinit();
failures_deinit();
Index: ostream-file.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib/ostream-file.c,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -d -r1.27 -r1.28
--- ostream-file.c 28 Jun 2004 16:13:59 -0000 1.27
+++ ostream-file.c 15 Aug 2004 03:40:31 -0000 1.28
@@ -3,7 +3,6 @@
/* @UNSAFE: whole file */
#include "lib.h"
-#include "alarm-hup.h"
#include "ioloop.h"
#include "write-full.h"
#include "network.h"
@@ -39,10 +38,6 @@
size_t buffer_size, max_buffer_size, optimal_block_size;
size_t head, tail; /* first unsent/unused byte */
- int timeout_msecs;
- void (*timeout_cb)(void *);
- void *timeout_context;
-
unsigned int full:1; /* if head == tail, is buffer empty or full? */
unsigned int file:1;
unsigned int corked:1;
@@ -51,6 +46,8 @@
unsigned int autoclose_fd:1;
};
+static void stream_send_io(void *context);
+
static void stream_closed(struct file_ostream *fstream)
{
if (fstream->autoclose_fd && fstream->fd != -1) {
@@ -69,7 +66,7 @@
static void _close(struct _iostream *stream)
{
- struct file_ostream *fstream = (struct file_ostream *) stream;
+ struct file_ostream *fstream = (struct file_ostream *)stream;
/* flush output before really closing it */
o_stream_flush(&fstream->ostream.ostream);
@@ -79,65 +76,18 @@
static void _destroy(struct _iostream *stream)
{
- struct file_ostream *fstream = (struct file_ostream *) stream;
+ struct file_ostream *fstream = (struct file_ostream *)stream;
p_free(fstream->ostream.iostream.pool, fstream->buffer);
}
static void _set_max_buffer_size(struct _iostream *stream, size_t max_size)
{
- struct file_ostream *fstream = (struct file_ostream *) stream;
+ struct file_ostream *fstream = (struct file_ostream *)stream;
fstream->max_buffer_size = max_size;
}
-static void _set_blocking(struct _iostream *stream, int timeout_msecs,
- void (*timeout_cb)(void *), void *context)
-{
- struct file_ostream *fstream = (struct file_ostream *) stream;
-
- fstream->timeout_msecs = timeout_msecs;
- fstream->timeout_cb = timeout_cb;
- fstream->timeout_context = context;
-
- if (!fstream->file)
- net_set_nonblock(fstream->fd, timeout_msecs == 0);
-
- if (timeout_msecs != 0)
- alarm_hup_init();
-}
-
-static void _cork(struct _ostream *stream)
-{
- struct file_ostream *fstream = (struct file_ostream *) stream;
-
- if (!fstream->corked) {
- if (!fstream->no_socket_cork) {
- if (net_set_cork(fstream->fd, TRUE) < 0)
- fstream->no_socket_cork = TRUE;
- }
- fstream->corked = TRUE;
- }
-}
-
-static void update_iovec(struct iovec *iov, unsigned int iov_size, size_t size)
-{
- while (size > 0) {
- i_assert(iov_size > 0);
-
- if ((size_t)iov->iov_len <= size) {
- size -= iov->iov_len;
- iov->iov_base = NULL;
- iov->iov_len = 0;
- } else {
- iov->iov_base = (void *)((char *)iov->iov_base + size);
- iov->iov_len -= size;
- size = 0;
- }
- iov++; iov_size--;
- }
-}
-
static void update_buffer(struct file_ostream *fstream, size_t size)
{
size_t used;
@@ -175,22 +125,15 @@
}
/* NOTE: modifies iov */
-static ssize_t
-o_stream_writev(struct file_ostream *fstream, struct iovec *iov, int iov_size)
+static ssize_t o_stream_writev(struct file_ostream *fstream,
+ const struct const_iovec *iov, int iov_size)
{
ssize_t ret;
- while (iov->iov_len == 0 && iov_size > 0) {
- iov++;
- iov_size--;
- }
-
- i_assert(iov_size > 0);
-
if (iov_size == 1)
ret = write(fstream->fd, iov->iov_base, iov->iov_len);
else
- ret = writev(fstream->fd, iov, iov_size);
+ ret = writev(fstream->fd, (const struct iovec *)iov, iov_size);
if (ret < 0) {
if (errno == EAGAIN || errno == EINTR)
@@ -200,107 +143,81 @@
return -1;
}
- update_iovec(iov, iov_size, ret);
- update_buffer(fstream, ret);
-
return ret;
}
/* returns how much of vector was used */
static int o_stream_fill_iovec(struct file_ostream *fstream,
- struct iovec iov[2])
+ struct const_iovec iov[2])
{
if (IS_STREAM_EMPTY(fstream))
return 0;
if (fstream->head < fstream->tail) {
- iov[0].iov_base = (void *)(fstream->buffer + fstream->head);
+ iov[0].iov_base = fstream->buffer + fstream->head;
iov[0].iov_len = fstream->tail - fstream->head;
return 1;
} else {
- iov[0].iov_base = (void *)(fstream->buffer + fstream->head);
+ iov[0].iov_base = fstream->buffer + fstream->head;
iov[0].iov_len = fstream->buffer_size - fstream->head;
if (fstream->tail == 0)
return 1;
else {
- iov[1].iov_base = (void *)fstream->buffer;
+ iov[1].iov_base = fstream->buffer;
iov[1].iov_len = fstream->tail;
return 2;
}
}
}
-static int o_stream_send_blocking(struct file_ostream *fstream,
- const void *data, size_t size)
+static int buffer_flush(struct file_ostream *fstream)
{
- time_t timeout_time;
- struct iovec iov[3];
- int iov_len, first;
+ struct const_iovec iov[2];
+ int iov_len;
+ ssize_t ret;
iov_len = o_stream_fill_iovec(fstream, iov);
- if (size > 0) {
- iov[iov_len].iov_base = (void *) data;
- iov[iov_len].iov_len = size;
- iov_len++;
- }
-
- first = TRUE;
-
- timeout_time = GET_TIMEOUT_TIME(fstream);
- while (iov[iov_len-1].iov_len != 0) {
- if (first)
- first = FALSE;
- else if (timeout_time > 0 && time(NULL) > timeout_time) {
- /* timeouted */
- if (fstream->timeout_cb != NULL)
- fstream->timeout_cb(fstream->timeout_context);
- fstream->ostream.ostream.stream_errno = EAGAIN;
+ if (iov_len > 0) {
+ ret = o_stream_writev(fstream, iov, iov_len);
+ if (ret < 0)
return -1;
- }
- if (o_stream_writev(fstream, iov, iov_len) < 0)
- return -1;
+ update_buffer(fstream, ret);
}
- return 1;
+ return IS_STREAM_EMPTY(fstream) ? 1 : 0;
}
-static int buffer_flush(struct file_ostream *fstream)
+static void _cork(struct _ostream *stream, int set)
{
- struct iovec iov[2];
- int iov_len;
+ struct file_ostream *fstream = (struct file_ostream *)stream;
- if (!IS_STREAM_EMPTY(fstream)) {
- iov_len = o_stream_fill_iovec(fstream, iov);
- if (o_stream_writev(fstream, iov, iov_len) < 0)
- return -1;
+ if (fstream->corked != set) {
+ if (!fstream->no_socket_cork) {
+ if (net_set_cork(fstream->fd, set) < 0)
+ fstream->no_socket_cork = TRUE;
+ }
+ fstream->corked = set;
- if (!IS_STREAM_EMPTY(fstream)) {
- if (o_stream_send_blocking(fstream, NULL, 0) < 0)
- return -1;
+ if (set && fstream->io != NULL) {
+ io_remove(fstream->io);
+ fstream->io = NULL;
+ } else if (!set && fstream->io == NULL) {
+ if (fstream->file)
+ buffer_flush(fstream);
+ else {
+ fstream->io = io_add(fstream->fd, IO_WRITE,
+ stream_send_io, fstream);
+ }
}
}
-
- return 1;
}
static int _flush(struct _ostream *stream)
{
struct file_ostream *fstream = (struct file_ostream *) stream;
- int ret;
-
- ret = buffer_flush(fstream);
-
- if (fstream->corked) {
- /* remove cork */
- if (!fstream->no_socket_cork) {
- if (net_set_cork(fstream->fd, FALSE) < 0)
- i_error("net_set_cork() failed: %m");
- }
- fstream->corked = FALSE;
- }
- return ret;
+ return buffer_flush(fstream);
}
static size_t get_unused_space(struct file_ostream *fstream)
@@ -317,25 +234,16 @@
}
}
-static int _have_space(struct _ostream *stream, size_t size)
+static size_t _get_used_size(struct _ostream *stream)
{
- struct file_ostream *fstream = (struct file_ostream *) stream;
- size_t unused;
-
- unused = get_unused_space(fstream);
- if (size <= unused)
- return 1;
-
- if (fstream->max_buffer_size == 0)
- return 1;
+ struct file_ostream *fstream = (struct file_ostream *)stream;
- unused += (fstream->max_buffer_size - fstream->buffer_size);
- return size <= unused ? 1 : 0;
+ return fstream->buffer_size - get_unused_space(fstream);
}
static int _seek(struct _ostream *stream, uoff_t offset)
{
- struct file_ostream *fstream = (struct file_ostream *) stream;
+ struct file_ostream *fstream = (struct file_ostream *)stream;
off_t ret;
if (offset > OFF_T_MAX) {
@@ -367,17 +275,16 @@
size_t size, head_size;
size = nearest_power(fstream->buffer_size + bytes);
- if (fstream->max_buffer_size != 0) {
- if (size > fstream->max_buffer_size) {
- /* limit the size */
- size = fstream->max_buffer_size;
- } else if (fstream->corked) {
- /* use the largest possible buffer with corking */
- size = fstream->max_buffer_size;
- }
+ if (size > fstream->max_buffer_size) {
+ /* limit the size */
+ size = fstream->max_buffer_size;
+ } else if (fstream->corked) {
+ /* use optimal buffer size with corking */
+ size = I_MIN(fstream->optimal_block_size,
+ fstream->max_buffer_size);
}
- if (size == fstream->buffer_size)
+ if (size <= fstream->buffer_size)
return;
fstream->buffer = p_realloc(fstream->ostream.iostream.pool,
@@ -405,18 +312,18 @@
static void stream_send_io(void *context)
{
struct file_ostream *fstream = context;
- struct iovec iov[2];
- int iov_len;
- iov_len = o_stream_fill_iovec(fstream, iov);
+ if (fstream->ostream.callback != NULL)
+ fstream->ostream.callback(fstream->ostream.context);
+ else {
+ if (_flush(&fstream->ostream) <= 0)
+ return;
+ }
- if (iov_len == 0 || o_stream_writev(fstream, iov, iov_len) < 0 ||
- iov[iov_len-1].iov_len == 0) {
- /* error / all sent */
- if (fstream->io != NULL) {
- io_remove(fstream->io);
- fstream->io = NULL;
- }
+ if (IS_STREAM_EMPTY(fstream) && fstream->io != NULL) {
+ /* all sent */
+ io_remove(fstream->io);
+ fstream->io = NULL;
}
}
@@ -455,48 +362,64 @@
fstream);
}
- i_assert(!STREAM_IS_BLOCKING(fstream) || sent == size);
return sent;
}
-static ssize_t _send(struct _ostream *stream, const void *data, size_t size)
+static ssize_t _sendv(struct _ostream *stream, const struct const_iovec *iov,
+ size_t iov_count)
{
- struct file_ostream *fstream = (struct file_ostream *) stream;
- struct iovec iov;
+ struct file_ostream *fstream = (struct file_ostream *)stream;
+ size_t i, size, added, optimal_size;
ssize_t ret = 0;
- i_assert(size <= SSIZE_T_MAX);
-
stream->ostream.stream_errno = 0;
- /* never try sending immediately if fd is blocking,
- so we don't need to deal with timeout issues here */
- if (IS_STREAM_EMPTY(fstream) && !STREAM_IS_BLOCKING(fstream) &&
- (!fstream->corked || !_have_space(stream, size))) {
- iov.iov_base = (void *) data;
- iov.iov_len = size;
-
- ret = o_stream_writev(fstream, &iov, 1);
- if (ret > 0)
- stream->ostream.offset += ret;
-
- if (ret < 0 || (size_t)ret == size)
- return ret;
+ for (i = 0, size = 0; i < iov_count; i++)
+ size += iov[i].iov_len;
- data = (const char *) data + ret;
- size -= ret;
+ if (size > get_unused_space(fstream)) {
+ if (_flush(stream) < 0)
+ return -1;
}
- if (!_have_space(stream, size) && STREAM_IS_BLOCKING(fstream)) {
- /* send it blocking */
- if (o_stream_send_blocking(fstream, data, size) < 0)
+ optimal_size = I_MIN(fstream->optimal_block_size,
+ fstream->max_buffer_size);
+ if (IS_STREAM_EMPTY(fstream) &&
+ (!fstream->corked || size >= optimal_size)) {
+ /* send immediately */
+ ret = o_stream_writev(fstream, iov, iov_count);
+ if (ret < 0)
return -1;
- ret += (ssize_t)size;
- } else {
- /* buffer it, at least partly */
- ret += (ssize_t)o_stream_add(fstream, data, size);
+
+ size = ret;
+ while (size > 0 && size >= iov[0].iov_len) {
+ size -= iov[0].iov_len;
+ iov++;
+ iov_count--;
+ }
+
+ if (iov_count > 0) {
+ added = o_stream_add(fstream,
+ CONST_PTR_OFFSET(iov[0].iov_base, size),
+ iov[0].iov_len - size);
+ if (added != iov[0].iov_len - size) {
+ /* buffer full */
+ stream->ostream.offset += added;
+ return added;
+ }
+
+ iov++;
+ iov_count--;
+ }
}
+ /* buffer it, at least partly */
+ for (i = 0; i < iov_count; i++) {
+ added = o_stream_add(fstream, iov[i].iov_base, iov[i].iov_len);
+ ret += added;
+ if (added != iov[i].iov_len)
+ break;
+ }
stream->ostream.offset += ret;
return ret;
}
@@ -505,64 +428,35 @@
struct istream *instream,
int in_fd, uoff_t in_size)
{
- struct file_ostream *foutstream = (struct file_ostream *) outstream;
- time_t timeout_time;
+ struct file_ostream *foutstream = (struct file_ostream *)outstream;
uoff_t start_offset;
uoff_t offset, send_size, v_offset;
ssize_t ret;
- int first;
-
- /* set timeout time before hflushing existing buffer which may block */
- timeout_time = GET_TIMEOUT_TIME(foutstream);
- start_offset = instream->v_offset;
/* flush out any data in buffer */
- if (buffer_flush(foutstream) < 0)
- return -1;
-
- v_offset = instream->v_offset;
+ if ((ret = buffer_flush(foutstream)) <= 0)
+ return ret;
- first = TRUE;
+ start_offset = v_offset = instream->v_offset;
do {
- if (first)
- first = FALSE;
- else if (timeout_time > 0 && time(NULL) > timeout_time) {
- /* timeouted */
- if (foutstream->timeout_cb != NULL) {
- foutstream->timeout_cb(
- foutstream->timeout_context);
- }
- outstream->ostream.stream_errno = EAGAIN;
- ret = -1;
- break;
- }
-
offset = instream->real_stream->abs_start_offset + v_offset;
send_size = in_size - v_offset;
ret = safe_sendfile(foutstream->fd, in_fd, &offset,
MAX_SSIZE_T(send_size));
if (ret <= 0) {
- if (ret == 0) {
- /* EOF */
- break;
- }
-
- if (errno != EINTR && errno != EAGAIN) {
- outstream->ostream.stream_errno = errno;
- if (errno != EINVAL) {
- /* close only if error wasn't because
- sendfile() isn't supported */
- stream_closed(foutstream);
- }
+ if (ret == 0 || errno == EINTR || errno == EAGAIN) {
+ ret = 0;
break;
}
- ret = 0;
- if (!STREAM_IS_BLOCKING(foutstream)) {
- /* don't block */
- break;
+ outstream->ostream.stream_errno = errno;
+ if (errno != EINVAL) {
+ /* close only if error wasn't because
+ sendfile() isn't supported */
+ stream_closed(foutstream);
}
+ break;
}
v_offset += ret;
@@ -576,17 +470,15 @@
static off_t io_stream_copy(struct _ostream *outstream,
struct istream *instream, uoff_t in_size)
{
- struct file_ostream *foutstream = (struct file_ostream *) outstream;
- time_t timeout_time;
+ struct file_ostream *foutstream = (struct file_ostream *)outstream;
uoff_t start_offset;
- struct iovec iov[3];
+ struct const_iovec iov[3];
int iov_len;
const unsigned char *data;
size_t size, skip_size, block_size;
ssize_t ret;
int pos;
- timeout_time = GET_TIMEOUT_TIME(foutstream);
iov_len = o_stream_fill_iovec(foutstream, iov);
skip_size = 0;
@@ -609,17 +501,12 @@
iov[pos].iov_len = size;
ret = o_stream_writev(foutstream, iov, iov_len);
- if (ret < 0) {
- /* error */
+ if (ret < 0)
return -1;
- }
-
- if (ret == 0 && !STREAM_IS_BLOCKING(foutstream)) {
- /* don't block */
- break;
- }
if (skip_size > 0) {
+ update_buffer(foutstream, ret);
+
if ((size_t)ret < skip_size) {
skip_size -= ret;
ret = 0;
@@ -629,27 +516,12 @@
}
}
outstream->ostream.offset += ret;
+ i_stream_skip(instream, ret);
- if (timeout_time > 0 && time(NULL) > timeout_time) {
- /* timeouted */
- if (foutstream->timeout_cb != NULL) {
- foutstream->timeout_cb(
- foutstream->timeout_context);
- }
- outstream->ostream.stream_errno = EAGAIN;
- return -1;
- }
-
- i_stream_skip(instream, size - iov[pos].iov_len);
- iov_len--;
+ if ((size_t)ret != iov[pos].iov_len)
+ break;
- /* if we already sent the iov[0] and iov[1], we
- can just remove them from future calls */
- while (iov_len > 0 && iov[0].iov_len == 0) {
- iov[0] = iov[1];
- if (iov_len > 1) iov[1] = iov[2];
- iov_len--;
- }
+ iov_len = 0;
}
return (off_t) (instream->v_offset - start_offset);
@@ -658,8 +530,7 @@
static off_t io_stream_copy_backwards(struct _ostream *outstream,
struct istream *instream, uoff_t in_size)
{
- struct file_ostream *foutstream = (struct file_ostream *) outstream;
- time_t timeout_time;
+ struct file_ostream *foutstream = (struct file_ostream *)outstream;
uoff_t in_start_offset, in_offset, in_limit, out_offset;
const unsigned char *data;
size_t buffer_size, size, read_size;
@@ -667,8 +538,6 @@
i_assert(IS_STREAM_EMPTY(foutstream));
- timeout_time = GET_TIMEOUT_TIME(foutstream);
-
/* figure out optimal buffer size */
buffer_size = instream->real_stream->buffer_size;
if (buffer_size == 0 || buffer_size > foutstream->buffer_size) {
@@ -705,7 +574,7 @@
size = read_size;
if (instream->mmaped) {
/* we'll have to write it through
- buffer of the file gets corrupted */
+ buffer or the file gets corrupted */
i_assert(size <=
foutstream->buffer_size);
memcpy(foutstream->buffer, data, size);
@@ -726,21 +595,11 @@
return -1;
ret = write_full(foutstream->fd, data, size);
- if (ret < 0) {
+ if (ret < 0) {
/* error */
outstream->ostream.stream_errno = errno;
return -1;
}
-
- if (timeout_time > 0 && time(NULL) > timeout_time) {
- /* timeouted */
- if (foutstream->timeout_cb != NULL) {
- foutstream->timeout_cb(
- foutstream->timeout_context);
- }
- outstream->ostream.stream_errno = EAGAIN;
- return -1;
- }
}
return (off_t) (in_size - in_start_offset);
@@ -748,7 +607,7 @@
static off_t _send_istream(struct _ostream *outstream, struct istream *instream)
{
- struct file_ostream *foutstream = (struct file_ostream *) outstream;
+ struct file_ostream *foutstream = (struct file_ostream *)outstream;
uoff_t in_size;
off_t ret;
int in_fd, overlapping;
@@ -814,13 +673,12 @@
fstream->ostream.iostream.close = _close;
fstream->ostream.iostream.destroy = _destroy;
fstream->ostream.iostream.set_max_buffer_size = _set_max_buffer_size;
- fstream->ostream.iostream.set_blocking = _set_blocking;
fstream->ostream.cork = _cork;
fstream->ostream.flush = _flush;
- fstream->ostream.have_space = _have_space;
+ fstream->ostream.get_used_size = _get_used_size;
fstream->ostream.seek = _seek;
- fstream->ostream.send = _send;
+ fstream->ostream.sendv = _sendv;
fstream->ostream.send_istream = _send_istream;
ostream = _o_stream_create(&fstream->ostream, pool);
@@ -842,8 +700,6 @@
if (S_ISREG(st.st_mode)) {
fstream->no_socket_cork = TRUE;
fstream->file = TRUE;
-
- o_stream_set_blocking(ostream, -1, 0, NULL);
}
}
#ifndef HAVE_LINUX_SENDFILE
Index: ostream-internal.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib/ostream-internal.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- ostream-internal.h 5 Jan 2003 13:09:51 -0000 1.2
+++ ostream-internal.h 15 Aug 2004 03:40:31 -0000 1.3
@@ -9,16 +9,20 @@
struct _iostream iostream;
/* methods: */
- void (*cork)(struct _ostream *stream);
+ void (*cork)(struct _ostream *stream, int set);
int (*flush)(struct _ostream *stream);
- int (*have_space)(struct _ostream *stream, size_t size);
+ size_t (*get_used_size)(struct _ostream *stream);
int (*seek)(struct _ostream *stream, uoff_t offset);
- ssize_t (*send)(struct _ostream *stream, const void *data, size_t size);
+ ssize_t (*sendv)(struct _ostream *stream, const struct const_iovec *iov,
+ size_t iov_count);
off_t (*send_istream)(struct _ostream *outstream,
struct istream *instream);
/* data: */
struct ostream ostream;
+
+ io_callback_t *callback;
+ void *context;
};
struct ostream *_o_stream_create(struct _ostream *_stream, pool_t pool);
Index: ostream.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib/ostream.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- ostream.c 26 Aug 2003 21:18:16 -0000 1.8
+++ ostream.c 15 Aug 2004 03:40:31 -0000 1.9
@@ -20,27 +20,39 @@
stream->closed = TRUE;
}
+void o_stream_set_flush_callback(struct ostream *stream,
+ io_callback_t *callback, void *context)
+{
+ struct _ostream *_stream = stream->real_stream;
+
+ _stream->callback = callback;
+ _stream->context = context;
+}
+
void o_stream_set_max_buffer_size(struct ostream *stream, size_t max_size)
{
_io_stream_set_max_buffer_size(&stream->real_stream->iostream,
max_size);
}
-void o_stream_set_blocking(struct ostream *stream, int timeout_msecs,
- void (*timeout_cb)(void *), void *context)
+void o_stream_cork(struct ostream *stream)
{
- _io_stream_set_blocking(&stream->real_stream->iostream, timeout_msecs,
- timeout_cb, context);
+ struct _ostream *_stream = stream->real_stream;
+
+ if (stream->closed)
+ return;
+
+ _stream->cork(_stream, TRUE);
}
-void o_stream_cork(struct ostream *stream)
+void o_stream_uncork(struct ostream *stream)
{
struct _ostream *_stream = stream->real_stream;
if (stream->closed)
return;
- _stream->cork(_stream);
+ _stream->cork(_stream, FALSE);
}
int o_stream_flush(struct ostream *stream)
@@ -53,11 +65,11 @@
return _stream->flush(_stream);
}
-int o_stream_have_space(struct ostream *stream, size_t size)
+size_t o_stream_get_buffer_used_size(struct ostream *stream)
{
struct _ostream *_stream = stream->real_stream;
- return _stream->have_space(_stream, size);
+ return _stream->get_used_size(_stream);
}
int o_stream_seek(struct ostream *stream, uoff_t offset)
@@ -70,20 +82,28 @@
return _stream->seek(_stream, offset);
}
-ssize_t o_stream_send(struct ostream *stream, const void *data, size_t size)
+int o_stream_send(struct ostream *stream, const void *data, size_t size)
+{
+ struct const_iovec iov;
+
+ iov.iov_base = data;
+ iov.iov_len = size;
+
+ return o_stream_sendv(stream, &iov, 1);
+}
+
+ssize_t o_stream_sendv(struct ostream *stream, const struct const_iovec *iov,
+ size_t iov_count)
{
struct _ostream *_stream = stream->real_stream;
if (stream->closed)
return -1;
- if (size == 0)
- return 0;
-
- return _stream->send(_stream, data, size);
+ return _stream->sendv(_stream, iov, iov_count);
}
-ssize_t o_stream_send_str(struct ostream *stream, const char *str)
+int o_stream_send_str(struct ostream *stream, const char *str)
{
return o_stream_send(stream, str, strlen(str));
}
Index: ostream.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib/ostream.h,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- ostream.h 28 Jun 2004 16:13:59 -0000 1.8
+++ ostream.h 15 Aug 2004 03:40:31 -0000 1.9
@@ -1,6 +1,8 @@
#ifndef __OSTREAM_H
#define __OSTREAM_H
+#include "ioloop.h"
+
struct ostream {
uoff_t offset;
@@ -24,30 +26,29 @@
/* Mark the stream closed. Nothing will be sent after this call. */
void o_stream_close(struct ostream *stream);
+/* Set IO_WRITE callback. Default will just try to flush the output. */
+void o_stream_set_flush_callback(struct ostream *stream,
+ io_callback_t *callback, void *context);
/* Change the maximum size for stream's output buffer to grow. */
void o_stream_set_max_buffer_size(struct ostream *stream, size_t max_size);
-/* Stream is made to be flushed out whenever it gets full (assumes max_size
- is already set), ie. writes will never be partial. Also makes any blocking
- writes to fail after specified timeout, calling timeout_cb if it's
- set. This call changes non-blocking state of file descriptor. */
-void o_stream_set_blocking(struct ostream *stream, int timeout_msecs,
- void (*timeout_cb)(void *), void *context);
/* Delays sending as far as possible, writing only full buffers. Also sets
- TCP_CORK on if supported. o_stream_flush() removes the cork. */
+ TCP_CORK on if supported. */
void o_stream_cork(struct ostream *stream);
+void o_stream_uncork(struct ostream *stream);
/* Flush the output stream, blocks until everything is sent.
Returns 1 if ok, -1 if error. */
int o_stream_flush(struct ostream *stream);
-/* Returns 1 if specified amount of data currently fits into stream's output
- buffer, 0 if not. */
-int o_stream_have_space(struct ostream *stream, size_t size);
+/* Returns number of bytes currently in buffer. */
+size_t o_stream_get_buffer_used_size(struct ostream *stream);
/* Seek to specified position from beginning of file. This works only for
files. Returns 1 if successful, -1 if error. */
int o_stream_seek(struct ostream *stream, uoff_t offset);
-/* Returns number of bytes sent or buffered, or -1 if disconnected */
+/* Returns number of bytes sent, -1 = error */
ssize_t o_stream_send(struct ostream *stream, const void *data, size_t size);
+ssize_t o_stream_sendv(struct ostream *stream, const struct const_iovec *iov,
+ size_t iov_count);
ssize_t o_stream_send_str(struct ostream *stream, const char *str);
/* Send data from input stream. Returns number of bytes sent, or -1 if error.
Note that this function may block if either instream or outstream is
Index: strfuncs.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib/strfuncs.c,v
retrieving revision 1.41
retrieving revision 1.42
diff -u -d -r1.41 -r1.42
--- strfuncs.c 18 Jul 2004 01:44:59 -0000 1.41
+++ strfuncs.c 15 Aug 2004 03:40:31 -0000 1.42
@@ -478,6 +478,13 @@
return strcasecmp(key, *member);
}
+int strcasecmp_p(const void *p1, const void *p2)
+{
+ const char *const *s1 = p1, *const *s2 = p2;
+
+ return strcasecmp(*s1, *s2);
+}
+
static const char **_strsplit(const char *data, const char *separators,
int spaces)
{
Index: strfuncs.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib/strfuncs.h,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -d -r1.20 -r1.21
--- strfuncs.h 20 Jun 2004 06:14:44 -0000 1.20
+++ strfuncs.h 15 Aug 2004 03:40:31 -0000 1.21
@@ -56,6 +56,7 @@
int null_strcmp(const char *s1, const char *s2);
int memcasecmp(const void *p1, const void *p2, size_t size);
int bsearch_strcasecmp(const void *p1, const void *p2);
+int strcasecmp_p(const void *p1, const void *p2);
/* seprators is an array of separator characters, not a separator string. */
const char **t_strsplit(const char *data, const char *separators);
- Previous message: [dovecot-cvs]
dovecot/src/lib-storage/index/mbox istream-raw-mbox.c, 1.16,
1.17 mbox-lock.c, 1.9, 1.10 mbox-save.c, 1.56, 1.57
- Next message: [dovecot-cvs] dovecot/src/pop3 client.c, 1.28, 1.29 client.h, 1.5,
1.6 commands.c, 1.19, 1.20
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the dovecot-cvs
mailing list