You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by "Roy T. Fielding" <fi...@kiwi.ics.uci.edu> on 1997/08/06 10:44:12 UTC
[PATCH] for 1.2.X, buff tuning
Okay, forget the bflush suggestion for get_remote_host -- I tested it
using truss and it didn't do what I was expecting anyway.
The following is Dean's patch without the superfluous start_chunk call
in bflush, plus a few changes where EAGAIN was not being caught on a
write that is supposed to be blocking (even if the socket isn't).
It still needs the porting-backward of the bhalfdup (weird name for that)
stuff, but I'll leave that to Dean since I need to work on what I am
supposed to be doing for a while.
.....Roy
Index: buff.c
===================================================================
RCS file: /export/home/cvs/apache/src/buff.c,v
retrieving revision 1.26
diff -c -r1.26 buff.c
*** buff.c 1997/05/29 05:21:15 1.26
--- buff.c 1997/08/06 07:29:51
***************
*** 624,629 ****
--- 624,630 ----
i = write(fb->fd, buf, nbyte);
if (i < 0) {
if (errno != EAGAIN && errno != EINTR) {
+ doerror (fb, B_WR);
return -1;
}
}
***************
*** 648,663 ****
bcwrite(BUFF *fb, const void *buf, int nbyte)
{
char chunksize[16]; /* Big enough for practically anything */
#ifndef NO_WRITEV
struct iovec vec[3];
! int i, rv;
#endif
if (fb->flags & (B_WRERR|B_EOUT))
return -1;
! if (!(fb->flags & B_CHUNK))
! return write(fb->fd, buf, nbyte);
#ifdef NO_WRITEV
/* without writev() this has poor performance, too bad */
--- 649,676 ----
bcwrite(BUFF *fb, const void *buf, int nbyte)
{
char chunksize[16]; /* Big enough for practically anything */
+ int rv;
#ifndef NO_WRITEV
struct iovec vec[3];
! int i;
#endif
if (fb->flags & (B_WRERR|B_EOUT))
return -1;
! if (!(fb->flags & B_CHUNK)) {
! do rv = write(fb->fd, buf, nbyte);
! while (rv == -1 && errno == EINTR && !(fb->flags & B_EOUT));
! if (rv == -1) {
! if (errno != EAGAIN) {
! doerror (fb, B_WR);
! }
! return -1;
! } else if (rv == 0) {
! errno = EAGAIN;
! }
! return rv;
! }
#ifdef NO_WRITEV
/* without writev() this has poor performance, too bad */
***************
*** 685,694 ****
* to deal with a partial writev()
*/
for( i = 0; i < NVEC; ) {
! do rv = writev( fb->fd, &vec[i], NVEC - i );
! while (rv == -1 && errno == EINTR && !(fb->flags & B_EOUT));
! if (rv == -1)
return -1;
/* recalculate vec to deal with partial writes */
while (rv > 0) {
if( rv <= vec[i].iov_len ) {
--- 698,712 ----
* to deal with a partial writev()
*/
for( i = 0; i < NVEC; ) {
! do {
! rv = writev( fb->fd, &vec[i], NVEC - i );
! } while ((rv <= 0)
! && !(fb->flags & B_EOUT)
! && (errno == EINTR || errno == EAGAIN || rv == 0));
! if (rv == -1) {
! doerror (fb, B_WR);
return -1;
+ }
/* recalculate vec to deal with partial writes */
while (rv > 0) {
if( rv <= vec[i].iov_len ) {
***************
*** 732,746 ****
{
/* unbuffered write -- have to use bcwrite since we aren't taking care
* of chunking any other way */
! do i = bcwrite(fb, buf, nbyte);
! while (i == -1 && errno == EINTR && !(fb->flags & B_EOUT));
! if (i == 0) { /* return of 0 means non-blocking */
! errno = EAGAIN;
! return -1;
! }
! else if (i < 0) {
! if (errno != EAGAIN)
! doerror(fb, B_WR);
return -1;
}
fb->bytes_sent += i;
--- 750,757 ----
{
/* unbuffered write -- have to use bcwrite since we aren't taking care
* of chunking any other way */
! i = bcwrite(fb, buf, nbyte);
! if (i <= 0) {
return -1;
}
fb->bytes_sent += i;
***************
*** 776,788 ****
/* it is just too painful to try to re-cram the buffer while
* chunking
*/
! i = (write_it_all(fb, fb->outbase, fb->outcnt) == -1) ?
! -1 : fb->outcnt;
! }
! else {
! do i = write(fb->fd, fb->outbase, fb->outcnt);
! while (i == -1 && errno == EINTR && !(fb->flags & B_EOUT));
}
if (i <= 0) {
if (i == 0) /* return of 0 means non-blocking */
errno = EAGAIN;
--- 787,803 ----
/* it is just too painful to try to re-cram the buffer while
* chunking
*/
! if (write_it_all(fb, fb->outbase, fb->outcnt) == -1) {
! /* we cannot continue after a chunked error */
! return -1;
! }
! fb->bytes_sent += fb->outcnt;
! fb->outcnt = 0;
! break;
}
+ do {
+ i = write(fb->fd, fb->outbase, fb->outcnt);
+ } while (i == -1 && errno == EINTR && !(fb->flags & B_EOUT));
if (i <= 0) {
if (i == 0) /* return of 0 means non-blocking */
errno = EAGAIN;
***************
*** 815,827 ****
*/
while (nbyte >= fb->bufsiz)
{
! do i = bcwrite(fb, buf, nbyte);
! while (i == -1 && errno == EINTR && !(fb->flags & B_EOUT));
if (i <= 0) {
- if (i == 0) /* return of 0 means non-blocking */
- errno = EAGAIN;
if (nwr == 0) {
- if (errno != EAGAIN) doerror(fb, B_WR);
return -1;
}
else return nwr;
--- 830,838 ----
*/
while (nbyte >= fb->bufsiz)
{
! i = bcwrite(fb, buf, nbyte);
if (i <= 0) {
if (nwr == 0) {
return -1;
}
else return nwr;
***************
*** 861,872 ****
while (fb->outcnt > 0)
{
! /* the buffer must be full */
! do i = write(fb->fd, fb->outbase, fb->outcnt);
! while (i == -1 && errno == EINTR && !(fb->flags & B_EOUT));
if (i == 0) {
errno = EAGAIN;
! return -1; /* return of 0 means non-blocking */
}
else if (i < 0) {
if (errno != EAGAIN) doerror(fb, B_WR);
--- 872,886 ----
while (fb->outcnt > 0)
{
! do {
! i = write(fb->fd, fb->outbase, fb->outcnt);
! } while ((i <= 0)
! && !(fb->flags & B_EOUT)
! && (errno == EINTR || errno == EAGAIN || i == 0));
!
if (i == 0) {
errno = EAGAIN;
! return -1; /* return of 0 means B_EOUT and non-blocking */
}
else if (i < 0) {
if (errno != EAGAIN) doerror(fb, B_WR);
Re: [PATCH] for 1.2.X, buff tuning
Posted by Dean Gaudet <dg...@arctic.org>.
This looks good, and passes my usual buffer tests. So a +1 on putting it
into 1.2.2.
I called it bhalfduplex() because it's used to check if a stream is really
in a half-duplex mode: client talks, server talks, client talks, server
talks, ... I'm open to suggestions. It's essentially the same as
B_SAFEREAD without actually reading anything. BTW, B_SAFEREAD is still
necessary because there may be stray CRLFs ready to read ... well, only on
POSTs, but it's a good safety measure.
Dean
On Wed, 6 Aug 1997, Roy T. Fielding wrote:
> Okay, forget the bflush suggestion for get_remote_host -- I tested it
> using truss and it didn't do what I was expecting anyway.
>
> The following is Dean's patch without the superfluous start_chunk call
> in bflush, plus a few changes where EAGAIN was not being caught on a
> write that is supposed to be blocking (even if the socket isn't).
> It still needs the porting-backward of the bhalfdup (weird name for that)
> stuff, but I'll leave that to Dean since I need to work on what I am
> supposed to be doing for a while.
>
> .....Roy
>
> Index: buff.c
> ===================================================================
> RCS file: /export/home/cvs/apache/src/buff.c,v
> retrieving revision 1.26
> diff -c -r1.26 buff.c
> *** buff.c 1997/05/29 05:21:15 1.26
> --- buff.c 1997/08/06 07:29:51
> ***************
> *** 624,629 ****
> --- 624,630 ----
> i = write(fb->fd, buf, nbyte);
> if (i < 0) {
> if (errno != EAGAIN && errno != EINTR) {
> + doerror (fb, B_WR);
> return -1;
> }
> }
> ***************
> *** 648,663 ****
> bcwrite(BUFF *fb, const void *buf, int nbyte)
> {
> char chunksize[16]; /* Big enough for practically anything */
> #ifndef NO_WRITEV
> struct iovec vec[3];
> ! int i, rv;
> #endif
>
> if (fb->flags & (B_WRERR|B_EOUT))
> return -1;
>
> ! if (!(fb->flags & B_CHUNK))
> ! return write(fb->fd, buf, nbyte);
>
> #ifdef NO_WRITEV
> /* without writev() this has poor performance, too bad */
> --- 649,676 ----
> bcwrite(BUFF *fb, const void *buf, int nbyte)
> {
> char chunksize[16]; /* Big enough for practically anything */
> + int rv;
> #ifndef NO_WRITEV
> struct iovec vec[3];
> ! int i;
> #endif
>
> if (fb->flags & (B_WRERR|B_EOUT))
> return -1;
>
> ! if (!(fb->flags & B_CHUNK)) {
> ! do rv = write(fb->fd, buf, nbyte);
> ! while (rv == -1 && errno == EINTR && !(fb->flags & B_EOUT));
> ! if (rv == -1) {
> ! if (errno != EAGAIN) {
> ! doerror (fb, B_WR);
> ! }
> ! return -1;
> ! } else if (rv == 0) {
> ! errno = EAGAIN;
> ! }
> ! return rv;
> ! }
>
> #ifdef NO_WRITEV
> /* without writev() this has poor performance, too bad */
> ***************
> *** 685,694 ****
> * to deal with a partial writev()
> */
> for( i = 0; i < NVEC; ) {
> ! do rv = writev( fb->fd, &vec[i], NVEC - i );
> ! while (rv == -1 && errno == EINTR && !(fb->flags & B_EOUT));
> ! if (rv == -1)
> return -1;
> /* recalculate vec to deal with partial writes */
> while (rv > 0) {
> if( rv <= vec[i].iov_len ) {
> --- 698,712 ----
> * to deal with a partial writev()
> */
> for( i = 0; i < NVEC; ) {
> ! do {
> ! rv = writev( fb->fd, &vec[i], NVEC - i );
> ! } while ((rv <= 0)
> ! && !(fb->flags & B_EOUT)
> ! && (errno == EINTR || errno == EAGAIN || rv == 0));
> ! if (rv == -1) {
> ! doerror (fb, B_WR);
> return -1;
> + }
> /* recalculate vec to deal with partial writes */
> while (rv > 0) {
> if( rv <= vec[i].iov_len ) {
> ***************
> *** 732,746 ****
> {
> /* unbuffered write -- have to use bcwrite since we aren't taking care
> * of chunking any other way */
> ! do i = bcwrite(fb, buf, nbyte);
> ! while (i == -1 && errno == EINTR && !(fb->flags & B_EOUT));
> ! if (i == 0) { /* return of 0 means non-blocking */
> ! errno = EAGAIN;
> ! return -1;
> ! }
> ! else if (i < 0) {
> ! if (errno != EAGAIN)
> ! doerror(fb, B_WR);
> return -1;
> }
> fb->bytes_sent += i;
> --- 750,757 ----
> {
> /* unbuffered write -- have to use bcwrite since we aren't taking care
> * of chunking any other way */
> ! i = bcwrite(fb, buf, nbyte);
> ! if (i <= 0) {
> return -1;
> }
> fb->bytes_sent += i;
> ***************
> *** 776,788 ****
> /* it is just too painful to try to re-cram the buffer while
> * chunking
> */
> ! i = (write_it_all(fb, fb->outbase, fb->outcnt) == -1) ?
> ! -1 : fb->outcnt;
> ! }
> ! else {
> ! do i = write(fb->fd, fb->outbase, fb->outcnt);
> ! while (i == -1 && errno == EINTR && !(fb->flags & B_EOUT));
> }
> if (i <= 0) {
> if (i == 0) /* return of 0 means non-blocking */
> errno = EAGAIN;
> --- 787,803 ----
> /* it is just too painful to try to re-cram the buffer while
> * chunking
> */
> ! if (write_it_all(fb, fb->outbase, fb->outcnt) == -1) {
> ! /* we cannot continue after a chunked error */
> ! return -1;
> ! }
> ! fb->bytes_sent += fb->outcnt;
> ! fb->outcnt = 0;
> ! break;
> }
> + do {
> + i = write(fb->fd, fb->outbase, fb->outcnt);
> + } while (i == -1 && errno == EINTR && !(fb->flags & B_EOUT));
> if (i <= 0) {
> if (i == 0) /* return of 0 means non-blocking */
> errno = EAGAIN;
> ***************
> *** 815,827 ****
> */
> while (nbyte >= fb->bufsiz)
> {
> ! do i = bcwrite(fb, buf, nbyte);
> ! while (i == -1 && errno == EINTR && !(fb->flags & B_EOUT));
> if (i <= 0) {
> - if (i == 0) /* return of 0 means non-blocking */
> - errno = EAGAIN;
> if (nwr == 0) {
> - if (errno != EAGAIN) doerror(fb, B_WR);
> return -1;
> }
> else return nwr;
> --- 830,838 ----
> */
> while (nbyte >= fb->bufsiz)
> {
> ! i = bcwrite(fb, buf, nbyte);
> if (i <= 0) {
> if (nwr == 0) {
> return -1;
> }
> else return nwr;
> ***************
> *** 861,872 ****
>
> while (fb->outcnt > 0)
> {
> ! /* the buffer must be full */
> ! do i = write(fb->fd, fb->outbase, fb->outcnt);
> ! while (i == -1 && errno == EINTR && !(fb->flags & B_EOUT));
> if (i == 0) {
> errno = EAGAIN;
> ! return -1; /* return of 0 means non-blocking */
> }
> else if (i < 0) {
> if (errno != EAGAIN) doerror(fb, B_WR);
> --- 872,886 ----
>
> while (fb->outcnt > 0)
> {
> ! do {
> ! i = write(fb->fd, fb->outbase, fb->outcnt);
> ! } while ((i <= 0)
> ! && !(fb->flags & B_EOUT)
> ! && (errno == EINTR || errno == EAGAIN || i == 0));
> !
> if (i == 0) {
> errno = EAGAIN;
> ! return -1; /* return of 0 means B_EOUT and non-blocking */
> }
> else if (i < 0) {
> if (errno != EAGAIN) doerror(fb, B_WR);
>