From: Brian Pane Date: Fri, 25 Oct 2002 06:52:02 +0000 (+0000) Subject: mod_logio modification: count bytes-sent after the writev or sendfile X-Git-Tag: 2.0.44~223 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=816177d6ecd19c83852f6260493785d9de6b0a84;p=thirdparty%2Fapache%2Fhttpd.git mod_logio modification: count bytes-sent after the writev or sendfile call in the core_output_filter, in order to get a more accurate count of the total bytes transmitted in cases where the client terminates the connection before the entire response is sent. Note: This works by adding a flush bucket to each response when mod_logio is used; the side-effect is that pipelined responses get broken up into separate network writes per request (but there's no impact on pipelining when mod_logio is not enabled). Submitted by: Bojan Smojver Reviewed by: Brian Pane git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@97300 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index 4e732e0e809..56f79206129 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,9 @@ Changes with Apache 2.0.44 + *) More accurate logging of bytes sent in mod_logio when + the client terminates the connection before the response + is completely sent [Bojan Smojver ] + *) Fix some problems in the perchild MPM. [Jonas Eriksson ] diff --git a/include/http_core.h b/include/http_core.h index 98feebfb537..b4ae82ed53b 100644 --- a/include/http_core.h +++ b/include/http_core.h @@ -61,6 +61,7 @@ #include "apr.h" #include "apr_hash.h" +#include "apr_optional.h" #include "util_filter.h" #if APR_HAVE_STRUCT_RLIMIT @@ -626,6 +627,16 @@ AP_DECLARE_HOOK(int, get_mgmt_items, /* ---------------------------------------------------------------------- */ +/* ---------------------------------------------------------------------- + * + * I/O logging with mod_logio + */ + +APR_DECLARE_OPTIONAL_FN(void, ap_logio_add_bytes_out, + (conn_rec *c, apr_off_t bytes)); + +/* ---------------------------------------------------------------------- */ + #ifdef __cplusplus } #endif diff --git a/modules/loggers/mod_logio.c b/modules/loggers/mod_logio.c index 64c364d4b61..ea922e016d3 100644 --- a/modules/loggers/mod_logio.c +++ b/modules/loggers/mod_logio.c @@ -79,6 +79,7 @@ #include "ap_config.h" #include "mod_log_config.h" #include "httpd.h" +#include "http_core.h" #include "http_config.h" #include "http_protocol.h" @@ -95,6 +96,16 @@ typedef struct logio_config_t { apr_off_t bytes_out; } logio_config_t; +/* + * Optional function for the core to add to bytes_out + */ + +static void ap_logio_add_bytes_out(conn_rec *c, apr_off_t bytes){ + logio_config_t *cf = ap_get_module_config(c->conn_config, &logio_module); + + cf->bytes_out += bytes; +} + /* * Format items... */ @@ -133,24 +144,6 @@ static int logio_transaction(request_rec *r) * Logging of input and output filters... */ -static apr_status_t logio_out_filter(ap_filter_t *f, - apr_bucket_brigade *bb) { - apr_off_t length; - logio_config_t *cf = ap_get_module_config(f->c->conn_config, &logio_module); - - if (!cf) { /* Create config */ - cf = apr_pcalloc(f->c->pool, sizeof(*cf)); - ap_set_module_config(f->c->conn_config, &logio_module, cf); - } - - apr_brigade_length (bb, 0, &length); - - if (length > 0) - cf->bytes_out += length; - - return ap_pass_brigade(f->next, bb); -} - static apr_status_t logio_in_filter(ap_filter_t *f, apr_bucket_brigade *bb, ap_input_mode_t mode, @@ -162,11 +155,6 @@ static apr_status_t logio_in_filter(ap_filter_t *f, status = ap_get_brigade(f->next, bb, mode, block, readbytes); - if (!cf) { /* Create config */ - cf = apr_pcalloc(f->c->pool, sizeof(*cf)); - ap_set_module_config(f->c->conn_config, &logio_module, cf); - } - apr_brigade_length (bb, 0, &length); if (length > 0) @@ -175,11 +163,30 @@ static apr_status_t logio_in_filter(ap_filter_t *f, return status; } +static apr_status_t logio_out_filter(ap_filter_t *f, + apr_bucket_brigade *bb) { + apr_bucket *b = APR_BRIGADE_LAST(bb); + + /* End of data, make sure we flush */ + if (APR_BUCKET_IS_EOS(b)) { + APR_BRIGADE_INSERT_TAIL(bb, + apr_bucket_flush_create(f->c->bucket_alloc)); + APR_BUCKET_REMOVE(b); + apr_bucket_destroy(b); + } + + return ap_pass_brigade(f->next, bb); +} + /* * The hooks... */ static int logio_pre_conn(conn_rec *c) { + logio_config_t *cf = apr_pcalloc(c->pool, sizeof(*cf)); + + ap_set_module_config(c->conn_config, &logio_module, cf); + ap_add_input_filter(logio_filter_name, NULL, NULL, c); ap_add_output_filter(logio_filter_name, NULL, NULL, c); @@ -212,6 +219,8 @@ static void register_hooks(apr_pool_t *p) AP_FTYPE_NETWORK - 1); ap_register_output_filter(logio_filter_name, logio_out_filter, NULL, AP_FTYPE_NETWORK - 1); + + APR_REGISTER_OPTIONAL_FN(ap_logio_add_bytes_out); } module AP_MODULE_DECLARE_DATA logio_module = diff --git a/server/core.c b/server/core.c index 126795ffa26..e607a75b8fe 100644 --- a/server/core.c +++ b/server/core.c @@ -2737,6 +2737,7 @@ static apr_status_t sendfile_it_all(core_net_rec *c, apr_off_t file_offset, apr_size_t file_bytes_left, apr_size_t total_bytes_left, + apr_size_t *bytes_sent, apr_int32_t flags) { apr_status_t rv; @@ -2748,11 +2749,15 @@ static apr_status_t sendfile_it_all(core_net_rec *c, == APR_SUCCESS) && timeout > 0); /* socket must be in timeout mode */ + /* Reset the bytes_sent field */ + *bytes_sent = 0; + do { apr_size_t tmplen = file_bytes_left; rv = apr_sendfile(c->client_socket, fd, hdtr, &file_offset, &tmplen, flags); + *bytes_sent += tmplen; total_bytes_left -= tmplen; if (!total_bytes_left || rv != APR_SUCCESS) { return rv; /* normal case & error exit */ @@ -3647,6 +3652,11 @@ static int core_input_filter(ap_filter_t *f, apr_bucket_brigade *b, */ #define MAX_IOVEC_TO_WRITE 16 +/* Optional function coming from mod_logio, used for logging of output + * traffic + */ +static APR_OPTIONAL_FN_TYPE(ap_logio_add_bytes_out) *logio_add_bytes_out; + static apr_status_t core_output_filter(ap_filter_t *f, apr_bucket_brigade *b) { apr_status_t rv; @@ -3908,6 +3918,8 @@ static apr_status_t core_output_filter(ap_filter_t *f, apr_bucket_brigade *b) if (fd) { apr_hdtr_t hdtr; + apr_size_t bytes_sent; + #if APR_HAS_SENDFILE apr_int32_t flags = 0; #endif @@ -3938,25 +3950,35 @@ static apr_status_t core_output_filter(ap_filter_t *f, apr_bucket_brigade *b) sending from */ flen, /* length of file */ nbytes + flen, /* total length including - headers */ + headers */ + &bytes_sent, /* how many bytes were + sent */ flags); /* apr_sendfile flags */ + + if (logio_add_bytes_out && bytes_sent > 0) + logio_add_bytes_out(c, bytes_sent); } else #endif { - apr_size_t unused_bytes_sent; rv = emulate_sendfile(net, fd, &hdtr, foffset, flen, - &unused_bytes_sent); + &bytes_sent); + + if (logio_add_bytes_out && bytes_sent > 0) + logio_add_bytes_out(c, bytes_sent); } fd = NULL; } else { - apr_size_t unused_bytes_sent; + apr_size_t bytes_sent; rv = writev_it_all(net->client_socket, vec, nvec, - nbytes, &unused_bytes_sent); + nbytes, &bytes_sent); + + if (logio_add_bytes_out && bytes_sent > 0) + logio_add_bytes_out(c, bytes_sent); } apr_brigade_destroy(b); @@ -3988,6 +4010,8 @@ static apr_status_t core_output_filter(ap_filter_t *f, apr_bucket_brigade *b) static int core_post_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s) { + logio_add_bytes_out = APR_RETRIEVE_OPTIONAL_FN(ap_logio_add_bytes_out); + ap_set_version(pconf); ap_setup_make_content_type(pconf); return OK;