From: Ryan Bloom Date: Mon, 5 Mar 2001 06:16:28 +0000 (+0000) Subject: Make the old_write filter use the ap_f* functions for buffering the data. X-Git-Tag: 2.0.14~15 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3358c41372c396c13f9eafb9493b9718ddda2b65;p=apache 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 --- diff --git a/CHANGES b/CHANGES index af4a4542df..bcebe838d7 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,8 @@ 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. diff --git a/STATUS b/STATUS index 012cf33469..165872403c 100644 --- a/STATUS +++ b/STATUS @@ -1,5 +1,5 @@ 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 diff --git a/server/protocol.c b/server/protocol.c index e04c194094..0bfd0ded90 100644 --- a/server/protocol.c +++ b/server/protocol.c @@ -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) { - /* 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); + 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_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; }