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/24 04:39:52 UTC
svn commit: r327925 - in /httpd/httpd/trunk: CHANGES include/http_request.h
modules/http/http_core.c modules/http/http_request.c server/Makefile.in
server/eor_bucket.c
Author: brianp
Date: Sun Oct 23 19:39:49 2005
New Revision: 327925
URL: http://svn.apache.org/viewcvs?rev=327925&view=rev
Log:
Redesign of request cleanup and logging to use End-Of-Request bucket
(backport from async-dev branch to 2.3 trunk)
Added:
httpd/httpd/trunk/server/eor_bucket.c
Modified:
httpd/httpd/trunk/CHANGES
httpd/httpd/trunk/include/http_request.h
httpd/httpd/trunk/modules/http/http_core.c
httpd/httpd/trunk/modules/http/http_request.c
httpd/httpd/trunk/server/Makefile.in
Modified: httpd/httpd/trunk/CHANGES
URL: http://svn.apache.org/viewcvs/httpd/httpd/trunk/CHANGES?rev=327925&r1=327924&r2=327925&view=diff
==============================================================================
--- httpd/httpd/trunk/CHANGES [utf-8] (original)
+++ httpd/httpd/trunk/CHANGES [utf-8] Sun Oct 23 19:39:49 2005
@@ -2,6 +2,12 @@
Changes with Apache 2.3.0
[Remove entries to the current 2.0 and 2.2 section below, when backported]
+ *) 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
+ of the response is sent; ap_core_output_filter() calls the access logger
+ indirectly when it destroys the EOR bucket. [Brian Pane]
+
*) Rewrite of logresolve support utility: IPv6 addresses are now supported
and the format of statistical output has changed. [Colm MacCarthaigh]
Modified: httpd/httpd/trunk/include/http_request.h
URL: http://svn.apache.org/viewcvs/httpd/httpd/trunk/include/http_request.h?rev=327925&r1=327924&r2=327925&view=diff
==============================================================================
--- httpd/httpd/trunk/include/http_request.h (original)
+++ httpd/httpd/trunk/include/http_request.h Sun Oct 23 19:39:49 2005
@@ -237,12 +237,21 @@
#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
* @param type Why the request is dieing
* @param r The current request
@@ -353,6 +362,36 @@
AP_DECLARE(int) ap_location_walk(request_rec *r);
AP_DECLARE(int) ap_directory_walk(request_rec *r);
AP_DECLARE(int) ap_file_walk(request_rec *r);
+
+/** End Of REQUEST (EOR) bucket */
+AP_DECLARE_DATA extern const apr_bucket_type_t ap_bucket_type_eor;
+
+/**
+ * Determine if a bucket is an End Of REQUEST (EOR) bucket
+ * @param e The bucket to inspect
+ * @return true or false
+ */
+#define AP_BUCKET_IS_EOR(e) (e->type == &ap_bucket_type_eor)
+
+/**
+ * Make the bucket passed in an End Of REQUEST (EOR) bucket
+ * @param b The bucket to make into an EOR bucket
+ * @param r The request to destroy when this bucket is destroyed
+ * @return The new bucket, or NULL if allocation failed
+ */
+AP_DECLARE(apr_bucket *) ap_bucket_eor_make(apr_bucket *b, request_rec *r);
+
+/**
+ * Create a bucket referring to an End Of REQUEST (EOR). This bucket
+ * holds a pointer to the request_rec, so that the request can be
+ * destroyed right after all of the output has been sent to the client.
+ *
+ * @param list The freelist from which this bucket should be allocated
+ * @param r The request to destroy when this bucket is destroyed
+ * @return The new bucket, or NULL if allocation failed
+ */
+AP_DECLARE(apr_bucket *) ap_bucket_eor_create(apr_bucket_alloc_t *list,
+ request_rec *r);
#ifdef __cplusplus
}
Modified: httpd/httpd/trunk/modules/http/http_core.c
URL: http://svn.apache.org/viewcvs/httpd/httpd/trunk/modules/http/http_core.c?rev=327925&r1=327924&r2=327925&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http/http_core.c (original)
+++ httpd/httpd/trunk/modules/http/http_core.c Sun Oct 23 19:39:49 2005
@@ -142,7 +142,6 @@
cs->state = CONN_STATE_READ_REQUEST_LINE;
}
- apr_pool_destroy(r->pool);
}
else { /* ap_read_request failed - client may have closed */
cs->state = CONN_STATE_LINGER;
@@ -182,7 +181,6 @@
break;
ap_update_child_status(c->sbh, SERVER_BUSY_KEEPALIVE, r);
- apr_pool_destroy(r->pool);
if (ap_graceful_stop_signalled())
break;
Modified: httpd/httpd/trunk/modules/http/http_request.c
URL: http://svn.apache.org/viewcvs/httpd/httpd/trunk/modules/http/http_request.c?rev=327925&r1=327924&r2=327925&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http/http_request.c (original)
+++ httpd/httpd/trunk/modules/http/http_request.c Sun Oct 23 19:39:49 2005
@@ -191,25 +191,24 @@
ap_send_error_response(r_1st_err, recursive_error);
}
-static void check_pipeline_flush(request_rec *r)
+static void check_pipeline_flush(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);
+ bb = apr_brigade_create(c->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) {
+ 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 */
}
@@ -228,12 +227,16 @@
* if something hasn't been sent to the network yet.
*/
APR_BRIGADE_INSERT_HEAD(bb, e);
- ap_pass_brigade(r->connection->output_filters, bb);
+ ap_pass_brigade(c->output_filters, bb);
}
+
void ap_process_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.
@@ -270,19 +273,25 @@
else {
ap_die(access_status, r);
}
-
- /*
- * 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.
+
+ /* Send an EOR bucket through the output filter chain. When
+ * this bucket is destroyed, the request will be logged and
+ * its pool will be freed
*/
- check_pipeline_flush(r);
- ap_update_child_status(r->connection->sbh, SERVER_BUSY_LOG, r);
- ap_run_log_transaction(r);
+ bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
+ b = ap_bucket_eor_create(r->connection->bucket_alloc, r);
+ APR_BRIGADE_INSERT_HEAD(bb, b);
+ ap_pass_brigade(r->connection->output_filters, bb);
+
+ /* From here onward, it is no longer safe to reference r
+ * or r->pool, because r->pool may have been destroyed
+ * already by the EOR bucket's cleanup function.
+ */
+
+ c->cs->state = CONN_STATE_WRITE_COMPLETION;
+ check_pipeline_flush(c);
if (ap_extended_status)
- ap_time_process_request(r->connection->sbh, STOP_PREQUEST);
+ ap_time_process_request(c->sbh, STOP_PREQUEST);
}
static apr_table_t *rename_original_env(apr_pool_t *p, apr_table_t *t)
Modified: httpd/httpd/trunk/server/Makefile.in
URL: http://svn.apache.org/viewcvs/httpd/httpd/trunk/server/Makefile.in?rev=327925&r1=327924&r2=327925&view=diff
==============================================================================
--- httpd/httpd/trunk/server/Makefile.in (original)
+++ httpd/httpd/trunk/server/Makefile.in Sun Oct 23 19:39:49 2005
@@ -14,7 +14,7 @@
mpm_common.c util_charset.c util_debug.c util_xml.c \
util_filter.c util_pcre.c exports.c \
scoreboard.c error_bucket.c protocol.c core.c request.c provider.c \
- eoc_bucket.c core_filters.c
+ eoc_bucket.c eor_bucket.c core_filters.c
TARGETS = delete-exports $(LTLIBRARY_NAME) $(CORE_IMPLIB_FILE) export_vars.h httpd.exp
Added: httpd/httpd/trunk/server/eor_bucket.c
URL: http://svn.apache.org/viewcvs/httpd/httpd/trunk/server/eor_bucket.c?rev=327925&view=auto
==============================================================================
--- httpd/httpd/trunk/server/eor_bucket.c (added)
+++ httpd/httpd/trunk/server/eor_bucket.c Sun Oct 23 19:39:49 2005
@@ -0,0 +1,66 @@
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "httpd.h"
+#include "http_request.h"
+
+static apr_status_t eor_bucket_read(apr_bucket *b, const char **str,
+ apr_size_t *len, apr_read_type_e block)
+{
+ *str = NULL;
+ *len = 0;
+ return APR_SUCCESS;
+}
+
+AP_DECLARE(apr_bucket *) ap_bucket_eor_make(apr_bucket *b, request_rec *r)
+{
+ b->length = 0;
+ b->start = 0;
+ b->data = r;
+ b->type = &ap_bucket_type_eor;
+
+ return b;
+}
+
+AP_DECLARE(apr_bucket *) ap_bucket_eor_create(apr_bucket_alloc_t *list,
+ request_rec *r)
+{
+ apr_bucket *b = apr_bucket_alloc(sizeof(*b), list);
+
+ APR_BUCKET_INIT(b);
+ b->free = apr_bucket_free;
+ b->list = list;
+ return ap_bucket_eor_make(b, r);
+}
+
+static void eor_bucket_destroy(void *data)
+{
+ request_rec *r = (request_rec *)data;
+ if (r != NULL) {
+ ap_run_log_transaction(r);
+ apr_pool_destroy(r->pool);
+ }
+}
+
+AP_DECLARE_DATA const apr_bucket_type_t ap_bucket_type_eor = {
+ "EOR", 5, APR_BUCKET_METADATA,
+ eor_bucket_destroy,
+ eor_bucket_read,
+ apr_bucket_setaside_noop,
+ apr_bucket_split_notimpl,
+ apr_bucket_simple_copy
+};
+