Commit 1f1392f4 authored by Greg Stein's avatar Greg Stein
Browse files

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.


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@87811 13f79535-47bb-0310-9956-ffa450edef68
parent 835e6f79
Loading
Loading
Loading
Loading
+157 −135
Original line number Diff line number Diff line
@@ -3314,28 +3314,19 @@ static int core_input_filter(ap_filter_t *f, apr_bucket_brigade *b, ap_input_mod
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);
@@ -3343,10 +3334,27 @@ static apr_status_t core_output_filter(ap_filter_t *f, apr_bucket_brigade *b)
        ctx->b = NULL;
    }

    /* Iterate over the brigade collecting iovecs */
    do {
    /* Perform multiple passes over the brigade, sending batches of output
       to the connection. */
    while (b) {
            nbytes = 0; /* in case more points to another brigade */
        apr_size_t nbytes = 0;
        apr_bucket *e;

        /* tail of brigade if we need another pass */
        apr_bucket_brigade *more = NULL;

        /* 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;
@@ -3354,12 +3362,14 @@ static apr_status_t core_output_filter(ap_filter_t *f, apr_bucket_brigade *b)
            /* 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)) {
            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.
                 * so we split here and send the file we have already
                 * found.
                 */
                if (fd) {
                    more = apr_brigade_split(b, e);
@@ -3373,6 +3383,7 @@ static apr_status_t core_output_filter(ap_filter_t *f, apr_bucket_brigade *b)
            else {
                const char *str;
                apr_size_t n;

                rv = apr_bucket_read(e, &str, &n, APR_BLOCK_READ);
                if (n) {
                    nbytes += n;
@@ -3401,9 +3412,20 @@ static apr_status_t core_output_filter(ap_filter_t *f, apr_bucket_brigade *b)
        }
    
        /* 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) && 
         * 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)) {
                
@@ -3418,6 +3440,7 @@ static apr_status_t core_output_filter(ap_filter_t *f, apr_bucket_brigade *b)
            ap_save_brigade(f, &ctx->b, &b);
            return APR_SUCCESS;
        }

        if (fd) {
            apr_hdtr_t hdtr;
#if APR_HAS_SENDFILE
@@ -3459,8 +3482,10 @@ static apr_status_t core_output_filter(ap_filter_t *f, apr_bucket_brigade *b)
             */
            if (rv == APR_ENOTIMPL) {
#endif
                apr_size_t unused_bytes_sent;

                    rv = send_the_file(c, fd, &hdtr, foffset, flen, &bytes_sent);
                rv = send_the_file(c, fd, &hdtr, foffset, flen,
                                   &unused_bytes_sent);
    
#if APR_HAS_SENDFILE
            }
@@ -3468,9 +3493,11 @@ static apr_status_t core_output_filter(ap_filter_t *f, apr_bucket_brigade *b)
            fd = NULL;
        }
        else {
            apr_size_t unused_bytes_sent;

            rv = writev_it_all(c->client_socket, 
                               vec, nvec, 
                                   nbytes, &bytes_sent);
                               nbytes, &unused_bytes_sent);
        }

        apr_brigade_destroy(b);
@@ -3480,16 +3507,11 @@ static apr_status_t core_output_filter(ap_filter_t *f, apr_bucket_brigade *b)
                apr_brigade_destroy(more);
            return rv;
        }
            nvec = 0;
            nvec_trailers = 0;
    
        b = more;
        more = NULL;
    }  /* end while () */

        b = more;
    } while (more);

    return APR_SUCCESS;
}