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: + + + +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 =