httpd-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From gst...@apache.org
Subject cvs commit: httpd-2.0/modules/http http_core.c
Date Wed, 24 Jan 2001 06:17:27 GMT
gstein      01/01/23 22:17:27

  Modified:    modules/http http_core.c
  Log:
  A single outermost loop is all that is needed. Simplify and add comments
  about what is going on in there. Shift some declarations to scope their
  usage and (re)initialize them on each pass over the brigade.
  
  Revision  Changes    Path
  1.247     +159 -137  httpd-2.0/modules/http/http_core.c
  
  Index: http_core.c
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/modules/http/http_core.c,v
  retrieving revision 1.246
  retrieving revision 1.247
  diff -u -u -r1.246 -r1.247
  --- http_core.c	2001/01/24 02:14:23	1.246
  +++ http_core.c	2001/01/24 06:17:26	1.247
  @@ -3314,181 +3314,203 @@
   typedef struct CORE_OUTPUT_FILTER_CTX {
       apr_bucket_brigade *b;
   } core_output_filter_ctx_t;
  +
   #define MAX_IOVEC_TO_WRITE 16
  +
   static apr_status_t core_output_filter(ap_filter_t *f, apr_bucket_brigade *b)
   {
       apr_status_t rv;
  -    apr_bucket_brigade *more = NULL;
  -    apr_size_t bytes_sent = 0, nbytes;
  -    apr_bucket *e;
       conn_rec *c = f->c;
       core_output_filter_ctx_t *ctx = f->ctx;
   
  -    apr_size_t nvec = 0;
  -    apr_size_t nvec_trailers= 0;
  -    struct iovec vec[MAX_IOVEC_TO_WRITE];
  -    struct iovec vec_trailers[MAX_IOVEC_TO_WRITE];
  -
  -    apr_file_t *fd = NULL;
  -    apr_size_t flen = 0;
  -    apr_off_t foffset = 0;
  -
       if (ctx == NULL) {
           f->ctx = ctx = apr_pcalloc(c->pool, sizeof(core_output_filter_ctx_t));
       }
  +
       /* If we have a saved brigade, concatenate the new brigade to it */
       if (ctx->b) {
           APR_BRIGADE_CONCAT(ctx->b, b);
           b = ctx->b;
           ctx->b = NULL;
       }
  +
  +    /* Perform multiple passes over the brigade, sending batches of output
  +       to the connection. */
  +    while (b) {
  +        apr_size_t nbytes = 0;
  +        apr_bucket *e;
  +
  +        /* tail of brigade if we need another pass */
  +        apr_bucket_brigade *more = NULL;
   
  -    /* Iterate over the brigade collecting iovecs */
  -    do {
  -        while (b) {
  -            nbytes = 0; /* in case more points to another brigade */
  -            APR_BRIGADE_FOREACH(e, b) {
  -                if (APR_BUCKET_IS_EOS(e) || APR_BUCKET_IS_FLUSH(e)) {
  +        /* one group of iovecs per pass over the brigade */
  +        apr_size_t nvec = 0;
  +        apr_size_t nvec_trailers = 0;
  +        struct iovec vec[MAX_IOVEC_TO_WRITE];
  +        struct iovec vec_trailers[MAX_IOVEC_TO_WRITE];
  +
  +        /* one file per pass over the brigade */
  +        apr_file_t *fd = NULL;
  +        apr_size_t flen = 0;
  +        apr_off_t foffset = 0;
  +
  +        /* Iterate over the brigade: collect iovecs and/or a file */
  +        APR_BRIGADE_FOREACH(e, b) {
  +            if (APR_BUCKET_IS_EOS(e) || APR_BUCKET_IS_FLUSH(e)) {
  +                break;
  +            }
  +            /* It doesn't make any sense to use sendfile for a file bucket
  +             * that represents 10 bytes.
  +             */
  +            else if (APR_BUCKET_IS_FILE(e)
  +                     && (e->length >= AP_MIN_SENDFILE_BYTES)) {
  +                apr_bucket_shared *s = e->data;
  +                apr_bucket_file *a = s->data;
  +    
  +                /* We can't handle more than one file bucket at a time
  +                 * so we split here and send the file we have already
  +                 * found.
  +                 */
  +                if (fd) {
  +                    more = apr_brigade_split(b, e);
                       break;
                   }
  -                /* It doesn't make any sense to use sendfile for a file bucket
  -                 * that represents 10 bytes.
  -                 */
  -                else if (APR_BUCKET_IS_FILE(e) && (e->length >= AP_MIN_SENDFILE_BYTES))
{
  -                    apr_bucket_shared *s = e->data;
  -                    apr_bucket_file *a = s->data;
  -    
  -                    /* We can't handle more than one file bucket at a time
  -                     * so we split here and send the file we have already found.
  -                     */
  -                    if (fd) {
  -                        more = apr_brigade_split(b, e);
  -                        break;
  -                    }
       
  -                    fd = a->fd;
  -                    flen = e->length;
  -                    foffset = s->start;
  -                }
  -                else {
  -                    const char *str;
  -                    apr_size_t n;
  -                    rv = apr_bucket_read(e, &str, &n, APR_BLOCK_READ);
  -                    if (n) {
  -                        nbytes += n;
  -                        if (!fd) {
  -                            vec[nvec].iov_base = (char*) str;
  -                            vec[nvec].iov_len = n;
  -                            nvec++;
  -                        }
  -                        else {
  -                            /* The bucket is a trailer to a file bucket */
  -                            vec_trailers[nvec_trailers].iov_base = (char*) str;
  -                            vec_trailers[nvec_trailers].iov_len = n;
  -                            nvec_trailers++;
  -                        }
  +                fd = a->fd;
  +                flen = e->length;
  +                foffset = s->start;
  +            }
  +            else {
  +                const char *str;
  +                apr_size_t n;
  +
  +                rv = apr_bucket_read(e, &str, &n, APR_BLOCK_READ);
  +                if (n) {
  +                    nbytes += n;
  +                    if (!fd) {
  +                        vec[nvec].iov_base = (char*) str;
  +                        vec[nvec].iov_len = n;
  +                        nvec++;
  +                    }
  +                    else {
  +                        /* The bucket is a trailer to a file bucket */
  +                        vec_trailers[nvec_trailers].iov_base = (char*) str;
  +                        vec_trailers[nvec_trailers].iov_len = n;
  +                        nvec_trailers++;
                       }
                   }
  +            }
       
  -                if ((nvec == MAX_IOVEC_TO_WRITE) || 
  -                    (nvec_trailers == MAX_IOVEC_TO_WRITE)) {
  -                    /* Split the brigade and break */
  -                    if (APR_BUCKET_NEXT(e) != APR_BRIGADE_SENTINEL(b)) {
  -                        more = apr_brigade_split(b, APR_BUCKET_NEXT(e));
  -                    }
  -                    break;
  +            if ((nvec == MAX_IOVEC_TO_WRITE) || 
  +                (nvec_trailers == MAX_IOVEC_TO_WRITE)) {
  +                /* Split the brigade and break */
  +                if (APR_BUCKET_NEXT(e) != APR_BRIGADE_SENTINEL(b)) {
  +                    more = apr_brigade_split(b, APR_BUCKET_NEXT(e));
                   }
  +                break;
               }
  +        }
       
  -            /* Completed iterating over the brigades, now determine if we want 
  -             * to buffer the brigade or send the brigade out on the network
  -             */
  -            if ((!fd && (!more) && 
  -                (nbytes < AP_MIN_BYTES_TO_WRITE) && !APR_BUCKET_IS_FLUSH(e))
  -                || (APR_BUCKET_IS_EOS(e) && c->keepalive)) {
  +        /* Completed iterating over the brigades, now determine if we want 
  +         * to buffer the brigade or send the brigade out on the network.
  +         *
  +         * Save if:
  +         *
  +         *   1) we didn't see a file, we don't have more passes over the
  +         *      brigade to perform, we haven't accumulated enough bytes to
  +         *      send, AND we didn't stop at a FLUSH bucket.
  +         *      (IOW, we will save away plain old bytes)
  +         * or
  +         *   2) we hit the EOS and have a keep-alive connection
  +         *      (IOW, this response is a bit more complex, but we save it
  +         *       with the hope of concatenating with another response)
  +         */
  +        if ((!fd && !more && 
  +             (nbytes < AP_MIN_BYTES_TO_WRITE) && !APR_BUCKET_IS_FLUSH(e))
  +            || (APR_BUCKET_IS_EOS(e) && c->keepalive)) {
                   
  -                /* NEVER save an EOS in here.  If we are saving a brigade with 
  -                 * an EOS bucket, then we are doing keepalive connections, and 
  -                 * we want to process to second request fully.
  -                 */
  -                if (APR_BUCKET_IS_EOS(e)) {
  -                    APR_BUCKET_REMOVE(e);
  -                    apr_bucket_destroy(e);
  -                }
  -                ap_save_brigade(f, &ctx->b, &b);
  -                return APR_SUCCESS;
  +            /* NEVER save an EOS in here.  If we are saving a brigade with 
  +             * an EOS bucket, then we are doing keepalive connections, and 
  +             * we want to process to second request fully.
  +             */
  +            if (APR_BUCKET_IS_EOS(e)) {
  +                APR_BUCKET_REMOVE(e);
  +                apr_bucket_destroy(e);
               }
  -            if (fd) {
  -                apr_hdtr_t hdtr;
  +            ap_save_brigade(f, &ctx->b, &b);
  +            return APR_SUCCESS;
  +        }
  +
  +        if (fd) {
  +            apr_hdtr_t hdtr;
   #if APR_HAS_SENDFILE
  -                apr_int32_t flags = 0;
  +            apr_int32_t flags = 0;
   #endif
       
  -                memset(&hdtr, '\0', sizeof(hdtr));
  -                if (nvec) {
  -                    hdtr.numheaders = nvec;
  -                    hdtr.headers = vec;
  -                }
  -                if (nvec_trailers) {
  -                    hdtr.numtrailers = nvec_trailers;
  -                    hdtr.trailers = vec_trailers;
  -                }
  +            memset(&hdtr, '\0', sizeof(hdtr));
  +            if (nvec) {
  +                hdtr.numheaders = nvec;
  +                hdtr.headers = vec;
  +            }
  +            if (nvec_trailers) {
  +                hdtr.numtrailers = nvec_trailers;
  +                hdtr.trailers = vec_trailers;
  +            }
   #if APR_HAS_SENDFILE
  -                if (!c->keepalive) {
  -                    /* Prepare the socket to be reused */
  -                    flags |= APR_SENDFILE_DISCONNECT_SOCKET;
  -                }
  -                rv = sendfile_it_all(c,        /* the connection            */
  -                                     fd,       /* the file to send          */
  -                                     &hdtr,    /* header and trailer iovecs */
  -                                     foffset,  /* offset in the file to begin
  -                                                  sending from              */
  -                                     flen,     /* length of file            */
  -                                     nbytes + flen, /* total length including
  -                                                       headers                */
  -                                     flags);   /* apr_sendfile flags        */
  -    
  -                /* If apr_sendfile() returns APR_ENOTIMPL, call send_the_file()
  -                 * to loop on apr_read/apr_send to send the file. Our Windows 
  -                 * binary distributions (which work on Windows 9x/NT) are 
  -                 * compiled on Windows NT. TransmitFile is not available on 
  -                 * Windows 95/98 and we discover this at runtime when 
  -                 * apr_sendfile() returns APR_ENOTIMPL. Having apr_sendfile() 
  -                 * return APR_ENOTIMPL seems the cleanest way to handle this 
  -                 * case.
  -                 */
  -                if (rv == APR_ENOTIMPL) {
  +            if (!c->keepalive) {
  +                /* Prepare the socket to be reused */
  +                flags |= APR_SENDFILE_DISCONNECT_SOCKET;
  +            }
  +            rv = sendfile_it_all(c,        /* the connection            */
  +                                 fd,       /* the file to send          */
  +                                 &hdtr,    /* header and trailer iovecs */
  +                                 foffset,  /* offset in the file to begin
  +                                              sending from              */
  +                                 flen,     /* length of file            */
  +                                 nbytes + flen, /* total length including
  +                                                   headers                */
  +                                 flags);   /* apr_sendfile flags        */
  +    
  +            /* If apr_sendfile() returns APR_ENOTIMPL, call send_the_file()
  +             * to loop on apr_read/apr_send to send the file. Our Windows 
  +             * binary distributions (which work on Windows 9x/NT) are 
  +             * compiled on Windows NT. TransmitFile is not available on 
  +             * Windows 95/98 and we discover this at runtime when 
  +             * apr_sendfile() returns APR_ENOTIMPL. Having apr_sendfile() 
  +             * return APR_ENOTIMPL seems the cleanest way to handle this 
  +             * case.
  +             */
  +            if (rv == APR_ENOTIMPL) {
   #endif
  -    
  -                    rv = send_the_file(c, fd, &hdtr, foffset, flen, &bytes_sent);
  +                apr_size_t unused_bytes_sent;
  +
  +                rv = send_the_file(c, fd, &hdtr, foffset, flen,
  +                                   &unused_bytes_sent);
       
   #if APR_HAS_SENDFILE
  -                }
  -#endif
  -                fd = NULL;
               }
  -            else {
  -                rv = writev_it_all(c->client_socket, 
  -                                   vec, nvec, 
  -                                   nbytes, &bytes_sent);
  -            }
  -    
  -            apr_brigade_destroy(b);
  -            if (rv != APR_SUCCESS) {
  -                /* XXX: log the error */
  -                if (more)
  -                    apr_brigade_destroy(more);
  -                return rv;
  -            }
  -            nvec = 0;
  -            nvec_trailers = 0;
  -    
  -            b = more;
  -            more = NULL;
  -        }  /* end while () */
  +#endif
  +            fd = NULL;
  +        }
  +        else {
  +            apr_size_t unused_bytes_sent;
   
  +            rv = writev_it_all(c->client_socket, 
  +                               vec, nvec, 
  +                               nbytes, &unused_bytes_sent);
  +        }
  +
  +        apr_brigade_destroy(b);
  +        if (rv != APR_SUCCESS) {
  +            /* XXX: log the error */
  +            if (more)
  +                apr_brigade_destroy(more);
  +            return rv;
  +        }
  +    
           b = more;
  -    } while (more);
  +        more = NULL;
  +    }  /* end while () */
   
       return APR_SUCCESS;
   }
  
  
  

Mime
View raw message