You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by br...@apache.org on 2005/10/10 05:49:35 UTC

svn commit: r312536 - in /httpd/httpd/branches/async-dev: CHANGES server/mpm/experimental/event/event.c

Author: brianp
Date: Sun Oct  9 20:49:31 2005
New Revision: 312536

URL: http://svn.apache.org/viewcvs?rev=312536&view=rev
Log:
Enabled async write completion in the Event MPM

Modified:
    httpd/httpd/branches/async-dev/CHANGES
    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=312536&r1=312535&r2=312536&view=diff
==============================================================================
--- httpd/httpd/branches/async-dev/CHANGES [utf-8] (original)
+++ httpd/httpd/branches/async-dev/CHANGES [utf-8] Sun Oct  9 20:49:31 2005
@@ -1,6 +1,8 @@
                                                         -*- coding: utf-8 -*-
 Changes in Apache 2.3.0 async-dev R&D branch
 
+  *) Added asynchronous write completion for Event MPM.  [Brian Pane]
+
   *) For asynchronous MPMs, moved responsibility for write completion from
      the core to the MPM.  [Brian Pane]
 

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=312536&r1=312535&r2=312536&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 Sun Oct  9 20:49:31 2005
@@ -164,7 +164,7 @@
 
 apr_thread_mutex_t *timeout_mutex;
 APR_RING_HEAD(timeout_head_t, conn_state_t);
-static struct timeout_head_t timeout_head;
+static struct timeout_head_t timeout_head, keepalive_timeout_head;
 
 static apr_pollset_t *event_pollset;
 
@@ -592,6 +592,7 @@
         pt->status = 1;
         pt->baton = cs;
         cs->pfd.client_data = pt;
+        APR_RING_ELEM_INIT(cs, timeout_list);
 
         ap_update_vhost_given_ip(c);
 
@@ -621,6 +622,7 @@
     else {
         c = cs->c;
         c->sbh = sbh;
+        pt = cs->pfd.client_data;
     }
 
 read_request:
@@ -643,21 +645,30 @@
          * 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);
         ap_filter_t *output_filter = c->output_filters;
         apr_status_t rv;
-        APR_BRIGADE_INSERT_HEAD(bb, b);
         while (output_filter->next != NULL) {
             output_filter = output_filter->next;
         }
-        rv = output_filter->frec->filter_func.out_func(output_filter, bb);
+        rv = output_filter->frec->filter_func.out_func(output_filter, NULL);
         if (rv != APR_SUCCESS) {
-            /* XXX log error */
+            ap_log_error(APLOG_MARK, APLOG_WARNING, rv, ap_server_conf,
+                     "core output filter");
             cs->state = CONN_STATE_LINGER;
         }
         else if (c->data_in_output_filters) {
-            cs->state = CONN_STATE_WRITE_COMPLETION;
+            /* Still in WRITE_COMPLETION_STATE:
+             * Set a write timeout for this connection, and let the
+             * event thread poll for writeability.
+             */
+            cs->expiration_time = ap_server_conf->timeout + time_now;
+            apr_thread_mutex_lock(timeout_mutex);
+            APR_RING_INSERT_TAIL(&timeout_head, cs, conn_state_t, timeout_list);
+            apr_thread_mutex_unlock(timeout_mutex);
+            pt->status = 0;
+            cs->pfd.reqevents = APR_POLLOUT | APR_POLLHUP | APR_POLLERR;
+            rc = apr_pollset_add(event_pollset, &cs->pfd);
+            return 1;
         }
         else if (c->keepalive != AP_CONN_KEEPALIVE || c->aborted || 
             ap_graceful_stop_signalled()) {
@@ -693,11 +704,12 @@
          */
         cs->expiration_time = ap_server_conf->keep_alive_timeout + time_now;
         apr_thread_mutex_lock(timeout_mutex);
-        APR_RING_INSERT_TAIL(&timeout_head, cs, conn_state_t, timeout_list);
+        APR_RING_INSERT_TAIL(&keepalive_timeout_head, cs, conn_state_t, timeout_list);
         apr_thread_mutex_unlock(timeout_mutex);
 
         pt->status = 0;
-        /* Add work to pollset. These are always read events */
+        /* Add work to pollset. */
+        cs->pfd.reqevents = APR_POLLIN;
         rc = apr_pollset_add(event_pollset, &cs->pfd);
 
         if (rc != APR_SUCCESS) {
@@ -874,6 +886,7 @@
     }
 
     APR_RING_INIT(&timeout_head, conn_state_t, timeout_list);
+    APR_RING_INIT(&keepalive_timeout_head, conn_state_t, timeout_list);
 
     /* Create the main pollset */
     rc = apr_pollset_create(&event_pollset,
@@ -942,6 +955,8 @@
                 case CONN_STATE_CHECK_REQUEST_LINE_READABLE:
                     cs->state = CONN_STATE_READ_REQUEST_LINE;
                     break;
+                case CONN_STATE_WRITE_COMPLETION:
+                    break;
                 default:
                     ap_log_error(APLOG_MARK, APLOG_ERR, rc,
                                  ap_server_conf,
@@ -953,6 +968,7 @@
                 apr_thread_mutex_lock(timeout_mutex);
                 APR_RING_REMOVE(cs, timeout_list);
                 apr_thread_mutex_unlock(timeout_mutex);
+                APR_RING_ELEM_INIT(cs, timeout_list);
 
                 rc = push2worker(out_pfd, event_pollset);
                 if (rc != APR_SUCCESS) {
@@ -1037,9 +1053,10 @@
         /* handle timed out sockets */
         apr_thread_mutex_lock(timeout_mutex);
 
-        cs = APR_RING_FIRST(&timeout_head);
+        /* Step 1: keepalive timeouts */
+        cs = APR_RING_FIRST(&keepalive_timeout_head);
         timeout_time = time_now + TIMEOUT_FUDGE_FACTOR;
-        while (!APR_RING_EMPTY(&timeout_head, conn_state_t, timeout_list)
+        while (!APR_RING_EMPTY(&keepalive_timeout_head, conn_state_t, timeout_list)
                && cs->expiration_time < timeout_time
                && get_worker(&have_idle_worker)) {
 
@@ -1058,8 +1075,25 @@
                  */
             }
             have_idle_worker = 0;
+            cs = APR_RING_FIRST(&keepalive_timeout_head);
+        }
+
+        /* Step 2: write completion timeouts */
+        cs = APR_RING_FIRST(&timeout_head);
+        while (!APR_RING_EMPTY(&timeout_head, conn_state_t, timeout_list)
+               && cs->expiration_time < timeout_time
+               && get_worker(&have_idle_worker)) {
+
+            cs->state = CONN_STATE_LINGER;
+            APR_RING_REMOVE(cs, timeout_list);
+            rc = push2worker(&cs->pfd, event_pollset);
+            if (rc != APR_SUCCESS) {
+                return NULL;
+            }
+            have_idle_worker = 0;
             cs = APR_RING_FIRST(&timeout_head);
         }
+
         apr_thread_mutex_unlock(timeout_mutex);
 
     }     /* listener main loop */