OK, this is my first "official" attempt at this. The basic idea is to replace
the EOS bucket at the end of the brigade with a FLUSH bucket, so that each
request is flushed down the pipe. I'm guessing this will completely break
pipelining if mod_logio is enabled, but, as someone mentioned, this is a
workaround, not a solution (hopefully 2.2 will have that :-)
The patch is otherwise the same as before (my first version) with one
difference: there is now an output filter in mod_logio.c. It's sole purpose is
to do the above. It runs just before the network filters.
Let me know what you think.
Bojan
diff -u --recursive --new-file httpd-2.0-vanilla/include/ap_mmn.h
httpd-2.0/include/ap_mmn.h
--- httpd-2.0-vanilla/include/ap_mmn.h Wed Sep 4 14:12:20 2002
+++ httpd-2.0/include/ap_mmn.h Thu Oct 17 12:36:11 2002
@@ -111,12 +111,13 @@
* 20020625 (2.0.40-dev) Changed conn_rec->keepalive to an enumeration
* 20020628 (2.0.40-dev) Added filter_init to filter registration functions
* 20020903 (2.0.41-dev) APR's error constants changed
+ * 20021014 (2.0.44-dev) conn_rec gets bytes_in and bytes_out fields
*/
#define MODULE_MAGIC_COOKIE 0x41503230UL /* "AP20" */
#ifndef MODULE_MAGIC_NUMBER_MAJOR
-#define MODULE_MAGIC_NUMBER_MAJOR 20020903
+#define MODULE_MAGIC_NUMBER_MAJOR 20021014
#endif
#define MODULE_MAGIC_NUMBER_MINOR 0 /* 0...n */
diff -u --recursive --new-file httpd-2.0-vanilla/include/httpd.h
httpd-2.0/include/httpd.h
--- httpd-2.0-vanilla/include/httpd.h Sat Oct 12 02:12:28 2002
+++ httpd-2.0/include/httpd.h Thu Oct 17 12:36:11 2002
@@ -1018,6 +1018,10 @@
void *sbh;
/** The bucket allocator to use for all bucket/brigade creations */
struct apr_bucket_alloc_t *bucket_alloc;
+ /** Input bytes on this connection */
+ apr_off_t bytes_in;
+ /** Output bytes on this connection */
+ apr_off_t bytes_out;
};
/* Per-vhost config... */
diff -u --recursive --new-file httpd-2.0-vanilla/modules/loggers/mod_logio.c
httpd-2.0/modules/loggers/mod_logio.c
--- httpd-2.0-vanilla/modules/loggers/mod_logio.c Sat Sep 28 14:18:35 2002
+++ httpd-2.0/modules/loggers/mod_logio.c Thu Oct 17 12:48:30 2002
@@ -87,32 +87,17 @@
static const char logio_filter_name[] = "LOG_INPUT_OUTPUT";
/*
- * Logging of input and output config...
- */
-
-typedef struct logio_config_t {
- apr_off_t bytes_in;
- apr_off_t bytes_out;
-} logio_config_t;
-
-/*
* Format items...
*/
static const char *log_bytes_in(request_rec *r, char *a)
{
- logio_config_t *cf = ap_get_module_config(r->connection->conn_config,
- &logio_module);
-
- return apr_off_t_toa(r->pool, cf->bytes_in);
+ return apr_off_t_toa(r->pool, r->connection->bytes_in);
}
static const char *log_bytes_out(request_rec *r, char *a)
{
- logio_config_t *cf = ap_get_module_config(r->connection->conn_config,
- &logio_module);
-
- return apr_off_t_toa(r->pool, cf->bytes_out);
+ return apr_off_t_toa(r->pool, r->connection->bytes_out);
}
/*
@@ -121,10 +106,7 @@
static int logio_transaction(request_rec *r)
{
- logio_config_t *cf = ap_get_module_config(r->connection->conn_config,
- &logio_module);
-
- cf->bytes_in = cf->bytes_out = 0;
+ r->connection->bytes_in = r->connection->bytes_out = 0;
return OK;
}
@@ -133,24 +115,6 @@
* 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,
@@ -158,23 +122,32 @@
apr_off_t readbytes) {
apr_off_t length;
apr_status_t status;
- logio_config_t *cf = ap_get_module_config(f->c->conn_config, &logio_module);
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)
- cf->bytes_in += length;
+ f->c->bytes_in += length;
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...
*/
diff -u --recursive --new-file httpd-2.0-vanilla/server/core.c httpd-2.0/server/core.c
--- httpd-2.0-vanilla/server/core.c Tue Oct 15 08:12:59 2002
+++ httpd-2.0/server/core.c Thu Oct 17 12:39:50 2002
@@ -2737,6 +2737,7 @@
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 @@
== 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 */
@@ -3908,6 +3913,7 @@
if (fd) {
apr_hdtr_t hdtr;
+ apr_size_t bytes_sent;
#if APR_HAS_SENDFILE
apr_int32_t flags = 0;
#endif
@@ -3938,25 +3944,35 @@
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 (bytes_sent > 0)
+ c->bytes_out += bytes_sent;
}
else
#endif
{
- apr_size_t unused_bytes_sent;
rv = emulate_sendfile(net, fd, &hdtr, foffset, flen,
- &unused_bytes_sent);
+ &bytes_sent);
+
+ if (bytes_sent > 0)
+ c->bytes_out += 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 (bytes_sent > 0)
+ c->bytes_out += bytes_sent;
}
apr_brigade_destroy(b);