Commit 3c4c5c70 authored by Ryan Bloom's avatar Ryan Bloom
Browse files

Make the old_write filter use the ap_f* functions for buffering the data.

This has been tested with a couple of directory listings, but it could
probably use a bit more testing before being declared stable.


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@88454 13f79535-47bb-0310-9956-ffa450edef68
parent 2f853610
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
Changes with Apache 2.0.14-dev

  *) Make the old_write filter use the ap_f* functions for the buffering.
     [Ryan Bloom]

  *) Move more code from the http module into the core server.  This
     is core code, basically the default handler, the default input
     and output filters, and all of the core configuration directives.
+1 −3
Original line number Diff line number Diff line
APACHE 2.0 STATUS:						-*-text-*-
Last modified at [$Date: 2001/03/04 17:44:07 $]
Last modified at [$Date: 2001/03/05 06:16:28 $]

Release:

@@ -101,8 +101,6 @@ RELEASE SHOWSTOPPERS:
        MsgId: <20010227104646.E2297@lyra.org>
        MsgId: <3A9C0097.9C83F07C@Golux.Com>

    * The old_write filter needs to use ap_f* functions for the buffering.

RELEASE NON-SHOWSTOPPERS BUT WOULD BE REAL NICE TO WRAP THESE UP:

    * mod_include doesn't stream data when there are no SSI tags in
+17 −74
Original line number Diff line number Diff line
@@ -1347,9 +1347,7 @@ AP_DECLARE(size_t) ap_send_mmap(apr_mmap_t *mm, request_rec *r, size_t offset,
#endif /* APR_HAS_MMAP */

typedef struct {
    char *buf;
    char *cur;
    apr_size_t avail;
    apr_bucket_brigade *bb;
} old_write_filter_ctx;

AP_CORE_DECLARE_NONSTD(apr_status_t) ap_old_write_filter(
@@ -1359,39 +1357,15 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_old_write_filter(

    AP_DEBUG_ASSERT(ctx);

    if (ctx->buf != NULL) {
        apr_size_t nbyte = ctx->cur - ctx->buf;

        if (nbyte != 0) {
    if (ctx->bb != 0) {
        /* whatever is coming down the pipe (we don't care), we
               can simply insert our buffered data at the front and
               pass the whole bundle down the chain. */
            apr_bucket *b = apr_bucket_heap_create(ctx->buf, nbyte, 0, NULL);
            APR_BRIGADE_INSERT_HEAD(bb, b);
            ctx->buf = NULL;
        }
    }

    return ap_pass_brigade(f->next, bb);
}

static apr_status_t flush_buffer(request_rec *r, old_write_filter_ctx *ctx,
                                 const char *extra, apr_size_t extra_len)
{
    apr_bucket_brigade *bb = apr_brigade_create(r->pool);
    apr_size_t nbyte = ctx->cur - ctx->buf;
    apr_bucket *b = apr_bucket_heap_create(ctx->buf, nbyte, 0, NULL);

    APR_BRIGADE_INSERT_TAIL(bb, b);
    ctx->buf = NULL;

    /* if there is extra data, then send that, too */
    if (extra != NULL) {
        b = apr_bucket_transient_create(extra, extra_len);
        APR_BRIGADE_INSERT_TAIL(bb, b);
         * can simply insert our buffered data at the front and
         * pass the whole bundle down the chain. 
         */
        APR_BRIGADE_CONCAT(ctx->bb, bb);
    }

    return ap_pass_brigade(r->output_filters, bb);
    return ap_pass_brigade(f->next, ctx->bb);
}

static apr_status_t buffer_output(request_rec *r,
@@ -1399,14 +1373,13 @@ static apr_status_t buffer_output(request_rec *r,
{
    ap_filter_t *f;
    old_write_filter_ctx *ctx;
    apr_size_t amt;
    apr_status_t status;

    if (len == 0)
        return APR_SUCCESS;

    /* ### future optimization: record some flags in the request_rec to
       ### say whether we've added our filter, and whether it is first. */
    /* future optimization: record some flags in the request_rec to
     * say whether we've added our filter, and whether it is first.
     */

    /* this will typically exit on the first test */
    for (f = r->output_filters; f != NULL; f = f->next)
@@ -1416,11 +1389,12 @@ static apr_status_t buffer_output(request_rec *r,
        /* our filter hasn't been added yet */
        ctx = apr_pcalloc(r->pool, sizeof(*ctx));
        ap_add_output_filter("OLD_WRITE", ctx, r, r->connection);
        f = r->output_filters;
    }

    /* if the first filter is not our buffering filter, then we have to
       deliver the content through the normal filter chain */
    if (strcmp("OLD_WRITE", r->output_filters->frec->name) != 0) {
     * deliver the content through the normal filter chain */
    if (f != r->output_filters) {
        apr_bucket_brigade *bb = apr_brigade_create(r->pool);
        apr_bucket *b = apr_bucket_transient_create(str, len);
        APR_BRIGADE_INSERT_TAIL(bb, b);
@@ -1431,42 +1405,11 @@ static apr_status_t buffer_output(request_rec *r,
    /* grab the context from our filter */
    ctx = r->output_filters->ctx;

    /* if there isn't a buffer in the context yet, put one there. */
    if (ctx->buf == NULL) {
        /* use the heap so it will get free'd after being flushed */
        ctx->avail = AP_MIN_BYTES_TO_WRITE;
        ctx->buf = ctx->cur = malloc(ctx->avail);
    }

    /* squeeze the data into the existing buffer */
    if (len <= ctx->avail) {
        memcpy(ctx->cur, str, len);
        ctx->cur += len;
        if ((ctx->avail -= len) == 0)
            return flush_buffer(r, ctx, NULL, 0);
        return APR_SUCCESS;
    }

    /* the new content can't fit in the existing buffer */

    if (len >= AP_MIN_BYTES_TO_WRITE) {
        /* it is really big. send what we have, and the new stuff. */
        return flush_buffer(r, ctx, str, len);
    if (ctx->bb == NULL) {
        ctx->bb = apr_brigade_create(r->pool);
    }

    /* the new data is small. put some into the current buffer, flush it,
       and then drop the remaining into a new buffer. */
    amt = ctx->avail;
    memcpy(ctx->cur, str, amt);
    ctx->cur += amt;
    ctx->avail = 0;
    if ((status = flush_buffer(r, ctx, NULL, 0)) != APR_SUCCESS)
        return status;

    ctx->buf = malloc(AP_MIN_BYTES_TO_WRITE);
    memcpy(ctx->buf, str + amt, len - amt);
    ctx->cur = ctx->buf + (len - amt);
    ctx->avail = AP_MIN_BYTES_TO_WRITE - (len - amt);
    ap_fwrite(f->next, ctx->bb, str, len);

    return APR_SUCCESS;
}