You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by yl...@apache.org on 2018/10/24 15:06:04 UTC

svn commit: r1844780 - /httpd/httpd/trunk/server/request.c

Author: ylavic
Date: Wed Oct 24 15:06:04 2018
New Revision: 1844780

URL: http://svn.apache.org/viewvc?rev=1844780&view=rev
Log:
request: forward as much buckets as possible in ap_request_core_filter().

This improves performances while still preventing morphing buckets bound to
r->pool from reaching connection filters.

Modified:
    httpd/httpd/trunk/server/request.c

Modified: httpd/httpd/trunk/server/request.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/server/request.c?rev=1844780&r1=1844779&r2=1844780&view=diff
==============================================================================
--- httpd/httpd/trunk/server/request.c (original)
+++ httpd/httpd/trunk/server/request.c Wed Oct 24 15:06:04 2018
@@ -2066,9 +2066,13 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_
 AP_CORE_DECLARE_NONSTD(apr_status_t) ap_request_core_filter(ap_filter_t *f,
                                                             apr_bucket_brigade *bb)
 {
-    apr_bucket *flush_upto = NULL;
     apr_status_t status = APR_SUCCESS;
+    apr_read_type_e block = APR_NONBLOCK_READ;
+    conn_rec *c = f->r->connection;
+    apr_bucket *flush_upto = NULL;
     apr_bucket_brigade *tmp_bb;
+    apr_size_t tmp_bb_len = 0;
+    core_server_config *conf;
     int seen_eor = 0;
 
     /*
@@ -2080,6 +2084,8 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_
         return ap_pass_brigade(f->next, bb);
     }
 
+    conf = ap_get_core_module_config(f->r->server->module_config);
+
     /* Reinstate any buffered content */
     ap_filter_reinstate_brigade(f, bb, &flush_upto);
 
@@ -2092,6 +2098,7 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_
     /* Don't touch *bb after seen_eor */
     while (status == APR_SUCCESS && !seen_eor && !APR_BRIGADE_EMPTY(bb)) {
         apr_bucket *bucket = APR_BRIGADE_FIRST(bb);
+        int do_pass = 0;
 
         if (AP_BUCKET_IS_EOR(bucket)) {
             /* pass out everything and never come back again,
@@ -2116,31 +2123,61 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_
              * something safe to pass down to the connection filters without
              * needing to be set aside.
              */
-            if (!APR_BUCKET_IS_METADATA(bucket)
-                    && bucket->length == (apr_size_t)-1) {
+            if (bucket->length == (apr_size_t)-1) {
                 const char *data;
                 apr_size_t size;
-                status = apr_bucket_read(bucket, &data, &size, APR_BLOCK_READ);
+
+                status = apr_bucket_read(bucket, &data, &size, block);
                 if (status != APR_SUCCESS) {
-                    break;
+                    if (!APR_STATUS_IS_EAGAIN(status)
+                            || block != APR_NONBLOCK_READ) {
+                        break;
+                    }
+                    /* Flush everything so far and retry in blocking mode */
+                    bucket = apr_bucket_flush_create(c->bucket_alloc);
+                    block = APR_BLOCK_READ;
+                }
+                else {
+                    tmp_bb_len += size;
+                    block = APR_NONBLOCK_READ;
                 }
             }
+            else {
+                tmp_bb_len += bucket->length;
+            }
 
-            /* pass each bucket down the chain */
+            /* move the bucket to tmp_bb and check whether it exhausts bb or
+             * brings tmp_bb above the limit; in both cases it's time to pass
+             * everything down the chain.
+             */
             APR_BUCKET_REMOVE(bucket);
             APR_BRIGADE_INSERT_TAIL(tmp_bb, bucket);
+            if (APR_BRIGADE_EMPTY(bb)
+                    || APR_BUCKET_IS_FLUSH(bucket)
+                    || tmp_bb_len >= conf->flush_max_threshold) {
+                do_pass = 1;
+            }
         }
 
-        status = ap_pass_brigade(f->next, tmp_bb);
-        apr_brigade_cleanup(tmp_bb);
+        if (do_pass || seen_eor) {
+            status = ap_pass_brigade(f->next, tmp_bb);
+            apr_brigade_cleanup(tmp_bb);
+            tmp_bb_len = 0;
+        }
     }
 
-    ap_release_brigade(f->c, tmp_bb);
-
     /* Don't touch *bb after seen_eor */
-    if (status == APR_SUCCESS && !seen_eor) {
-        status = ap_filter_setaside_brigade(f, bb);
+    if (!seen_eor) {
+        apr_status_t rv;
+        APR_BRIGADE_PREPEND(bb, tmp_bb);
+        rv = ap_filter_setaside_brigade(f, bb);
+        if (status == APR_SUCCESS) {
+            status = rv;
+        }
     }
+
+    ap_release_brigade(f->c, tmp_bb);
+
     return status;
 }