httpd-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Dean Gaudet <dgau...@hyperreal.org>
Subject cvs commit: apache/src CHANGES buff.c
Date Tue, 29 Jul 1997 06:52:28 GMT
dgaudet     97/07/28 23:52:28

  Modified:    src       CHANGES buff.c
  Log:
  Combine large bwrite() with partial buffer by using writev() to avoid any
  mem->mem copies.  Fix a bug where if bflush/bwrite had a write failure
  while chunking they won't properly start the next chunk.
  
  Revision  Changes    Path
  1.371     +10 -0     apache/src/CHANGES
  
  Index: CHANGES
  ===================================================================
  RCS file: /export/home/cvs/apache/src/CHANGES,v
  retrieving revision 1.370
  retrieving revision 1.371
  diff -u -r1.370 -r1.371
  --- CHANGES	1997/07/28 18:22:40	1.370
  +++ CHANGES	1997/07/29 06:52:25	1.371
  @@ -1,5 +1,15 @@
   Changes with Apache 1.3a2
   
  +  *) When a large bwrite() occurs (larger than the internal buffer size),
  +     while there is already something in the buffer, apache will combine
  +     the large write and the buffer into a single writev().  (This is
  +     in anticipation of using mmap() for reading files.)
  +     [Dean Gaudet]
  +
  +  *) In obscure cases where a partial socket write occured while chunking,
  +     Apache would omit the chunk header/footer on the next block.
  +     [Dean Gaudet]
  +
     *) API: Added child_exit function to module structure.  This is called
        once per "heavy-weight process" just before a server child exit()'s 
        e.g. when max_requests_per_child is reached, etc.
  
  
  
  1.39      +103 -39   apache/src/buff.c
  
  Index: buff.c
  ===================================================================
  RCS file: /export/home/cvs/apache/src/buff.c,v
  retrieving revision 1.38
  retrieving revision 1.39
  diff -u -r1.38 -r1.39
  --- buff.c	1997/07/24 04:23:57	1.38
  +++ buff.c	1997/07/29 06:52:26	1.39
  @@ -840,6 +840,45 @@
   }
   
   
  +#ifndef NO_WRITEV
  +/* similar to previous, but uses writev.  Note that it modifies vec.
  + * return 0 if successful, -1 otherwise.
  + */
  +static int writev_it_all (BUFF *fb, struct iovec *vec, int nvec)
  +{
  +    int i, rv;
  +
  +    /* while it's nice an easy to build the vector and crud, it's painful
  +     * 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) {
  +		vec[i].iov_base = (char *)vec[i].iov_base + rv;
  +		vec[i].iov_len -= rv;
  +		rv = 0;
  +		if (vec[i].iov_len == 0) {
  +		    ++i;
  +		}
  +	    } else {
  +		rv -= vec[i].iov_len;
  +		++i;
  +	    }
  +	}
  +	if (fb->flags & B_EOUT)
  +	    return -1;
  +    }
  +    /* if we got here, we wrote it all */
  +    return 0;
  +}
  +#endif
  +
  +
   /*
    * A hook to write() that deals with chunking. This is really a protocol-
    * level issue, but we deal with it here because it's simpler; this is
  @@ -852,7 +891,6 @@
       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))
  @@ -874,9 +912,6 @@
   	return -1;
       return nbyte;
   #else
  -
  -#define NVEC	(sizeof(vec)/sizeof(vec[0]))
  -
       vec[0].iov_base = chunksize;
       vec[0].iov_len = ap_snprintf(chunksize, sizeof(chunksize), "%x\015\012",
   	nbyte);
  @@ -884,38 +919,51 @@
       vec[1].iov_len = nbyte;
       vec[2].iov_base = "\r\n";
       vec[2].iov_len = 2;
  -    /* while it's nice an easy to build the vector and crud, it's painful
  -     * 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 ) {
  -		vec[i].iov_base = (char *)vec[i].iov_base + rv;
  -		vec[i].iov_len -= rv;
  -		rv = 0;
  -		if( vec[i].iov_len == 0 ) {
  -		    ++i;
  -		}
  -	    } else {
  -		rv -= vec[i].iov_len;
  -		++i;
  -	    }
  -	}
  -	if (fb->flags & B_EOUT)
  -	    return -1;
  -    }
  -    /* if we got here, we wrote it all */
  -    return nbyte;
  -#undef NVEC
  +
  +    return writev_it_all (fb, vec, (sizeof(vec)/sizeof(vec[0]))) ? -1 : nbyte;
   #endif
   }
   
   
  +#ifndef NO_WRITEV
  +/*
  + * Used to combine the contents of the fb buffer, and a large buffer
  + * passed in.
  + */
  +static int large_write (BUFF *fb, const void *buf, int nbyte)
  +{
  +    struct iovec vec[4];
  +    int nvec;
  +    char chunksize[16];
  +
  +    nvec = 0;
  +    /* it's easiest to end the current chunk */
  +    if (fb->flags & B_CHUNK) {
  +	end_chunk(fb);
  +    }
  +    vec[0].iov_base = fb->outbase;
  +    vec[0].iov_len = fb->outcnt;
  +    if (fb->flags & B_CHUNK) {
  +	vec[1].iov_base = chunksize;
  +	vec[1].iov_len = ap_snprintf (chunksize, sizeof(chunksize),
  +	    "%x\015\012", nbyte);
  +	vec[2].iov_base = (void *)buf;
  +	vec[2].iov_len = nbyte;
  +	vec[3].iov_base = "\r\n";
  +	vec[3].iov_len = 2;
  +	nvec = 4;
  +    } else {
  +	vec[1].iov_base = (void *)buf;
  +	vec[1].iov_len = nbyte;
  +	nvec = 2;
  +    }
  +
  +    fb->outcnt = 0;
  +    return writev_it_all (fb, vec, nvec) ? -1 : nbyte;
  +}
  +#endif
  +
  +
   /*
    * Write nbyte bytes.
    * Only returns fewer than nbyte if an error ocurred.
  @@ -952,6 +1000,19 @@
   	    return i;
       }
   
  +#ifndef NO_WRITEV
  +/*
  + * Detect case where we're asked to write a large buffer, and combine our
  + * current buffer with it in a single writev()
  + */
  +    if (fb->outcnt > 0 && nbyte >= fb->bufsiz) {
  +	return large_write (fb, buf, nbyte);
  +    }
  +#endif
  +
  +    /* in case a chunk hasn't been started yet */
  +    if( fb->flags & B_CHUNK ) start_chunk( fb );
  +
   /*
    * Whilst there is data in the buffer, keep on adding to it and writing it
    * out
  @@ -978,13 +1039,17 @@
   	    /* 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 = buff_write(fb, fb->outbase, fb->outcnt);
  -	    } while (i == -1 && errno == EINTR && !(fb->flags & B_EOUT));
  +	    if (write_it_all(fb, fb->outbase, fb->outcnt) == -1) {
  +		/* we cannot continue after a chunked error */
  +		doerror (fb, B_WR);
  +		return -1;
  +	    }
  +	    fb->outcnt = 0;
  +	    break;
   	}
  +	do {
  +	    i = buff_write(fb, 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;
  @@ -1062,7 +1127,6 @@
   
       while (fb->outcnt > 0)
       {
  -	/* the buffer must be full */
   	do {
   	    i = buff_write(fb, fb->outbase, fb->outcnt);
   	} while (i == -1 && errno == EINTR && !(fb->flags & B_EOUT));
  
  
  

Mime
View raw message