]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
mod_logio modification: count bytes-sent after the writev or sendfile
authorBrian Pane <brianp@apache.org>
Fri, 25 Oct 2002 06:52:02 +0000 (06:52 +0000)
committerBrian Pane <brianp@apache.org>
Fri, 25 Oct 2002 06:52:02 +0000 (06:52 +0000)
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 <bojan@rexursive.com>
Reviewed by: Brian Pane

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@97300 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
include/http_core.h
modules/loggers/mod_logio.c
server/core.c

diff --git a/CHANGES b/CHANGES
index 4e732e0e80962c992d285f143840bffe3bb079d1..56f79206129ee15bc7d222a43a490f1769a24301 100644 (file)
--- 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 <bojan@rexursive.com>]
+
   *) Fix some problems in the perchild MPM.  
      [Jonas Eriksson <jonas@webkonsulterna.com>]
 
index 98feebfb537c9faaef5d8c2ac0518f496fd18c4b..b4ae82ed53bc409e394ea04b4b63b36bbf7e0636 100644 (file)
@@ -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
index 64c364d4b610db81cf0a5c841c809106c8d00a3b..ea922e016d3addef166793d760aa9480d382522a 100644 (file)
@@ -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 =
index 126795ffa26f6102716172fa527e37677c015f76..e607a75b8fe21c64b672529375a328916f47af37 100644 (file)
@@ -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;