diff -Naur apache_2.0a6/10xpatchlevel-3 apache_2.0a6/10xpatchlevel
--- apache_2.0a6/10xpatchlevel-3 Tue Sep 19 22:21:31 2000
+++ apache_2.0a6/10xpatchlevel Wed Sep 20 15:41:29 2000
@@ -2,4 +2,4 @@
available from
http://oss.sgi.com/projects/apache/
-10xpatchlevel=2.0a6-3
+10xpatchlevel=2.0a6-4
diff -Naur apache_2.0a6/htdocs/manual/mod/mod_log_config.html-3 apache_2.0a6/htdocs/manual/mod/mod_log_config.html
--- apache_2.0a6/htdocs/manual/mod/mod_log_config.html-3 Fri Aug 18 10:42:47 2000
+++ apache_2.0a6/htdocs/manual/mod/mod_log_config.html Wed Sep 20 16:33:26 2000
@@ -179,9 +179,9 @@
Note that the common log format is defined by the string "%h %l
-%u %t \"%r\" %s %b", which can be used as the basis for
+%u %t \"%r\" %>s %b", which can be used as the basis for
extending for format if desired (e.g., to add extra fields at the end).
-NCSA's extended/combined log format would be "%h %l %u %t \"%r\" %s %b \"%{Referer}i\" \"%{User-agent}i\"".
+NCSA's extended/combined log format would be "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"".
@@ -212,6 +212,33 @@
See the examples below.
+
Performance Issues
+
+When Apache is compiled with USE_QUICK_LOG defined, logging
+in Common Log Format (CLF) is extra fast. This module recognizes and
+accelerates two variants of CLF:
+
+
+- standard CLF (
"%h %l %u %t \"%r\" %>s %b")
+ - numeric CLF (
"%a %l %u %t \"%r\" %>s %b")
+
+
+Numeric CLF is the same as using standard CLF with HostNameLookups off:
+both log IP addresses rather than host names. Logging IP addresses is
+much faster than logging host names.
+
+Buffering log entries also increases performance, but at the cost of
+delaying writing those entries to disk. Compile Apache with
+BUFFERED_LOGS defined to buffer log entries. The standard
+amount buffered is PIPE_BUF bytes (a POSIX defined
+constant). For an even faster web server you can increase the buffering
+by defining LOG_BUFSIZE to be the number of bytes you want
+buffered. Beware though: increase LOG_BUFSIZE beyond
+PIPE_BUF only if you know you're not using piped logs and
+your system can write more than PIPE_BUF bytes atomically
+to disk at once
+
Security Considerations
See the security tips
@@ -370,7 +397,7 @@
HREF="directive-dict.html#Default"
REL="Help"
>Default: LogFormat "%h %l %u %t \"%r\"
-%s %b"
+%>s %b"
client, B_SAFEREAD, 0);
r->request_time = apr_now();
- r->the_request = apr_pstrdup(r->pool, l);
+ r->the_request = apr_pstrndup(r->pool, l, len);
+ r->the_request_len = len;
r->method = ap_getword_white(r->pool, &ll);
ap_update_connection_status(conn->id, "Method", r->method);
uri = ap_getword_white(r->pool, &ll);
@@ -1302,6 +1303,7 @@
void ap_set_sub_req_protocol(request_rec *rnew, const request_rec *r)
{
rnew->the_request = r->the_request; /* Keep original request-line */
+ rnew->the_request_len = r->the_request_len;
rnew->assbackwards = 1; /* Don't send headers from this. */
rnew->no_local_copy = 1; /* Don't try to send HTTP_NOT_MODIFIED for a
diff -Naur apache_2.0a6/src/main/http_request.c-3 apache_2.0a6/src/main/http_request.c
--- apache_2.0a6/src/main/http_request.c-3 Sat Aug 12 11:45:35 2000
+++ apache_2.0a6/src/main/http_request.c Wed Sep 20 16:37:45 2000
@@ -1348,6 +1348,7 @@
/* Inherit the rest of the protocol info... */
new->the_request = r->the_request;
+ new->the_request_len = r->the_request_len;
new->allowed = r->allowed;
diff -Naur apache_2.0a6/src/modules/standard/mod_log_config.c-3 apache_2.0a6/src/modules/standard/mod_log_config.c
--- apache_2.0a6/src/modules/standard/mod_log_config.c-3 Thu Sep 7 22:06:11 2000
+++ apache_2.0a6/src/modules/standard/mod_log_config.c Wed Sep 20 16:35:00 2000
@@ -142,6 +142,9 @@
* %...U: the URL path requested.
* %...v: the configured name of the server (i.e. which virtual host?)
* %...V: the server name according to the UseCanonicalName setting
+ * %...m: the request method
+ * %...H: the request protocol
+ * %...q: the query string prepended by "?", or empty if no query string
*
* The '...' can be nothing at all (e.g. "%h %u %r %s %b"), or it can
* indicate conditions for inclusion of the item (which will cause it
@@ -168,8 +171,6 @@
*
* --- rst */
-#define DEFAULT_LOG_FORMAT "%h %l %u %t \"%r\" %>s %b"
-
#include "apr_strings.h"
#include "ap_config.h"
#include "httpd.h"
@@ -192,6 +193,20 @@
static int xfer_flags = (APR_WRITE | APR_APPEND | APR_CREATE);
static apr_fileperms_t xfer_perms = APR_OS_DEFAULT;
+static const char common_log_format[] = "%h %l %u %t \"%r\" %>s %b";
+#ifdef USE_QUICK_LOG
+#define QUICK_CLF_MARKER ((apr_array_header_t *) 0x1)
+
+static const char quick_log_format[] = "%a %l %u %t \"%r\" %>s %b";
+#define QUICK_QLF_MARKER ((apr_array_header_t *) 0x2)
+#endif
+
+/*
+ * Increasing LOG_BUFSIZE beyond PIPE_BUF is good for performance but do
+ * so only if you know you're not using piped logs and your system can
+ * write more than PIPE_BUF bytes atomically to disk at once
+ */
+#ifndef LOG_BUFSIZE
/* POSIX.1 defines PIPE_BUF as the maximum number of bytes that is
* guaranteed to be atomic when writing a pipe. And PIPE_BUF >= 512
* is guaranteed. So we'll just guess 512 in the event the system
@@ -206,6 +221,7 @@
#else
#define LOG_BUFSIZE (512)
#endif
+#endif
/*
* multi_log_state is our per-(virtual)-server configuration. We store
@@ -246,7 +262,7 @@
apr_file_t *log_fd;
char *condition_var;
#ifdef BUFFERED_LOGS
- int outcnt;
+ apr_ssize_t outcnt;
char outbuf[LOG_BUFSIZE];
#endif
} config_log_state;
@@ -256,114 +272,125 @@
* Note that many of these could have ap_sprintfs replaced with static buffers.
*/
-typedef const char *(*item_key_func) (request_rec *, char *);
+typedef const char *(*item_key_func) (request_rec *, char *, apr_size_t *);
typedef struct {
item_key_func func;
char *arg;
+ apr_size_t arglen;
int condition_sense;
int want_orig;
apr_array_header_t *conditions;
} log_format_item;
-static char *format_integer(apr_pool_t *p, int i)
-{
- return apr_psprintf(p, "%d", i);
-}
-
-static char *pfmt(apr_pool_t *p, int i)
-{
- if (i <= 0) {
- return "-";
- }
- else {
- return format_integer(p, i);
- }
-}
-
-static const char *constant_item(request_rec *dummy, char *stuff)
+static const char *constant_item(request_rec *dummy, char *stuff, apr_size_t *rlen)
{
return stuff;
}
-static const char *log_remote_host(request_rec *r, char *a)
+static const char *log_remote_host(request_rec *r, char *a, apr_size_t *rlen)
{
return ap_get_remote_host(r->connection, r->per_dir_config,
REMOTE_NAME);
}
-static const char *log_remote_address(request_rec *r, char *a)
+static const char *log_remote_address(request_rec *r, char *a, apr_size_t *rlen)
{
return r->connection->remote_ip;
}
-static const char *log_local_address(request_rec *r, char *a)
+static const char *log_local_address(request_rec *r, char *a, apr_size_t *rlen)
{
return r->connection->local_ip;
}
-static const char *log_remote_logname(request_rec *r, char *a)
+static const char *log_remote_logname(request_rec *r, char *a, apr_size_t *rlen)
{
return ap_get_remote_logname(r);
}
-static const char *log_remote_user(request_rec *r, char *a)
+static const char *log_remote_user(request_rec *r, char *a, apr_size_t *rlen)
{
char *rvalue = r->user;
- if (rvalue == NULL) {
- rvalue = "-";
+ if (rvalue && *rvalue == 0) {
+ rvalue = "\"\"";
+ *rlen = 2;
}
- else if (strlen(rvalue) == 0) {
- rvalue = "\"\"";
- }
return rvalue;
}
-static const char *log_request_line(request_rec *r, char *a)
+static const char *log_request_line(request_rec *r, char *a, apr_size_t *rlen)
{
- /* NOTE: If the original request contained a password, we
- * re-write the request line here to contain XXXXXX instead:
- * (note the truncation before the protocol string for HTTP/0.9 requests)
- * (note also that r->the_request contains the unmodified request)
- */
- return (r->parsed_uri.password) ? apr_pstrcat(r->pool, r->method, " ",
- ap_unparse_uri_components(r->pool, &r->parsed_uri, 0),
- r->assbackwards ? NULL : " ", r->protocol, NULL)
- : r->the_request;
+ /* NOTE: If the original request contained a password, we
+ * re-write the request line here to contain XXXXXX instead:
+ * (note the truncation before the protocol string for HTTP/0.9 requests)
+ * (note also that r->the_request contains the unmodified request)
+ */
+ if (r->parsed_uri.password == NULL) {
+ *rlen = r->the_request_len;
+ return r->the_request;
+ }
+
+ return apr_pstrcat(r->pool, r->method, " ",
+ ap_unparse_uri_components(r->pool, &r->parsed_uri, 0),
+ r->assbackwards ? NULL : " ", r->protocol, NULL);
}
-static const char *log_request_file(request_rec *r, char *a)
+static const char *log_request_file(request_rec *r, char *a, apr_size_t *rlen)
{
return r->filename;
}
-static const char *log_request_uri(request_rec *r, char *a)
+static const char *log_request_uri(request_rec *r, char *a, apr_size_t *rlen)
{
return r->uri;
}
-static const char *log_status(request_rec *r, char *a)
+static const char *log_request_method(request_rec *r, char *a, apr_size_t *rlen)
+{
+ return r->method;
+}
+static const char *log_request_protocol(request_rec *r, char *a, apr_size_t *rlen)
+{
+ return r->protocol;
+}
+static const char *log_request_query(request_rec *r, char *a, apr_size_t *rlen)
{
- return pfmt(r->pool, r->status);
+ return (r->args != NULL) ? apr_pstrcat(r->pool, "?", r->args, NULL)
+ : "";
}
+static const char *log_status(request_rec *r, char *a, apr_size_t *rlen)
+{
+ /* Accelerate the most common case. */
+ if (r->status == 200) {
+ *rlen = 3;
+ return "200";
+ } else if (r->status > 0)
+ return apr_psprintf(r->pool, "%d", r->status);
+ else
+ return NULL;
+}
-static const char *log_bytes_sent(request_rec *r, char *a)
+static const char *log_bytes_sent(request_rec *r, char *a, apr_size_t *rlen)
{
- if (!r->sent_bodyct) {
- return "-";
- }
- else {
+ const char *cp;
+
+ if (!r->sent_bodyct)
+ cp = NULL;
+ else if ((cp = apr_table_get(r->headers_out, "Content-Length")) == NULL) {
long int bs;
ap_bgetopt(r->connection->client, BO_BYTECT, &bs);
- return apr_psprintf(r->pool, "%ld", bs);
+ cp = apr_psprintf(r->pool, "%ld", bs);
}
+
+ return cp;
}
-static const char *log_header_in(request_rec *r, char *a)
+static const char *log_header_in(request_rec *r, char *a, apr_size_t *rlen)
{
return apr_table_get(r->headers_in, a);
}
-static const char *log_header_out(request_rec *r, char *a)
+static const char *log_header_out(request_rec *r, char *a, apr_size_t *rlen)
{
const char *cp = apr_table_get(r->headers_out, a);
if (!strcasecmp(a, "Content-type") && r->content_type) {
@@ -375,16 +402,16 @@
return apr_table_get(r->err_headers_out, a);
}
-static const char *log_note(request_rec *r, char *a)
+static const char *log_note(request_rec *r, char *a, apr_size_t *rlen)
{
return apr_table_get(r->notes, a);
}
-static const char *log_env_var(request_rec *r, char *a)
+static const char *log_env_var(request_rec *r, char *a, apr_size_t *rlen)
{
return apr_table_get(r->subprocess_env, a);
}
-static const char *log_request_time(request_rec *r, char *a)
+static const char *log_request_time(request_rec *r, char *a, apr_size_t *rlen)
{
apr_time_t t;
apr_exploded_time_t xt;
@@ -395,6 +422,7 @@
static struct {
apr_time_t time;
char str[32];
+ apr_size_t len;
} last;
#endif
@@ -425,8 +453,10 @@
int timz;
#if !APR_HAS_THREADS
- if (t == last.time)
+ if (t == last.time) {
+ *rlen = last.len;
return last.str;
+ }
#endif
apr_explode_localtime(&xt, t);
@@ -439,6 +469,9 @@
sign = '+';
}
+#if !APR_HAS_THREADS
+ last.len =
+#endif
apr_snprintf(
#if APR_HAS_THREADS
tstr, sizeof(tstr),
@@ -454,12 +487,13 @@
return apr_pstrdup(r->pool, tstr);
#else
last.time = t;
+ *rlen = last.len;
return last.str;
#endif
}
}
-static const char *log_request_duration(request_rec *r, char *a)
+static const char *log_request_duration(request_rec *r, char *a, apr_size_t *rlen)
{
return apr_psprintf(r->pool, "%lld", (apr_now() - r->request_time)
/ APR_USEC_PER_SEC);
@@ -468,12 +502,12 @@
/* These next two routines use the canonical name:port so that log
* parsers don't need to duplicate all the vhost parsing crud.
*/
-static const char *log_virtual_host(request_rec *r, char *a)
+static const char *log_virtual_host(request_rec *r, char *a, apr_size_t *rlen)
{
return r->server->server_hostname;
}
-static const char *log_server_port(request_rec *r, char *a)
+static const char *log_server_port(request_rec *r, char *a, apr_size_t *rlen)
{
return apr_psprintf(r->pool, "%u",
r->server->port ? r->server->port : ap_default_port(r));
@@ -482,12 +516,12 @@
/* This respects the setting of UseCanonicalName so that
* the dynamic mass virtual hosting trick works better.
*/
-static const char *log_server_name(request_rec *r, char *a)
+static const char *log_server_name(request_rec *r, char *a, apr_size_t *rlen)
{
return ap_get_server_name(r);
}
-static const char *log_child_pid(request_rec *r, char *a)
+static const char *log_child_pid(request_rec *r, char *a, apr_size_t *rlen)
{
return apr_psprintf(r->pool, "%ld", (long) getpid());
}
@@ -564,6 +598,15 @@
'P', log_child_pid, 0
},
{
+ 'H', log_request_protocol, 0
+ },
+ {
+ 'm', log_request_method, 0
+ },
+ {
+ 'q', log_request_query, 0
+ },
+ {
'\0'
}
};
@@ -637,6 +680,7 @@
}
}
*d = '\0';
+ it->arglen = d - it->arg;
*sa = s;
return NULL;
@@ -655,6 +699,7 @@
it->conditions = NULL;
it->want_orig = -1;
it->arg = ""; /* For safety's sake... */
+ it->arglen = 0;
while (*s) {
int i;
@@ -729,9 +774,17 @@
static apr_array_header_t *parse_log_string(apr_pool_t *p, const char *s, const char **err)
{
- apr_array_header_t *a = apr_make_array(p, 30, sizeof(log_format_item));
+ apr_array_header_t *a;
char *res;
+#ifdef USE_QUICK_LOG
+ if (s == common_log_format || !strcmp(s, common_log_format))
+ return QUICK_CLF_MARKER;
+ else if (s == quick_log_format || !strcmp(s, quick_log_format))
+ return QUICK_QLF_MARKER;
+#endif
+
+ a = apr_make_array(p, 30, sizeof(log_format_item));
while (*s) {
if ((res = parse_log_item(p, (log_format_item *) apr_push_array(a), &s))) {
*err = res;
@@ -750,9 +803,10 @@
*/
static const char *process_item(request_rec *r, request_rec *orig,
- log_format_item *item)
+ log_format_item *item, apr_size_t *rlen)
{
const char *cp;
+ static const char dash[2] = "-";
/* First, see if we need to process this thing at all... */
@@ -770,14 +824,20 @@
if ((item->condition_sense && in_list)
|| (!item->condition_sense && !in_list)) {
- return "-";
+ *rlen = 1;
+ return dash;
}
}
/* We do. Do it... */
- cp = (*item->func) (item->want_orig ? orig : r, item->arg);
- return cp ? cp : "-";
+ *rlen = item->arglen;
+ cp = (*item->func) (item->want_orig ? orig : r, item->arg, rlen);
+ if (cp)
+ return cp;
+
+ *rlen = 1;
+ return dash;
}
#ifdef BUFFERED_LOGS
@@ -784,24 +844,178 @@
static void flush_log(config_log_state *cls)
{
if (cls->outcnt && cls->log_fd != NULL) {
- apr_write(cls->log_fd, cls->outbuf, cls->outcnt);
+ apr_write(cls->log_fd, cls->outbuf, &cls->outcnt);
cls->outcnt = 0;
}
}
#endif
+static void log_vec(request_rec *r, config_log_state *cls, struct iovec *iovec,
+ apr_size_t iovcnt, apr_size_t len)
+{
+ apr_size_t i;
+ char *s;
+
+#ifdef BUFFERED_LOGS
+ if (len + cls->outcnt > LOG_BUFSIZE)
+ flush_log(cls);
+ if (len < LOG_BUFSIZE) {
+ for (i = 0, s = &cls->outbuf[cls->outcnt]; i < iovcnt; i++) {
+ memcpy(s, iovec[i].iov_base, iovec[i].iov_len);
+ s += iovec[i].iov_len;
+ }
+ cls->outcnt += len;
+ } else {
+#endif
+ /*
+ * would use apr_writev() but on systems without writev it
+ * writes only iovec[0]!
+ */
+ char *str = apr_palloc(r->pool, len);
+ apr_ssize_t w = len;
+ for (i = 0, s = str; i < iovcnt; i++) {
+ memcpy(s, iovec[i].iov_base, iovec[i].iov_len);
+ s += iovec[i].iov_len;
+ }
+ apr_write(cls->log_fd, str, &w);
+#ifdef BUFFERED_LOGS
+ }
+#endif
+}
+
+#ifdef USE_QUICK_LOG
+static int quick_log(request_rec *r, request_rec *orig, config_log_state *cls,
+ const apr_array_header_t *format)
+{
+ struct iovec iovec[14];
+ static const char sqsdn[6] = " \" -\n";
+
+ /*
+ * format is either:
+ * QUICK_CLF_MARKER for "%h %l %u %t \"%r\" %>s %b\n"
+ * or
+ * QUICK_QLF_MARKER for "%a %l %u %t \"%r\" %>s %b\n"
+ */
+
+ /* "%h" or "%a" */
+ iovec[0].iov_len = 0;
+ iovec[0].iov_base = (format == QUICK_QLF_MARKER) ?
+ (void *) log_remote_address(r, NULL, &iovec[0].iov_len) :
+ (void *) log_remote_host(r, NULL, &iovec[0].iov_len);
+ if (iovec[0].iov_base) {
+ if (iovec[0].iov_len == 0)
+ iovec[0].iov_len = strlen(iovec[0].iov_base);
+ } else {
+ iovec[0].iov_base = (void *) &sqsdn[3];
+ iovec[0].iov_len = 1;
+ }
+
+ /* " " */
+ iovec[1].iov_base = (void *) sqsdn;
+ iovec[1].iov_len = 1;
+
+ /* "%l" */
+ iovec[2].iov_len = 0;
+ iovec[2].iov_base = (void *) log_remote_logname(r, NULL, &iovec[2].iov_len);
+ if (iovec[2].iov_base == NULL) {
+ iovec[2].iov_base = (void *) &sqsdn[3];
+ iovec[2].iov_len = 1;
+ } else if (iovec[2].iov_len == 0)
+ iovec[2].iov_len = strlen(iovec[2].iov_base);
+
+ /* " " */
+ iovec[3].iov_base = (void *) sqsdn;
+ iovec[3].iov_len = 1;
+
+ /* "%u" */
+ iovec[4].iov_len = 0;
+ iovec[4].iov_base = (void *) log_remote_user(r, NULL, &iovec[4].iov_len);
+ if (iovec[4].iov_base == NULL) {
+ iovec[4].iov_base = (void *) &sqsdn[3];
+ iovec[4].iov_len = 1;
+ } else if (iovec[4].iov_len == 0)
+ iovec[4].iov_len = strlen(iovec[4].iov_base);
+
+ /* " " */
+ iovec[5].iov_base = (void *) sqsdn;
+ iovec[5].iov_len = 1;
+
+ /* "%t" */
+ iovec[6].iov_len = 0;
+ iovec[6].iov_base = (void *) log_request_time(r, NULL, &iovec[6].iov_len);
+ if (iovec[6].iov_len == 0)
+ iovec[6].iov_len = strlen(iovec[6].iov_base);
+
+ /* " \"" */
+ iovec[7].iov_base = (void *) sqsdn;
+ iovec[7].iov_len = 2;
+
+ /* "%r" */
+ iovec[8].iov_len = 0;
+ iovec[8].iov_base = (void *) log_request_line(orig, NULL, &iovec[8].iov_len);
+ if (iovec[8].iov_base) {
+ if (iovec[8].iov_len == 0)
+ iovec[8].iov_len = strlen(iovec[8].iov_base);
+ } else {
+ iovec[8].iov_base = (void *) &sqsdn[3];
+ iovec[8].iov_len = 1;
+ }
+
+ /* "\" " */
+ iovec[9].iov_base = (void *) &sqsdn[1];
+ iovec[9].iov_len = 2;
+
+ /* "%>s" */
+ iovec[10].iov_len = 0;
+ iovec[10].iov_base = (void *) log_status(r, NULL, &iovec[10].iov_len);
+ if (iovec[10].iov_base) {
+ if (iovec[10].iov_len == 0)
+ iovec[10].iov_len = strlen(iovec[10].iov_base);
+ } else {
+ iovec[10].iov_base = (void *) &sqsdn[3];
+ iovec[10].iov_len = 1;
+ }
+
+ /* " " */
+ iovec[11].iov_base = (void *) sqsdn;
+ iovec[11].iov_len = 1;
+
+ /* "%b" */
+ iovec[12].iov_len = 0;
+ iovec[12].iov_base = (void *) log_bytes_sent(r, NULL, &iovec[12].iov_len);
+ if (iovec[12].iov_base) {
+ if (iovec[12].iov_len == 0)
+ iovec[12].iov_len = strlen(iovec[12].iov_base);
+ } else {
+ iovec[12].iov_base = (void *) &sqsdn[3];
+ iovec[12].iov_len = 1;
+ }
+
+ /* "\n" */
+ iovec[13].iov_base = (void *) &sqsdn[4];
+ iovec[13].iov_len = 1;
+
+ log_vec(r, cls, iovec, 14,
+ iovec[0].iov_len + iovec[1].iov_len + iovec[2].iov_len +
+ iovec[3].iov_len + iovec[4].iov_len + iovec[5].iov_len +
+ iovec[6].iov_len + iovec[7].iov_len + iovec[8].iov_len +
+ iovec[9].iov_len + iovec[10].iov_len + iovec[11].iov_len +
+ iovec[12].iov_len + iovec[13].iov_len);
+
+ return OK;
+}
+#endif
+
static int config_log_transaction(request_rec *r, config_log_state *cls,
apr_array_header_t *default_format)
{
log_format_item *items;
- char *str, *s;
- const char **strs;
- int *strl;
request_rec *orig;
int i;
- apr_ssize_t len = 0;
+ apr_ssize_t len;
apr_array_header_t *format;
char *envar;
+ struct iovec local_iovec[20], *iovec;
if (cls->fname == NULL) {
return DECLINED;
@@ -825,12 +1039,6 @@
}
}
- format = cls->format ? cls->format : default_format;
-
- strs = apr_palloc(r->pool, sizeof(char *) * (format->nelts));
- strl = apr_palloc(r->pool, sizeof(int) * (format->nelts));
- items = (log_format_item *) format->elts;
-
orig = r;
while (orig->prev) {
orig = orig->prev;
@@ -839,43 +1047,29 @@
r = r->next;
}
- for (i = 0; i < format->nelts; ++i) {
- strs[i] = process_item(r, orig, &items[i]);
- }
-
- for (i = 0; i < format->nelts; ++i) {
- len += strl[i] = strlen(strs[i]);
- }
+ format = cls->format ? cls->format : default_format;
+#ifdef USE_QUICK_LOG
+ if (format == QUICK_CLF_MARKER || format == QUICK_QLF_MARKER)
+ return quick_log(r, orig, cls, format);
+#endif
-#ifdef BUFFERED_LOGS
- if (len + cls->outcnt > LOG_BUFSIZE) {
- flush_log(cls);
- }
- if (len >= LOG_BUFSIZE) {
- str = apr_palloc(r->pool, len + 1);
- for (i = 0, s = str; i < format->nelts; ++i) {
- memcpy(s, strs[i], strl[i]);
- s += strl[i];
- }
- apr_write(cls->log_fd, str, len);
- }
- else {
- for (i = 0, s = &cls->outbuf[cls->outcnt]; i < format->nelts; ++i) {
- memcpy(s, strs[i], strl[i]);
- s += strl[i];
- }
- cls->outcnt += len;
- }
-#else
- str = apr_palloc(r->pool, len + 1);
+ len = 0;
+ if (format->nelts <= sizeof local_iovec / sizeof local_iovec[0])
+ iovec = local_iovec;
+ else
+ iovec = apr_palloc(r->pool, sizeof *iovec * format->nelts);
+ items = (log_format_item *) format->elts;
- for (i = 0, s = str; i < format->nelts; ++i) {
- memcpy(s, strs[i], strl[i]);
- s += strl[i];
+ for (i = 0; i < format->nelts; i++) {
+ iovec[i].iov_len = 0;
+ iovec[i].iov_base = (void *) process_item(r, orig, &items[i],
+ &iovec[i].iov_len);
+ if (iovec[i].iov_len == 0)
+ iovec[i].iov_len = strlen(iovec[i].iov_base);
+ len += iovec[i].iov_len;
}
- apr_write(cls->log_fd, str, &len);
-#endif
+ log_vec(r, cls, iovec, format->nelts, len);
return OK;
}
@@ -925,7 +1119,7 @@
mls->default_format = NULL;
mls->server_config_logs = NULL;
mls->formats = apr_make_table(p, 4);
- apr_table_setn(mls->formats, "CLF", DEFAULT_LOG_FORMAT);
+ apr_table_setn(mls->formats, "CLF", common_log_format);
return mls;
}
@@ -1095,7 +1289,7 @@
}
if (!mls->default_format) {
- mls->default_format = parse_log_string(p, DEFAULT_LOG_FORMAT, &dummy);
+ mls->default_format = parse_log_string(p, common_log_format, &dummy);
}
if (mls->config_logs->nelts) {
@@ -1132,28 +1326,10 @@
return NULL;
}
-static void init_config_log(apr_pool_t *pc, apr_pool_t *p, apr_pool_t *pt, server_rec *s)
-{
- /* First, do "physical" server, which gets default log fd and format
- * for the virtual servers, if they don't override...
- */
-
- open_multi_logs(s, p);
-
- /* Then, virtual servers */
-
- for (s = s->next; s; s = s->next) {
- open_multi_logs(s, p);
- }
-#ifdef BUFFERED_LOGS
- /* Now register the last buffer flush with the cleanup engine */
- apr_register_cleanup(p , s, flush_all_logs, flush_all_logs);
-#endif
-}
-
#ifdef BUFFERED_LOGS
-static void flush_all_logs(server_rec *s)
+static apr_status_t flush_all_logs(void *data)
{
+ server_rec *s = data;
multi_log_state *mls;
apr_array_header_t *log_list;
config_log_state *clsarray;
@@ -1175,13 +1351,42 @@
}
}
}
+
+ return APR_SUCCESS;
+}
+#endif
+
+static void init_config_log(apr_pool_t *p, apr_pool_t *pl, apr_pool_t *pt, server_rec *s)
+{
+ /* First, do "physical" server, which gets default log fd and format
+ * for the virtual servers, if they don't override...
+ */
+
+ open_multi_logs(s, p);
+
+ /* Then, virtual servers */
+
+ for (s = s->next; s; s = s->next) {
+ open_multi_logs(s, p);
+ }
+#ifdef BUFFERED_LOGS
+ /* Now register the last buffer flush with the cleanup engine */
+ apr_register_cleanup(p , s, flush_all_logs, flush_all_logs);
+#endif
}
+
+static void config_log_child_init(apr_pool_t *pchild, server_rec *s)
+{
+#ifdef BUFFERED_LOGS
+ apr_register_cleanup(pchild, s, flush_all_logs, flush_all_logs);
#endif
+}
static void register_hooks(void)
{
ap_hook_open_logs(init_config_log,NULL,NULL,AP_HOOK_MIDDLE);
ap_hook_log_transaction(multi_log_transaction,NULL,NULL,AP_HOOK_MIDDLE);
+ ap_hook_child_init(config_log_child_init, NULL, NULL, AP_HOOK_MIDDLE);
}
module MODULE_VAR_EXPORT config_log_module =