diff -Naur apache_1.3.6+01-02/htdocs/manual/mod/mod_log_config.html apache_1.3.6+01-03/htdocs/manual/mod/mod_log_config.html
--- apache_1.3.6+01-02/htdocs/manual/mod/mod_log_config.html Mon Mar 22 16:17:41 1999
+++ apache_1.3.6+01-03/htdocs/manual/mod/mod_log_config.html Thu Jul 15 13:11:41 1999
@@ -172,9 +172,10 @@
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\"".
@@ -205,6 +206,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
@@ -363,7 +391,7 @@
HREF="directive-dict.html#Default"
REL="Help"
>Default: LogFormat "%h %l %u %t \"%r\"
-%s %b"
+%>s %b"
+#ifdef NO_WRITEV
+struct iovec {
+ void *iov_base;
+ size_t iov_len;
+};
+#else
+#include
+#endif
+
#ifdef __cplusplus
extern "C" {
#endif
diff -Naur apache_1.3.6+01-02/src/include/httpd.h apache_1.3.6+01-03/src/include/httpd.h
--- apache_1.3.6+01-02/src/include/httpd.h Wed Jul 14 15:47:23 1999
+++ apache_1.3.6+01-03/src/include/httpd.h Thu Jul 15 10:25:51 1999
@@ -66,6 +66,12 @@
* httpd.h: header for simple (ha! not anymore) http daemon
*/
+/* Mike Abbott - mja@sgi.com */
+#ifdef SPEED_DAEMON /* that's me, a real speed demon */
+# define BUFFERED_LOGS /* buffer log messages */
+# define USE_QUICK_LOG /* fast path through logging code */
+#endif
+
/* Headers in which EVERYONE has an interest... */
#include "ap_types.h"
@@ -652,6 +658,7 @@
*/
char *the_request; /* First line of request, so we can log it */
+ int the_request_len; /* strlen(the_request) */
int assbackwards; /* HTTP/0.9, "simple" request */
int proxyreq; /* A proxy request (calculated during
* post_read_request or translate_name) */
@@ -805,7 +812,8 @@
struct sockaddr_in local_addr; /* local address */
struct sockaddr_in remote_addr; /* remote address */
- char *remote_ip; /* Client's IP address */
+ char remote_ip[16]; /* Client's IP address */
+ int remote_ip_len; /* strlen(remote_ip) */
char *remote_host; /* Client's DNS name, if known.
* NULL if DNS hasn't been checked,
* "" if it has and no address was found.
@@ -983,6 +991,7 @@
API_EXPORT(char *) ap_escape_quotes (pool *p, const char *instring);
+API_EXPORT(char *) ap_inet_ntoa(struct in_addr, char * /* 16 bytes */, int *);
API_EXPORT(int) ap_oversized_file(off_t);
/* Common structure for reading of config files / passwd files etc. */
diff -Naur apache_1.3.6+01-02/src/main/buff.c apache_1.3.6+01-03/src/main/buff.c
--- apache_1.3.6+01-02/src/main/buff.c Thu Jul 8 13:34:58 1999
+++ apache_1.3.6+01-03/src/main/buff.c Thu Jul 15 14:05:15 1999
@@ -63,10 +63,6 @@
#include
#include
#include
-#ifndef NO_WRITEV
-#include
-#include
-#endif
#ifdef HAVE_BSTRING_H
#include /* for IRIX, FD_SET calls bzero() */
diff -Naur apache_1.3.6+01-02/src/main/http_main.c apache_1.3.6+01-03/src/main/http_main.c
--- apache_1.3.6+01-02/src/main/http_main.c Thu Jul 8 13:34:58 1999
+++ apache_1.3.6+01-03/src/main/http_main.c Thu Jul 15 12:25:03 1999
@@ -2986,8 +2986,8 @@
conn->client = inout;
conn->remote_addr = *remaddr;
- conn->remote_ip = ap_pstrdup(conn->pool,
- inet_ntoa(conn->remote_addr.sin_addr));
+ ap_inet_ntoa(conn->remote_addr.sin_addr, conn->remote_ip,
+ &conn->remote_ip_len);
return conn;
}
@@ -3024,10 +3024,12 @@
int one = 1;
char addr[512];
- if (server->sin_addr.s_addr != (ap_uint32) htonl(INADDR_ANY))
+ if (server->sin_addr.s_addr != htonl(INADDR_ANY)) {
+ char nbuf[16];
ap_snprintf(addr, sizeof(addr), "address %s port %d",
- inet_ntoa(server->sin_addr), ntohs(server->sin_port));
- else
+ ap_inet_ntoa(server->sin_addr, nbuf, NULL),
+ ntohs(server->sin_port));
+ } else
ap_snprintf(addr, sizeof(addr), "port %d", ntohs(server->sin_port));
/* note that because we're about to slack we don't use psocket */
@@ -3420,6 +3422,7 @@
#endif
#ifdef BUFFERED_LOGS
printf(" -D BUFFERED_LOGS\n");
+ printf(" -D LOG_BUFSIZE=%d\n", LOG_BUFSIZE);
#ifdef PIPE_BUF
printf(" -D PIPE_BUF=%ld\n",(long)PIPE_BUF);
#endif
diff -Naur apache_1.3.6+01-02/src/main/http_protocol.c apache_1.3.6+01-03/src/main/http_protocol.c
--- apache_1.3.6+01-02/src/main/http_protocol.c Wed Jul 14 17:19:12 1999
+++ apache_1.3.6+01-03/src/main/http_protocol.c Thu Jul 15 10:29:50 1999
@@ -840,6 +840,7 @@
r->request_time = time(NULL);
r->the_request = r->rqbuf;
+ r->the_request_len = (int) (cp + 9 - r->rqbuf);
r->method = "GET";
r->method_number = M_GET;
ap_assert(!r->assbackwards);
@@ -916,6 +917,7 @@
r->request_time = time(NULL);
r->the_request = ap_pstrndup(r->pool, l, len);
+ r->the_request_len = len;
r->method = ap_getword_white(r->pool, &ll);
uri = ap_getword_white(r->pool, &ll);
@@ -1314,6 +1316,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 USE_LOCAL_COPY for a
diff -Naur apache_1.3.6+01-02/src/main/http_request.c apache_1.3.6+01-03/src/main/http_request.c
--- apache_1.3.6+01-02/src/main/http_request.c Thu Jul 8 12:28:26 1999
+++ apache_1.3.6+01-03/src/main/http_request.c Thu Jul 15 10:30:03 1999
@@ -1289,6 +1289,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_1.3.6+01-02/src/main/http_vhost.c apache_1.3.6+01-03/src/main/http_vhost.c
--- apache_1.3.6+01-02/src/main/http_vhost.c Thu Jul 8 12:28:36 1999
+++ apache_1.3.6+01-03/src/main/http_vhost.c Thu Jul 15 10:30:09 1999
@@ -607,11 +607,12 @@
else {
/* again, what can we do? They didn't specify a
ServerName, and their DNS isn't working. -djg */
+ char nbuf[16];
ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, main_s,
"Failed to resolve server name "
"for %s (check DNS) -- or specify an explicit "
"ServerName",
- inet_ntoa(s->addrs->host_addr));
+ ap_inet_ntoa(s->addrs->host_addr, nbuf, NULL));
s->server_hostname =
ap_pstrdup(p, "bogus_host_without_reverse_dns");
}
diff -Naur apache_1.3.6+01-02/src/main/util.c apache_1.3.6+01-03/src/main/util.c
--- apache_1.3.6+01-02/src/main/util.c Thu Jul 8 12:31:15 1999
+++ apache_1.3.6+01-03/src/main/util.c Thu Jul 15 10:30:25 1999
@@ -2189,6 +2189,50 @@
return outstring;
}
+/*
+ * Fast implementation of inet_ntoa(). buf should be 16 bytes. Returns
+ * buf and, if rlen is non-null, sets *rlen to strlen(buf).
+ */
+API_EXPORT(char *)
+ap_inet_ntoa(struct in_addr in, char *buf, int *rlen)
+{
+ int i;
+ char *bp;
+
+ /*
+ * This implementation is fast because it avoids sprintf(),
+ * division/modulo, and global static array lookups.
+ */
+
+ bp = buf;
+ for (i = 0; i < 4; i++) {
+ unsigned int o, n;
+
+ o = ((unsigned char *) &in)[i];
+ n = o;
+ if (n >= 200) {
+ *bp++ = '2';
+ n -= 200;
+ } else if (n >= 100) {
+ *bp++ = '1';
+ n -= 100;
+ }
+ if (o >= 10) {
+ int i;
+ for (i = 0; n >= 10; i++)
+ n -= 10;
+ *bp++ = i + '0';
+ }
+ *bp++ = n + '0';
+ *bp++ = '.';
+ }
+ *--bp = 0;
+ if (rlen)
+ *rlen = (int) (bp - buf);
+
+ return buf;
+}
+
/* Return nonzero if the given file size is too large to serve. */
API_EXPORT(int)
ap_oversized_file(off_t size)
diff -Naur apache_1.3.6+01-02/src/modules/standard/mod_log_config.c apache_1.3.6+01-03/src/modules/standard/mod_log_config.c
--- apache_1.3.6+01-02/src/modules/standard/mod_log_config.c Thu Jul 15 12:50:23 1999
+++ apache_1.3.6+01-03/src/modules/standard/mod_log_config.c Thu Jul 15 13:41:12 1999
@@ -166,8 +166,12 @@
*
* --- rst */
-#define DEFAULT_LOG_FORMAT "%h %l %u %t \"%r\" %>s %b"
+static const char common_log_format[] = "%h %l %u %t \"%r\" %>s %b";
+#define QUICK_CLF_MARKER ((array_header *) (ap_ptr) 0x1)
+static const char quick_log_format[] = "%a %l %u %t \"%r\" %>s %b";
+#define QUICK_QLF_MARKER ((array_header *) (ap_ptr) 0x2)
+
#include "httpd.h"
#include "http_config.h"
#include "http_core.h" /* For REMOTE_NAME */
@@ -184,6 +188,12 @@
static mode_t xfer_mode = (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
#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
@@ -198,6 +208,7 @@
#else
#define LOG_BUFSIZE (512)
#endif
+#endif
/*
* multi_log_state is our per-(virtual)-server configuration. We store
@@ -248,39 +259,25 @@
* 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 *, size_t *);
typedef struct {
item_key_func func;
char *arg;
+ size_t arglen;
int condition_sense;
int want_orig;
array_header *conditions;
} log_format_item;
-static char *format_integer(pool *p, int i)
-{
- return ap_psprintf(p, "%d", i);
-}
-
-static char *pfmt(pool *p, int i)
-{
- if (i <= 0) {
- return "-";
- }
- else {
- return format_integer(p, i);
- }
-}
-
/*ARGSUSED*/
-static const char *constant_item(request_rec *dummy, char *stuff)
+static const char *constant_item(request_rec *dummy, char *stuff, size_t *rlen)
{
return stuff;
}
/*ARGSUSED1*/
-static const char *log_remote_host(request_rec *r, char *a)
+static const char *log_remote_host(request_rec *r, char *a, size_t *rlen)
{
return ap_get_remote_host(r->connection, r->per_dir_config,
REMOTE_NAME);
@@ -287,82 +284,112 @@
}
/*ARGSUSED1*/
-static const char *log_remote_address(request_rec *r, char *a)
+static const char *log_remote_address(request_rec *r, char *a, size_t *rlen)
{
+ *rlen = r->connection->remote_ip_len;
return r->connection->remote_ip;
}
/*ARGSUSED1*/
-static const char *log_remote_logname(request_rec *r, char *a)
+static const char *log_remote_logname(request_rec *r, char *a, size_t *rlen)
{
return ap_get_remote_logname(r);
}
-/*ARGSUSED1*/
-static const char *log_remote_user(request_rec *r, char *a)
+/*ARGSUSED*/
+static const char *log_remote_user(request_rec *r, char *a, size_t *rlen)
{
char *rvalue = r->connection->user;
- if (rvalue == NULL) {
- rvalue = "-";
- }
- else if (strlen(rvalue) == 0) {
- rvalue = "\"\"";
+ if (rvalue && *rvalue == 0) {
+ rvalue = "\"\"";
+ *rlen = 2;
}
+
return rvalue;
}
/*ARGSUSED1*/
-static const char *log_request_line(request_rec *r, char *a)
+static const char *log_request_line(request_rec *r, char *a, 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) ? ap_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 ap_pstrcat(r->pool, r->method, " ",
+ ap_unparse_uri_components(r->pool, &r->parsed_uri, 0),
+ r->assbackwards ? NULL : " ", r->protocol, NULL);
}
/*ARGSUSED1*/
-static const char *log_request_file(request_rec *r, char *a)
+static const char *log_request_file(request_rec *r, char *a, size_t *rlen)
{
return r->filename;
}
/*ARGSUSED1*/
-static const char *log_request_uri(request_rec *r, char *a)
+static const char *log_request_uri(request_rec *r, char *a, size_t *rlen)
{
return r->uri;
}
-/*ARGSUSED1*/
-static const char *log_status(request_rec *r, char *a)
+/*ARGSUSED*/
+static const char *log_status(request_rec *r, char *a, size_t *rlen)
{
- return pfmt(r->pool, r->status);
+ /* Cache the last converted status. */
+ static struct {
+ int status;
+ char str[16];
+ size_t len;
+ } last;
+
+ if (r->status > 0) {
+ if (r->status != last.status) {
+ last.status = r->status;
+ last.len = sprintf(last.str, "%d", last.status);
+ }
+
+ *rlen = last.len;
+ return last.str;
+ }
+
+ return NULL;
}
/*ARGSUSED1*/
-static const char *log_bytes_sent(request_rec *r, char *a)
+static const char *log_bytes_sent(request_rec *r, char *a, size_t *rlen)
{
- if (!r->sent_bodyct) {
- return "-";
- }
+ const char *cp;
+ const char *length;
+
+ if (!r->sent_bodyct)
+ cp = NULL;
+ else if ((length = ap_table_get(r->headers_out, "Content-Length")) != NULL)
+ cp = length;
else {
ap_int32 bs;
ap_bgetopt(r->connection->client, BO_BYTECT, &bs);
- return ap_psprintf(r->pool, "%ld", (long) bs);
+ cp = ap_psprintf(r->pool, "%ld", (long) bs);
}
+
+ return cp;
}
-static const char *log_header_in(request_rec *r, char *a)
+/*ARGSUSED2*/
+static const char *log_header_in(request_rec *r, char *a, size_t *rlen)
{
return ap_table_get(r->headers_in, a);
}
-static const char *log_header_out(request_rec *r, char *a)
+/*ARGSUSED2*/
+static const char *log_header_out(request_rec *r, char *a, size_t *rlen)
{
const char *cp = ap_table_get(r->headers_out, a);
if (!strcasecmp(a, "Content-type") && r->content_type) {
@@ -374,16 +401,20 @@
return ap_table_get(r->err_headers_out, a);
}
-static const char *log_note(request_rec *r, char *a)
+/*ARGSUSED2*/
+static const char *log_note(request_rec *r, char *a, size_t *rlen)
{
return ap_table_get(r->notes, a);
}
-static const char *log_env_var(request_rec *r, char *a)
+
+/*ARGSUSED2*/
+static const char *log_env_var(request_rec *r, char *a, size_t *rlen)
{
return ap_table_get(r->subprocess_env, a);
}
-static const char *log_request_time(request_rec *r, char *a)
+/*ARGSUSED2*/
+static const char *log_request_time(request_rec *r, char *a, size_t *rlen)
{
int timz;
struct tm *t;
@@ -412,7 +443,7 @@
}
/*ARGSUSED1*/
-static const char *log_request_duration(request_rec *r, char *a)
+static const char *log_request_duration(request_rec *r, char *a, size_t *rlen)
{
return ap_psprintf(r->pool, "%ld", (long) (time(NULL) - r->request_time));
}
@@ -421,13 +452,13 @@
* parsers don't need to duplicate all the vhost parsing crud.
*/
/*ARGSUSED1*/
-static const char *log_virtual_host(request_rec *r, char *a)
+static const char *log_virtual_host(request_rec *r, char *a, size_t *rlen)
{
return r->server->server_hostname;
}
/*ARGSUSED1*/
-static const char *log_server_port(request_rec *r, char *a)
+static const char *log_server_port(request_rec *r, char *a, size_t *rlen)
{
return ap_psprintf(r->pool, "%u",
r->server->port ? r->server->port : ap_default_port(r));
@@ -437,13 +468,13 @@
* the dynamic mass virtual hosting trick works better.
*/
/*ARGSUSED1*/
-static const char *log_server_name(request_rec *r, char *a)
+static const char *log_server_name(request_rec *r, char *a, size_t *rlen)
{
return ap_get_server_name(r);
}
/*ARGSUSED1*/
-static const char *log_child_pid(request_rec *r, char *a)
+static const char *log_child_pid(request_rec *r, char *a, size_t *rlen)
{
return ap_psprintf(r->pool, "%ld", (long) getpid());
}
@@ -586,6 +617,7 @@
}
}
*d = '\0';
+ it->arglen = d - it->arg;
*sa = s;
return NULL;
@@ -604,6 +636,7 @@
it->conditions = NULL;
it->want_orig = -1;
it->arg = ""; /* For safety's sake... */
+ it->arglen = 0;
while (*s) {
int i;
@@ -678,9 +711,17 @@
static array_header *parse_log_string(pool *p, const char *s, const char **err)
{
- array_header *a = ap_make_array(p, 30, sizeof(log_format_item));
+ array_header *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 = ap_make_array(p, 30, sizeof(log_format_item));
while (*s) {
if ((res = parse_log_item(p, (log_format_item *) ap_push_array(a), &s))) {
*err = res;
@@ -699,9 +740,10 @@
*/
static const char *process_item(request_rec *r, request_rec *orig,
- log_format_item *item)
+ log_format_item *item, size_t *rlen)
{
const char *cp;
+ static const char dash[2] = "-";
/* First, see if we need to process this thing at all... */
@@ -719,14 +761,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
@@ -739,18 +787,162 @@
}
#endif
+static void
+log_vec(request_rec *r, config_log_state *cls, struct iovec *iovec,
+ int iovcnt, size_t len)
+{
+ int 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
+ char *str = ap_palloc(r->pool, len);
+ for (i = 0, s = str; i < iovcnt; i++) {
+ memcpy(s, iovec[i].iov_base, iovec[i].iov_len);
+ s += iovec[i].iov_len;
+ }
+ write(cls->log_fd, str, len);
+#ifdef BUFFERED_LOGS
+ }
+#endif
+}
+
+#ifdef USE_QUICK_LOG
+static int quick_log(request_rec *r, request_rec *orig, config_log_state *cls,
+ const array_header *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_len == 0)
+ iovec[8].iov_len = strlen(iovec[8].iov_base);
+
+ /* "\" " */
+ 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,
array_header *default_format)
{
log_format_item *items;
- char *str, *s;
- const char **strs;
- int *strl;
request_rec *orig;
- int i;
- int len = 0;
+ int i, len;
array_header *format;
char *envar;
+ struct iovec local_iovec[20], *iovec;
if (cls->fname == NULL) {
return DECLINED;
@@ -774,12 +966,6 @@
}
}
- format = cls->format ? cls->format : default_format;
-
- strs = ap_palloc(r->pool, sizeof(char *) * (format->nelts));
- strl = ap_palloc(r->pool, sizeof(int) * (format->nelts));
- items = (log_format_item *) format->elts;
-
orig = r;
while (orig->prev) {
orig = orig->prev;
@@ -788,43 +974,30 @@
r = r->next;
}
- for (i = 0; i < format->nelts; ++i) {
- strs[i] = process_item(r, orig, &items[i]);
- }
+ format = cls->format ? cls->format : default_format;
- for (i = 0; i < format->nelts; ++i) {
- len += strl[i] = ap_strlen(strs[i]);
- }
+#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 = ap_palloc(r->pool, len + 1);
- for (i = 0, s = str; i < format->nelts; ++i) {
- memcpy(s, strs[i], strl[i]);
- s += strl[i];
- }
- 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 = ap_palloc(r->pool, len + 1);
+ len = 0;
+ if (format->nelts <= sizeof local_iovec / sizeof local_iovec[0])
+ iovec = local_iovec;
+ else
+ iovec = ap_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;
}
- write(cls->log_fd, str, len);
-#endif
+ log_vec(r, cls, iovec, format->nelts, len);
return OK;
}
@@ -875,7 +1048,7 @@
mls->default_format = NULL;
mls->server_config_logs = NULL;
mls->formats = ap_make_table(p, 4);
- ap_table_setn(mls->formats, "CLF", DEFAULT_LOG_FORMAT);
+ ap_table_setn(mls->formats, "CLF", common_log_format);
return mls;
}
@@ -1043,7 +1216,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) {