Loading CHANGES +2 −0 Original line number Diff line number Diff line -*- 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] Loading server/mpm/experimental/event/event.c +45 −11 Original line number Diff line number Diff line Loading @@ -164,7 +164,7 @@ static int sick_child_detected; 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; Loading Loading @@ -592,6 +592,7 @@ static int process_socket(apr_pool_t * p, apr_socket_t * sock, pt->status = 1; pt->baton = cs; cs->pfd.client_data = pt; APR_RING_ELEM_INIT(cs, timeout_list); ap_update_vhost_given_ip(c); Loading Loading @@ -621,6 +622,7 @@ static int process_socket(apr_pool_t * p, apr_socket_t * sock, else { c = cs->c; c->sbh = sbh; pt = cs->pfd.client_data; } read_request: Loading @@ -643,21 +645,30 @@ read_request: * 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()) { Loading Loading @@ -693,11 +704,12 @@ read_request: */ 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) { Loading Loading @@ -874,6 +886,7 @@ static void *listener_thread(apr_thread_t * thd, void *dummy) } 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, Loading Loading @@ -942,6 +955,8 @@ static void *listener_thread(apr_thread_t * thd, void *dummy) 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, Loading @@ -953,6 +968,7 @@ static void *listener_thread(apr_thread_t * thd, void *dummy) 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) { Loading Loading @@ -1037,9 +1053,10 @@ static void *listener_thread(apr_thread_t * thd, void *dummy) /* 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)) { Loading @@ -1058,8 +1075,25 @@ static void *listener_thread(apr_thread_t * thd, void *dummy) */ } 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 */ Loading Loading
CHANGES +2 −0 Original line number Diff line number Diff line -*- 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] Loading
server/mpm/experimental/event/event.c +45 −11 Original line number Diff line number Diff line Loading @@ -164,7 +164,7 @@ static int sick_child_detected; 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; Loading Loading @@ -592,6 +592,7 @@ static int process_socket(apr_pool_t * p, apr_socket_t * sock, pt->status = 1; pt->baton = cs; cs->pfd.client_data = pt; APR_RING_ELEM_INIT(cs, timeout_list); ap_update_vhost_given_ip(c); Loading Loading @@ -621,6 +622,7 @@ static int process_socket(apr_pool_t * p, apr_socket_t * sock, else { c = cs->c; c->sbh = sbh; pt = cs->pfd.client_data; } read_request: Loading @@ -643,21 +645,30 @@ read_request: * 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()) { Loading Loading @@ -693,11 +704,12 @@ read_request: */ 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) { Loading Loading @@ -874,6 +886,7 @@ static void *listener_thread(apr_thread_t * thd, void *dummy) } 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, Loading Loading @@ -942,6 +955,8 @@ static void *listener_thread(apr_thread_t * thd, void *dummy) 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, Loading @@ -953,6 +968,7 @@ static void *listener_thread(apr_thread_t * thd, void *dummy) 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) { Loading Loading @@ -1037,9 +1053,10 @@ static void *listener_thread(apr_thread_t * thd, void *dummy) /* 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)) { Loading @@ -1058,8 +1075,25 @@ static void *listener_thread(apr_thread_t * thd, void *dummy) */ } 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 */ Loading