]> granicus.if.org Git - apache/commitdiff
core, mod_deflate, mod_sed: Reduce memory usage by reusing bucket
authorStefan Fritsch <sf@apache.org>
Sun, 4 Oct 2009 07:37:28 +0000 (07:37 +0000)
committerStefan Fritsch <sf@apache.org>
Sun, 4 Oct 2009 07:37:28 +0000 (07:37 +0000)
brigades in several places

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@821471 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
modules/filters/mod_deflate.c
modules/filters/mod_sed.c
modules/http/chunk_filter.c
server/protocol.c

diff --git a/CHANGES b/CHANGES
index fd5bb5b176904cc94d65c9a42c9f2f435d4e5b33..38c3f92a1adaee49820b0e4da5cf8ba7c196c31a 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -10,6 +10,9 @@ Changes with Apache 2.3.3
      mod_proxy_ftp: NULL pointer dereference on error paths.
      [Stefan Fritsch <sf fritsch.de>, Joe Orton]
 
+  *) core, mod_deflate, mod_sed: Reduce memory usage by reusing bucket
+     brigades in several places. [Stefan Fritsch]
+
   *) mod_cache: Fix uri_meets_conditions() so that CacheEnable will
      match by scheme, or by a wildcarded hostname. PR 40169
      [Ryan Pendergast <rpender us.ibm.com>, Graham Leggett]
index 4451d77a205e20f15a0c331ddcd887b91701d9b7..2cbbf6bbf61c14e7151281af620652ec32684378 100644 (file)
@@ -1011,14 +1011,11 @@ static apr_status_t deflate_in_filter(ap_filter_t *f,
     }
 
     if (!APR_BRIGADE_EMPTY(ctx->proc_bb)) {
-        apr_bucket_brigade *newbb;
-
         /* May return APR_INCOMPLETE which is fine by us. */
         apr_brigade_partition(ctx->proc_bb, readbytes, &bkt);
 
-        newbb = apr_brigade_split(ctx->proc_bb, bkt);
         APR_BRIGADE_CONCAT(bb, ctx->proc_bb);
-        APR_BRIGADE_CONCAT(ctx->proc_bb, newbb);
+        apr_brigade_split_ex(bb, bkt, ctx->proc_bb);
     }
 
     return APR_SUCCESS;
index 1fc72b057952d83ca7b540429e72c891320c5291..8c01fe1a0d04900f28894e16317c90a1edcf97ca 100644 (file)
@@ -48,6 +48,7 @@ typedef struct sed_filter_ctxt
     ap_filter_t *f;
     request_rec *r;
     apr_bucket_brigade *bb;
+    apr_bucket_brigade *bbinp;
     char *outbuf;
     char *curoutbuf;
     int bufsize;
@@ -392,6 +393,7 @@ static apr_status_t sed_request_filter(ap_filter_t *f,
                                            &sed_module);
     sed_filter_ctxt *ctx = f->ctx;
     apr_status_t status;
+    apr_bucket_brigade *bbinp;
     sed_expr_config *sed_cfg = &cfg->input;
 
     if (mode != AP_MODE_READBYTES) {
@@ -413,9 +415,12 @@ static apr_status_t sed_request_filter(ap_filter_t *f,
         if (status != APR_SUCCESS)
              return status;
         ctx = f->ctx;
-        ctx->bb = apr_brigade_create(f->r->pool, f->c->bucket_alloc);
+        ctx->bb    = apr_brigade_create(f->r->pool, f->c->bucket_alloc);
+        ctx->bbinp = apr_brigade_create(f->r->pool, f->c->bucket_alloc);
     }
 
+    bbinp = ctx->bbinp;
+
     /* Here is the logic :
      * Read the readbytes data from next level fiter into bbinp. Loop through
      * the buckets in bbinp and read the data from buckets and invoke
@@ -435,11 +440,10 @@ static apr_status_t sed_request_filter(ap_filter_t *f,
      * the question is where to add it?
      */
     while (APR_BRIGADE_EMPTY(ctx->bb)) {
-        apr_bucket_brigade *bbinp;
         apr_bucket *b;
 
         /* read the bytes from next level filter */
-        bbinp = apr_brigade_create(f->r->pool, f->c->bucket_alloc);
+        apr_brigade_cleanup(bbinp);
         status = ap_get_brigade(f->next, bbinp, mode, block, readbytes);
         if (status != APR_SUCCESS) {
             return status;
@@ -469,20 +473,16 @@ static apr_status_t sed_request_filter(ap_filter_t *f,
                 flush_output_buffer(ctx);
             }
         }
-        apr_brigade_cleanup(bbinp);
-        apr_brigade_destroy(bbinp);
     }
 
     if (!APR_BRIGADE_EMPTY(ctx->bb)) {
-        apr_bucket_brigade *newbb = NULL;
         apr_bucket *b = NULL;
 
         /* This may return APR_INCOMPLETE which should be fine */
         apr_brigade_partition(ctx->bb, readbytes, &b);
 
-        newbb = apr_brigade_split(ctx->bb, b);
         APR_BRIGADE_CONCAT(bb, ctx->bb);
-        APR_BRIGADE_CONCAT(ctx->bb, newbb);
+        apr_brigade_split_ex(bb, b, ctx->bb);
     }
     return APR_SUCCESS;
 }
index a8ce0d02402169273ba33246fb26815dc25800e0..17fbabdb0a70b1e15c7d4c738b265f5008bb68f2 100644 (file)
@@ -49,11 +49,11 @@ apr_status_t ap_http_chunk_filter(ap_filter_t *f, apr_bucket_brigade *b)
 #define ASCII_CRLF  "\015\012"
 #define ASCII_ZERO  "\060"
     conn_rec *c = f->r->connection;
-    apr_bucket_brigade *more;
+    apr_bucket_brigade *more, *tmp;
     apr_bucket *e;
     apr_status_t rv;
 
-    for (more = NULL; b; b = more, more = NULL) {
+    for (more = tmp = NULL; b; b = more, more = NULL) {
         apr_off_t bytes = 0;
         apr_bucket *eos = NULL;
         apr_bucket *flush = NULL;
@@ -85,7 +85,7 @@ apr_status_t ap_http_chunk_filter(ap_filter_t *f, apr_bucket_brigade *b)
             if (APR_BUCKET_IS_FLUSH(e)) {
                 flush = e;
                 if (e != APR_BRIGADE_LAST(b)) {
-                    more = apr_brigade_split(b, APR_BUCKET_NEXT(e));
+                    more = apr_brigade_split_ex(b, APR_BUCKET_NEXT(e), tmp);
                 }
                 break;
             }
@@ -105,7 +105,7 @@ apr_status_t ap_http_chunk_filter(ap_filter_t *f, apr_bucket_brigade *b)
                      * block so we pass down what we have so far.
                      */
                     bytes += len;
-                    more = apr_brigade_split(b, APR_BUCKET_NEXT(e));
+                    more = apr_brigade_split_ex(b, APR_BUCKET_NEXT(e), tmp);
                     break;
                 }
                 else {
@@ -189,6 +189,8 @@ apr_status_t ap_http_chunk_filter(ap_filter_t *f, apr_bucket_brigade *b)
         if (rv != APR_SUCCESS || eos != NULL) {
             return rv;
         }
+        tmp = b;
+        apr_brigade_cleanup(tmp);
     }
     return APR_SUCCESS;
 }
index e082de939017d35146cc0de479e203c3f7c71423..85965d08bc86deb91ee93f1eea945dea6b17286e 100644 (file)
@@ -1251,6 +1251,7 @@ struct content_length_ctx {
                      * least one bucket on to the next output filter
                      * for this request
                      */
+    apr_bucket_brigade *tmpbb;
 };
 
 /* This filter computes the content length, but it also computes the number
@@ -1271,6 +1272,7 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_content_length_filter(
     if (!ctx) {
         f->ctx = ctx = apr_palloc(r->pool, sizeof(*ctx));
         ctx->data_sent = 0;
+        ctx->tmpbb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
     }
 
     /* Loop through this set of buckets to compute their length
@@ -1300,16 +1302,15 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_content_length_filter(
                  * do a blocking read on the next batch.
                  */
                 if (e != APR_BRIGADE_FIRST(b)) {
-                    apr_bucket_brigade *split = apr_brigade_split(b, e);
+                    apr_brigade_split_ex(b, e, ctx->tmpbb);
                     apr_bucket *flush = apr_bucket_flush_create(r->connection->bucket_alloc);
 
                     APR_BRIGADE_INSERT_TAIL(b, flush);
                     rv = ap_pass_brigade(f->next, b);
                     if (rv != APR_SUCCESS || f->c->aborted) {
-                        apr_brigade_destroy(split);
                         return rv;
                     }
-                    b = split;
+                    APR_BRIGADE_CONCAT(b, ctx->tmpbb);
                     e = APR_BRIGADE_FIRST(b);
 
                     ctx->data_sent = 1;
@@ -1402,6 +1403,7 @@ AP_DECLARE(size_t) ap_send_mmap(apr_mmap_t *mm, request_rec *r, size_t offset,
 
 typedef struct {
     apr_bucket_brigade *bb;
+    apr_bucket_brigade *tmpbb;
 } old_write_filter_ctx;
 
 AP_CORE_DECLARE_NONSTD(apr_status_t) ap_old_write_filter(
@@ -1422,16 +1424,11 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_old_write_filter(
     return ap_pass_brigade(f->next, bb);
 }
 
-static apr_status_t buffer_output(request_rec *r,
-                                  const char *str, apr_size_t len)
+static ap_filter_t *insert_old_write_filter(request_rec *r)
 {
-    conn_rec *c = r->connection;
     ap_filter_t *f;
     old_write_filter_ctx *ctx;
 
-    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.
      */
@@ -1445,24 +1442,41 @@ static apr_status_t buffer_output(request_rec *r,
     if (f == NULL) {
         /* our filter hasn't been added yet */
         ctx = apr_pcalloc(r->pool, sizeof(*ctx));
+        ctx->tmpbb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
+
         ap_add_output_filter("OLD_WRITE", ctx, r, r->connection);
         f = r->output_filters;
     }
 
+    return f;
+}
+
+static apr_status_t buffer_output(request_rec *r,
+                                  const char *str, apr_size_t len)
+{
+    conn_rec *c = r->connection;
+    ap_filter_t *f;
+    old_write_filter_ctx *ctx;
+
+    if (len == 0)
+        return APR_SUCCESS;
+
+    f = insert_old_write_filter(r);
+    ctx = f->ctx;
+
     /* if the first filter is not our buffering filter, then we have to
      * deliver the content through the normal filter chain
      */
     if (f != r->output_filters) {
-        apr_bucket_brigade *bb = apr_brigade_create(r->pool, c->bucket_alloc);
+        apr_status_t rv;
         apr_bucket *b = apr_bucket_transient_create(str, len, c->bucket_alloc);
-        APR_BRIGADE_INSERT_TAIL(bb, b);
+        APR_BRIGADE_INSERT_TAIL(ctx->tmpbb, b);
 
-        return ap_pass_brigade(r->output_filters, bb);
+        rv = ap_pass_brigade(r->output_filters, ctx->tmpbb);
+        apr_brigade_cleanup(ctx->tmpbb);
+        return rv;
     }
 
-    /* grab the context from our filter */
-    ctx = r->output_filters->ctx;
-
     if (ctx->bb == NULL) {
         ctx->bb = apr_brigade_create(r->pool, c->bucket_alloc);
     }
@@ -1617,13 +1631,20 @@ AP_DECLARE_NONSTD(int) ap_rvputs(request_rec *r, ...)
 AP_DECLARE(int) ap_rflush(request_rec *r)
 {
     conn_rec *c = r->connection;
-    apr_bucket_brigade *bb;
     apr_bucket *b;
+    ap_filter_t *f;
+    old_write_filter_ctx *ctx;
+    apr_status_t rv;
+
+    f = insert_old_write_filter(r);
+    ctx = f->ctx;
 
-    bb = apr_brigade_create(r->pool, c->bucket_alloc);
     b = apr_bucket_flush_create(c->bucket_alloc);
-    APR_BRIGADE_INSERT_TAIL(bb, b);
-    if (ap_pass_brigade(r->output_filters, bb) != APR_SUCCESS)
+    APR_BRIGADE_INSERT_TAIL(ctx->tmpbb, b);
+
+    rv = ap_pass_brigade(r->output_filters, ctx->tmpbb);
+    apr_brigade_cleanup(ctx->tmpbb);
+    if (rv != APR_SUCCESS)
         return -1;
 
     return 0;