On Mon, 2 Jul 2001, Brian Pane wrote:
> >On Mon, 2 Jul 2001, Brian Pane wrote:
> >
> >>then it should be possible to eliminate a system call by not doing the
> >>initial read before the select.
> >>
> Here's a patch that disables the read before the select, but only for
> the HTTP client socket.
hey brian, i think i prefer the approach below instead. but i haven't
been able to test this patch because my top-of-tree httpd-2.0 won't build
with top-of-tree apr/apr-util.
the approach i'm using doesn't require any changes to any applications --
it just implements the heuristic i mentioned earlier. whenever a read()
returns an incomplete buffer assume we want to select() first before
read()ing again (and all of this only if the socket is non-blocking).
-dean
Index: srclib/apr/include/apr_network_io.h
===================================================================
RCS file: /home/cvs/apr/include/apr_network_io.h,v
retrieving revision 1.102
diff -u -r1.102 apr_network_io.h
--- srclib/apr/include/apr_network_io.h 2001/05/02 02:32:44 1.102
+++ srclib/apr/include/apr_network_io.h 2001/07/07 18:18:14
@@ -102,6 +102,12 @@
* APR_TCP_NODELAY should be turned on
* again when NOPUSH is turned off
*/
+/* an internal flag. this is set on non-blocking sockets
+ * (APR_SO_TIMEOUT != 0) on which the previous read() did not fill a
+ * buffer completely. the next apr_recv() will first call select()/poll()
+ * rather than going straight into read().
+ */
+#define APR_INCOMPLETE_READ 4096
#define APR_POLLIN 0x001
#define APR_POLLPRI 0x002
Index: srclib/apr/network_io/unix/sendrecv.c
===================================================================
RCS file: /home/cvs/apr/network_io/unix/sendrecv.c,v
retrieving revision 1.65
diff -u -r1.65 sendrecv.c
--- srclib/apr/network_io/unix/sendrecv.c 2001/05/03 22:38:00 1.65
+++ srclib/apr/network_io/unix/sendrecv.c 2001/07/07 18:18:16
@@ -125,14 +125,21 @@
apr_status_t apr_recv(apr_socket_t *sock, char *buf, apr_size_t *len)
{
ssize_t rv;
-
+ apr_status_t arv;
+
+ if (sock->netmask & APR_INCOMPLETE_READ) {
+ sock->netmask &= ~APR_INCOMPLETE_READ;
+ goto do_select;
+ }
+
do {
- rv = read(sock->socketdes, buf, (*len));
+ rv = read(sock->socketdes, buf, (*len));
} while (rv == -1 && errno == EINTR);
if (rv == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) &&
sock->timeout != 0) {
- apr_status_t arv = wait_for_io_or_timeout(sock, 1);
+do_select:
+ arv = wait_for_io_or_timeout(sock, 1);
if (arv != APR_SUCCESS) {
*len = 0;
return arv;
@@ -146,6 +153,9 @@
if (rv == -1) {
(*len) = 0;
return errno;
+ }
+ if (sock->timeout && rv < *len) {
+ sock->netmask |= APR_INCOMPLETE_READ;
}
(*len) = rv;
if (rv == 0) {
Index: srclib/apr/network_io/unix/sockopt.c
===================================================================
RCS file: /home/cvs/apr/network_io/unix/sockopt.c,v
retrieving revision 1.45
diff -u -r1.45 sockopt.c
--- srclib/apr/network_io/unix/sockopt.c 2001/04/05 18:56:08 1.45
+++ srclib/apr/network_io/unix/sockopt.c 2001/07/07 18:18:17
@@ -216,6 +216,12 @@
}
}
}
+ /* must disable the incomplete read support if we change to a
+ * blocking socket.
+ */
+ if (on == 0) {
+ sock->netmask &= ~APR_INCOMPLETE_READ;
+ }
sock->timeout = on;
apr_set_option(&sock->netmask, APR_SO_TIMEOUT, on);
}