httpd-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From bri...@apache.org
Subject svn commit: r307362 - in /httpd/httpd/branches/async-dev: CHANGES include/http_request.h modules/http/http_core.c modules/http/http_request.c server/mpm/experimental/event/event.c
Date Sun, 09 Oct 2005 04:49:56 GMT
Author: brianp
Date: Sat Oct  8 21:49:52 2005
New Revision: 307362

URL: http://svn.apache.org/viewcvs?rev=307362&view=rev
Log:
Refactored ap_process_request() so that in async MPMs, the MPM (and not
the httpd core) is responsible for write completion.

Note that, with this commit, the Event MPM is still doing write
completion synchronously.  I'll add async write completion as a
separate commit.

Note also that this commit breaks the (experimental) Leader/Followers
MPM on the (equally experimental) async-dev branch.  The fix is to add
either synchronous or asynchronous write completion to that MPM.  Rather
than hack in synchronous write completion, I'll revisit Leader/Followers
once I have async working in Event.

Modified:
    httpd/httpd/branches/async-dev/CHANGES
    httpd/httpd/branches/async-dev/include/http_request.h
    httpd/httpd/branches/async-dev/modules/http/http_core.c
    httpd/httpd/branches/async-dev/modules/http/http_request.c
    httpd/httpd/branches/async-dev/server/mpm/experimental/event/event.c

Modified: httpd/httpd/branches/async-dev/CHANGES
URL: http://svn.apache.org/viewcvs/httpd/httpd/branches/async-dev/CHANGES?rev=307362&r1=307361&r2=307362&view=diff
==============================================================================
--- httpd/httpd/branches/async-dev/CHANGES [utf-8] (original)
+++ httpd/httpd/branches/async-dev/CHANGES [utf-8] Sat Oct  8 21:49:52 2005
@@ -1,6 +1,9 @@
                                                         -*- coding: utf-8 -*-
 Changes in Apache 2.3.0 async-dev R&D branch
 
+  *) For asynchronous MPMs, moved responsibility for write completion from
+     the core to the MPM.  [Brian Pane]
+
   *) Added an End-Of-Request bucket type.  The logging of a request and
      the freeing of its pool are now done when the EOR bucket is destroyed.
      This has the effect of delaying the logging until right after the last

Modified: httpd/httpd/branches/async-dev/include/http_request.h
URL: http://svn.apache.org/viewcvs/httpd/httpd/branches/async-dev/include/http_request.h?rev=307362&r1=307361&r2=307362&view=diff
==============================================================================
--- httpd/httpd/branches/async-dev/include/http_request.h (original)
+++ httpd/httpd/branches/async-dev/include/http_request.h Sat Oct  8 21:49:52 2005
@@ -237,10 +237,19 @@
 
 #ifdef CORE_PRIVATE
 /**
- * Process a top-level request from a client
+ * Process a top-level request from a client, and synchronously write
+ * the response to the client
  * @param r The current request
  */
 void ap_process_request(request_rec *);
+
+/**
+ * Process a top-level request from a client, allowing some or all of
+ * the response to remain buffered in the core output filter for later,
+ * asynchronous write completion
+ * @param r The current request
+ */
+void ap_process_async_request(request_rec *);
 
 /**
  * Kill the current request

Modified: httpd/httpd/branches/async-dev/modules/http/http_core.c
URL: http://svn.apache.org/viewcvs/httpd/httpd/branches/async-dev/modules/http/http_core.c?rev=307362&r1=307361&r2=307362&view=diff
==============================================================================
--- httpd/httpd/branches/async-dev/modules/http/http_core.c (original)
+++ httpd/httpd/branches/async-dev/modules/http/http_core.c Sat Oct  8 21:49:52 2005
@@ -130,18 +130,9 @@
             if (ap_extended_status)
                 ap_increment_counts(c->sbh, r);
 
-            if (c->keepalive != AP_CONN_KEEPALIVE || c->aborted 
-                    || ap_graceful_stop_signalled()) {
+            if (cs->state != CONN_STATE_WRITE_COMPLETION) {
+                /* Something went wrong; close the connection */
                 cs->state = CONN_STATE_LINGER;
-            }
-            else if (!c->data_in_input_filters) {
-                cs->state = CONN_STATE_CHECK_REQUEST_LINE_READABLE;
-            }
-            else {
-                /* else we are pipelining.  Return to READ_REQUEST_LINE state
-                 *  and stay in the loop
-                 */
-                cs->state = CONN_STATE_READ_REQUEST_LINE;
             }
         }
         else {   /* ap_read_request failed - client may have closed */

Modified: httpd/httpd/branches/async-dev/modules/http/http_request.c
URL: http://svn.apache.org/viewcvs/httpd/httpd/branches/async-dev/modules/http/http_request.c?rev=307362&r1=307361&r2=307362&view=diff
==============================================================================
--- httpd/httpd/branches/async-dev/modules/http/http_request.c (original)
+++ httpd/httpd/branches/async-dev/modules/http/http_request.c Sat Oct  8 21:49:52 2005
@@ -191,51 +191,29 @@
     ap_send_error_response(r_1st_err, recursive_error);
 }
 
-static void check_pipeline_flush(request_rec *r)
+/* Check whether there's another request ready to be read
+ */
+static void check_pipeline(conn_rec *c)
 {
-    apr_bucket *e;
-    apr_bucket_brigade *bb;
-    conn_rec *c = r->connection;
-    /* ### if would be nice if we could PEEK without a brigade. that would
-       ### allow us to defer creation of the brigade to when we actually
-       ### need to send a FLUSH. */
-    bb = apr_brigade_create(r->pool, c->bucket_alloc);
-
-    /* Flush the filter contents if:
-     *
-     *   1) the connection will be closed
-     *   2) there isn't a request ready to be read
-     */
-    /* ### shouldn't this read from the connection input filters? */
     /* ### is zero correct? that means "read one line" */
-    if (r->connection->keepalive != AP_CONN_CLOSE) {
-        if (ap_get_brigade(r->input_filters, bb, AP_MODE_EATCRLF, 
+    if (c->keepalive != AP_CONN_CLOSE) {
+        apr_bucket_brigade *bb = apr_brigade_create(c->pool, c->bucket_alloc);
+        if (ap_get_brigade(c->input_filters, bb, AP_MODE_EATCRLF, 
                        APR_NONBLOCK_READ, 0) != APR_SUCCESS) {
             c->data_in_input_filters = 0;  /* we got APR_EOF or an error */
         }
         else {
             c->data_in_input_filters = 1;
-            return;    /* don't flush */
         }
     }
-
-        e = apr_bucket_flush_create(c->bucket_alloc);
-
-        /* We just send directly to the connection based filters.  At
-         * this point, we know that we have seen all of the data
-         * (request finalization sent an EOS bucket, which empties all
-         * of the request filters). We just want to flush the buckets
-         * if something hasn't been sent to the network yet.
-         */
-        APR_BRIGADE_INSERT_HEAD(bb, e);
-        ap_pass_brigade(r->connection->output_filters, bb);
 }
 
-void ap_process_request(request_rec *r)
+void ap_process_async_request(request_rec *r)
 {
     int access_status;
     apr_bucket_brigade *bb;
     apr_bucket *b;
+    conn_rec *c = r->connection;
 
     /* Give quick handlers a shot at serving the request on the fast
      * path, bypassing all of the other Apache hooks.
@@ -281,18 +259,28 @@
     b = ap_bucket_eor_create(r->connection->bucket_alloc, r);
     APR_BRIGADE_INSERT_HEAD(bb, b);
     ap_pass_brigade(r->connection->output_filters, bb);
+    c->cs->state = CONN_STATE_WRITE_COMPLETION;
+    check_pipeline(c);
+}
 
-    /*
-     * We want to flush the last packet if this isn't a pipelining connection
-     * *before* we start into logging.  Suppose that the logging causes a DNS
-     * lookup to occur, which may have a high latency.  If we hold off on
-     * this packet, then it'll appear like the link is stalled when really
-     * it's the application that's stalled.
-     */
-    check_pipeline_flush(r);
-    ap_update_child_status(r->connection->sbh, SERVER_BUSY_LOG, r);
-    if (ap_extended_status)
+void ap_process_request(request_rec *r)
+{
+    apr_bucket_brigade *bb;
+    apr_bucket *b;
+    conn_rec *c = r->connection;
+
+    ap_process_async_request(r);
+
+    if (!c->data_in_input_filters) {
+        bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
+        b = apr_bucket_flush_create(c->bucket_alloc);
+        APR_BRIGADE_INSERT_HEAD(bb, b);
+        ap_pass_brigade(r->connection->output_filters, bb);
+        ap_update_child_status(r->connection->sbh, SERVER_BUSY_LOG, r);
+    }
+    if (ap_extended_status) {
         ap_time_process_request(r->connection->sbh, STOP_PREQUEST);
+    }
 }
 
 static apr_table_t *rename_original_env(apr_pool_t *p, apr_table_t *t)

Modified: httpd/httpd/branches/async-dev/server/mpm/experimental/event/event.c
URL: http://svn.apache.org/viewcvs/httpd/httpd/branches/async-dev/server/mpm/experimental/event/event.c?rev=307362&r1=307361&r2=307362&view=diff
==============================================================================
--- httpd/httpd/branches/async-dev/server/mpm/experimental/event/event.c (original)
+++ httpd/httpd/branches/async-dev/server/mpm/experimental/event/event.c Sat Oct  8 21:49:52
2005
@@ -636,6 +636,27 @@
             cs->state = CONN_STATE_LINGER;
         }
     }
+    
+    if (cs->state == CONN_STATE_WRITE_COMPLETION) {
+        /* For now, do blocking writes in this thread to transfer the
+         * rest of the response.  TODO: Hand off this connection to a
+         * pollset for asynchronous write completion.
+         */
+        apr_bucket_brigade *bb = apr_brigade_create(c->pool, c->bucket_alloc);
+        apr_bucket *b = apr_bucket_flush_create(c->bucket_alloc);
+        APR_BRIGADE_INSERT_HEAD(bb, b);
+        ap_pass_brigade(c->output_filters, bb);
+        if (c->keepalive != AP_CONN_KEEPALIVE || c->aborted || 
+            ap_graceful_stop_signalled()) {
+            c->cs->state = CONN_STATE_LINGER;
+        }
+        else if (c->data_in_input_filters) {
+            cs->state = CONN_STATE_READ_REQUEST_LINE;
+        }
+        else {
+            cs->state = CONN_STATE_CHECK_REQUEST_LINE_READABLE;
+        }
+    }
 
     if (cs->state == CONN_STATE_LINGER) {
         ap_lingering_close(c);



Mime
View raw message