Commit 4c580430 authored by Ryan Bloom's avatar Ryan Bloom
Browse files

Remove the coalesce filter. With the addition of the ap_f* functions,

this filter is no longer necessary.


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@88178 13f79535-47bb-0310-9956-ffa450edef68
parent 00fbaec7
Loading
Loading
Loading
Loading
+0 −138
Original line number Diff line number Diff line
@@ -3029,143 +3029,6 @@ static int default_handler(request_rec *r)
    return ap_pass_brigade(r->output_filters, bb);
}

/*
 * coalesce_filter()
 * This is a simple filter to coalesce many small buckets into one large
 * bucket. 
 *
 * Note:
 * This implementation of coalesce_filter will only coalesce a single
 * contiguous string of coalesable buckets. It will not coalesce multiple
 * non-contiguous buckets. For example, if a brigade contains 10 small 
 * buckets followed by a large bucket (or a pipe or file bucket) followed 
 * by more small buckets, only the first 10 buckets will be coalesced.
 */
typedef struct COALESCE_FILTER_CTX {
    char *buf;           /* Start of buffer */
    char *cur;           /* Pointer to next location to write */
    apr_size_t cnt;     /* Number of bytes put in buf */
    apr_size_t avail;   /* Number of bytes available in the buf */
} coalesce_filter_ctx_t;
#define MIN_BUCKET_SIZE 200
static apr_status_t coalesce_filter(ap_filter_t *f, apr_bucket_brigade *b)
{
    apr_status_t rv;
    apr_pool_t *p = f->r->pool;
    apr_bucket *e, *insert_before = NULL, *destroy_me = NULL;
    coalesce_filter_ctx_t *ctx = f->ctx;
    int pass_the_brigade = 0, insert_first = 0;

    if (ctx == NULL) {
        f->ctx = ctx = apr_pcalloc(p, sizeof(coalesce_filter_ctx_t));
        ctx->avail = AP_MIN_BYTES_TO_WRITE;
    }

    if (ctx->cnt) {
        insert_first = 1;
    }

    /* Iterate across the buckets, coalescing the small buckets into a 
     * single buffer 
     */
    APR_BRIGADE_FOREACH(e, b) {
        if (destroy_me) {
            apr_bucket_destroy(destroy_me);
            destroy_me = NULL;
        }
        if (APR_BUCKET_IS_EOS(e)  || APR_BUCKET_IS_FILE(e) ||
            APR_BUCKET_IS_PIPE(e) || APR_BUCKET_IS_FLUSH(e)) {
            pass_the_brigade = 1;
        }
        else {
            const char *str;
            apr_size_t n;
            rv = apr_bucket_read(e, &str, &n, APR_BLOCK_READ);
            if (rv != APR_SUCCESS) {
                /* XXX: log error */
                return rv;
            }
            if ((n < MIN_BUCKET_SIZE) && (n < ctx->avail)) {
                /* Coalesce this bucket into the buffer */
                if (ctx->buf == NULL) {
                    ctx->buf = apr_palloc(p, AP_MIN_BYTES_TO_WRITE);
                    ctx->cur = ctx->buf;
                    ctx->cnt = 0;
                }
                memcpy(ctx->cur, str, n);
                ctx->cnt += n;
                ctx->cur += n;
                ctx->avail -= n;
                /* If this is the first bucket to be coalesced, don't remove it 
                 * from the brigade. Save it as a marker for where to insert 
                 * ctx->buf into the brigade when we're done.
                 */
                if (insert_before || insert_first){
                    APR_BUCKET_REMOVE(e);
                    destroy_me = e;
                }
                else {
                    insert_before = e;
                }
            } 
            else if (insert_before || insert_first) {
                /* This bucket was not able to be coalesced because it either
                 * exceeds MIN_BUCKET_SIZE or its contents will not fit into
                 * buf. We're done...
                 */
                pass_the_brigade = 1;
                break;
            }
            else {
                /* If there is even a single bucket that cannot be coalesced, 
                 * then we must pass the brigade down to the next filter.
                 */
                pass_the_brigade = 1;
            }
        }
    }

    if (destroy_me) {
        apr_bucket_destroy(destroy_me);
        destroy_me = NULL;
    }

    if (pass_the_brigade) {
        /* Insert ctx->buf into the correct spot in the brigade */
        e = apr_bucket_pool_create(ctx->buf, ctx->cnt, p);
        if (insert_first) {
            APR_BRIGADE_INSERT_HEAD(b, e);
        } 
        else if (insert_before) {
            APR_BUCKET_INSERT_BEFORE(e, insert_before);
            APR_BUCKET_REMOVE(insert_before);
            apr_bucket_destroy(insert_before);
            insert_before = NULL;
        }
        rv = ap_pass_brigade(f->next, b);
        if (rv != APR_SUCCESS) {
            /* XXX: Log the error */
            return rv;
        }
        /* Get ctx->buf ready for the next brigade */
        if (ctx) {
            ctx->cur = ctx->buf;
            ctx->cnt = 0;
            ctx->avail = AP_MIN_BYTES_TO_WRITE;
        }
    }
    else {
        if (insert_before) {
            APR_BUCKET_REMOVE(insert_before);
            apr_bucket_destroy(insert_before);
        }
        /* The brigade should be empty now because all the buckets
         * were coalesced into the coalesce_filter buf
         */
    }

    return APR_SUCCESS;
}
/*
 * HTTP/1.1 chunked transfer encoding filter.
 */
@@ -3585,7 +3448,6 @@ static void register_hooks(apr_pool_t *p)
    ap_register_output_filter("SUBREQ_CORE", ap_sub_req_output_filter, 
                              AP_FTYPE_CONTENT);
    ap_register_output_filter("CHUNK", chunk_filter, AP_FTYPE_TRANSCODE);
    ap_register_output_filter("COALESCE", coalesce_filter, AP_FTYPE_CONTENT);
    ap_register_output_filter("OLD_WRITE", ap_old_write_filter,
                              AP_FTYPE_CONTENT - 1);
}