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);
>