summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Christopher Powell 2001-12-07 03:52:56 +0000
committerGravatar Christopher Powell 2001-12-07 03:52:56 +0000
commit3ddc5c9b88226097f93d4c21ea51f7a37f0e56f3 (patch)
treeb141b4bfc8532e3640ca6dd7204538f74079742e
parent84fbbe1411ec93b3aa97ad535f0f9ce737f62a52 (diff)
Added a mysql_close mechanism to the child exit process to fix MySQL
complaining about bad communication packets. Considerable code reorg and cleanup.
-rw-r--r--CHANGELOG10
-rw-r--r--Makefile21
-rw-r--r--README27
-rw-r--r--access_log.sql10
-rw-r--r--mod_log_sql.c468
5 files changed, 232 insertions, 304 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 64422e0..5479725 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,4 +1,4 @@
1$Id: CHANGELOG,v 1.3 2001/12/03 19:54:02 helios Exp $ 1$Id: CHANGELOG,v 1.4 2001/12/07 03:52:56 helios Exp $
2 2
3 3
4TODO: 4TODO:
@@ -8,6 +8,14 @@ TODO:
8 8
9CHANGES: 9CHANGES:
10 10
111.12:
12
13* Added a mysql_close() call to get rid of those annoying MySQL
14 complaints every time an httpd child process terminates. (Apache
15 1.3 or later.)
16* Considerable code reorganization and cleanup.
17
18
111.11: 191.11:
12 20
13* Completely re-worked the cookie code. Now the user can instruct 21* Completely re-worked the cookie code. Now the user can instruct
diff --git a/Makefile b/Makefile
index c1966b2..5744be4 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
1# $Id: Makefile,v 1.3 2001/12/03 19:56:58 helios Exp $ 1# $Id: Makefile,v 1.4 2001/12/07 03:52:56 helios Exp $
2 2
3# Verify that this points to the right place... 3# Verify that this points to the right place...
4APACHEDIR = /usr/local/src/apache_1.3.22 4APACHEDIR = /usr/local/src/apache_1.3.22
@@ -9,9 +9,10 @@ APACHEDIR = /usr/local/src/apache_1.3.22
9DEFS = -DWANT_SSL_LOGGING 9DEFS = -DWANT_SSL_LOGGING
10#DEFS = 10#DEFS =
11 11
12# Use this one if you do WANT_SSL_LOGGING, and confirm the last two paths. 12# Use this one if you do WANT_SSL_LOGGING, and confirm the last three paths.
13# Make "/usr/local/ssl/include" point to where your openssl/*.h files are, 13# Point "/usr/local/ssl/include" to where your openssl/*.h files are,
14# and make "/usr/include/db1" point to where ndbm.h can be found. 14# Point "/usr/include/db1" to where ndbm.h can be found,
15# Point "/usr/local/src/apache_1.3.22/src/modules/ssl" to where mod_ssl.h can be found.
15# 16#
16# How to find your directories: 17# How to find your directories:
17# 18#
@@ -23,11 +24,13 @@ DEFS = -DWANT_SSL_LOGGING
23# 24#
24# $ locate ndbm.h 25# $ locate ndbm.h
25# /usr/include/db1/ndbm.h 26# /usr/include/db1/ndbm.h
27#
28# $ locate mod_ssl.h
29# /usr/local/src/apache_1.3.22/src/modules/ssl/mod_ssl.h
26 30
27CFLAGS = -fpic -O2 -Wall -I/usr/local/Apache/include -I/usr/local/ssl/include -I/usr/include/db1 31CFLAGS = -fpic -O2 -Wall -I/usr/local/Apache/include -I/usr/local/ssl/include -I/usr/include/db1 -I/usr/local/src/apache_1.3.22/src/modules/ssl
28 32
29# Use this one if you don't WANT_SSL_LOGGING: 33# Use this one if you don't WANT_SSL_LOGGING:
30
31#CFLAGS = -fpic -O2 -Wall -I/usr/local/Apache/include 34#CFLAGS = -fpic -O2 -Wall -I/usr/local/Apache/include
32 35
33 36
@@ -40,8 +43,8 @@ INSTALL = /usr/bin/install -m 664
40all: mod_log_mysql.o 43all: mod_log_mysql.o
41 44
42mod_log_mysql.o: mod_log_mysql.c Makefile 45mod_log_mysql.o: mod_log_mysql.c Makefile
43 $(CC) ${CFLAGS} ${DEFS} -c mod_log_mysql.c 46 $(CC) ${CFLAGS} ${DEFS} -c mod_log_mysql.c
44 47
45install: all 48install: all
46 $(INSTALL) mod_log_mysql.o ${APACHEDIR}/src/mod_log_mysql.o 49 $(INSTALL) mod_log_mysql.o ${APACHEDIR}/src/mod_log_mysql.o
47 50
@@ -49,7 +52,7 @@ distro: all
49 cp -f INSTALL /usr/local/Apache/html/mod_log_mysql/ 52 cp -f INSTALL /usr/local/Apache/html/mod_log_mysql/
50 cp -f README /usr/local/Apache/html/mod_log_mysql/ 53 cp -f README /usr/local/Apache/html/mod_log_mysql/
51 cp -f CHANGELOG /usr/local/Apache/html/mod_log_mysql/ 54 cp -f CHANGELOG /usr/local/Apache/html/mod_log_mysql/
52 cd ..; tar zcf mod_log_mysql.tar.gz mod_log_mysql/; $(INSTALL) mod_log_mysql.tar.gz /usr/local/Apache/html/mod_log_mysql/; rm -f mod_log_mysql.tar.gz 55 cd ..; tar zcf mod_log_mysql.tar.gz --exclude mod_log_mysql/CVS mod_log_mysql/; $(INSTALL) mod_log_mysql.tar.gz /usr/local/Apache/html/mod_log_mysql/; rm -f mod_log_mysql.tar.gz
53 56
54clean: 57clean:
55 rm -f *.o *~ 58 rm -f *.o *~
diff --git a/README b/README
index 9fee671..d25bc06 100644
--- a/README
+++ b/README
@@ -1,4 +1,4 @@
1$Id: README,v 1.2 2001/12/03 19:54:02 helios Exp $ 1$Id: README,v 1.3 2001/12/07 03:52:56 helios Exp $
2 2
3 3
4Homepage 4Homepage
@@ -105,10 +105,6 @@ request_uri: corresponds to the Apache %U directive. Contains the
105 needed for log analysis, and saves the database a LOT of wasted growth 105 needed for log analysis, and saves the database a LOT of wasted growth
106 on unneeded bytes. 106 on unneeded bytes.
107 107
108request_duration: corresponds to the Apache %T directive. Contains the
109 time in seconds that it took to serve the request.
110 Example: 2
111
112virtual_host: contains the VirtualHost that is making the log entry. This 108virtual_host: contains the VirtualHost that is making the log entry. This
113 allows you to log multiple VirtualHosts to a single MySQL database and 109 allows you to log multiple VirtualHosts to a single MySQL database and
114 yet still be able to extract them for separate analysis. 110 yet still be able to extract them for separate analysis.
@@ -149,7 +145,7 @@ Notes
149* The 'time_stamp' field is stored in an UNSIGNED INTEGER column, in the 145* The 'time_stamp' field is stored in an UNSIGNED INTEGER column, in the
150 standard unix "seconds since 1/1/1970 12:00:00" format. This is 146 standard unix "seconds since 1/1/1970 12:00:00" format. This is
151 superior to storing the access time as a string due to size 147 superior to storing the access time as a string due to size
152 requirements: an UNSIGNED INT type fits in 4 bytes. The Apache date 148 requirements: an UNSIGNED INT type fits in 4 bytes, whereas the Apache date
153 string (e.g. "18/Nov/2001:13:59:52 -0800") requires 26 bytes -- 149 string (e.g. "18/Nov/2001:13:59:52 -0800") requires 26 bytes --
154 significantly larger, and those extra 22 bytes will add up over the 150 significantly larger, and those extra 22 bytes will add up over the
155 thousands of accesses that a busy server will experience. Besides, 151 thousands of accesses that a busy server will experience. Besides,
@@ -187,19 +183,6 @@ Notes
187 makes perfect sense anyway. 183 makes perfect sense anyway.
188 184
189 185
190Disclaimer
191----------
192
193It works for me (I've tested it on my '2 hits/busy day' home Linux box,
194and afterwards on our pretty busy tucows mirror (>100K hits a day) and
195it appears to be working fine.
196
197If it doesn't, and causes you damage of any sort, including but not
198limited to losing logs, losing money or your girlfriend leaving you
199(read 'boyfriend' where applicable), I'm not liable to anything. Bug
200reports and constructive flame mail are ok, though (both about the code
201and this quickly-written README file).
202
203 186
204Author / Maintainer 187Author / Maintainer
205------------------- 188-------------------
@@ -207,11 +190,11 @@ Author / Maintainer
207The actual logging code was taken from the already existing flat file 190The actual logging code was taken from the already existing flat file
208text modules, so all that credit goes to the Apache Server group. 191text modules, so all that credit goes to the Apache Server group.
209 192
210The MySQL routines and directives was added in by Zeev Suraski 193The MySQL routines and directives were added by Zeev Suraski
211<bourbon@netvision.net.il> 194<bourbon@netvision.net.il>.
212 195
213Changes from 1.06 on and the new documentation were added by 196Changes from 1.06 on and the new documentation were added by
214Chris Powell <chris@grubbybaby.com>. It seems that the module had fallen 197Chris Powell <chris@grubbybaby.com>. It seems that the module had fallen
215into the "unmaintained" category -- it hadn't been updated since 1998 -- 198into the "unmaintained" category -- it hadn't been updated since 1998 --
216so I've adopted it as the new maintainer. 199so Chris adopted it as the new maintainer.
217 200
diff --git a/access_log.sql b/access_log.sql
index 46d5a6e..a667494 100644
--- a/access_log.sql
+++ b/access_log.sql
@@ -10,16 +10,16 @@ create table access_log (
10 remote_user varchar(50) not null, 10 remote_user varchar(50) not null,
11 request_duration smallint not null, 11 request_duration smallint not null,
12 request_line varchar(255), 12 request_line varchar(255),
13 request_method not null, 13 request_method varchar(6) not null,
14 request_protocol not null, 14 request_protocol varchar(10) not null,
15 request_time char(28), 15 request_time char(28),
16 request_uri varchar(50) not null, 16 request_uri varchar(50) not null,
17 server_port smallint unsigned, 17 server_port smallint unsigned,
18 ssl_cipher varchar(25), 18 ssl_cipher varchar(25),
19 ssl_keysize smallint 19 ssl_keysize smallint unsigned,
20 ssl_maxkeysize smallint, 20 ssl_maxkeysize smallint unsigned,
21 status smallint not null, 21 status smallint not null,
22 time_stamp int unsigned not null, 22 time_stamp int unsigned not null,
23 virtual_host varchar(50) not null, 23 virtual_host varchar(50) not null
24) 24)
25 25
diff --git a/mod_log_sql.c b/mod_log_sql.c
index 5bb992b..efbf45c 100644
--- a/mod_log_sql.c
+++ b/mod_log_sql.c
@@ -1,85 +1,11 @@
1/* $Id: mod_log_sql.c,v 1.3 2001/12/03 19:54:02 helios Exp $ 1/* $Id: mod_log_sql.c,v 1.4 2001/12/07 03:52:56 helios Exp $ */
2 *
3 * mod_log_mysql.c
4 * Release v 1.10
5 *
6 * Hi, I'm the new maintainer of this code. If you have any questions,
7 * comments or suggestions (which are always welcome), please contact Chris
8 * Powell <chris@grubbybaby.com>. This code still falls under the rules of
9 * the Apache license, and all credit for the code up to my changes is still
10 * preserved below.
11 *
12 * ====================================================================
13 *
14 * The original preface from version 1.05: This module was patched, wrapped
15 * and coded by Zeev Suraski <bourbon@netvision.net.il>
16 *
17 * It may be used freely, with the same restrictions as its predecessors
18 * (specified below). This module is based on code from standard apache
19 * modules. Their copyright notice follows.
20 *
21 * ====================================================================
22 * Copyright (c) 1995-1997 The Apache Group. All rights reserved.
23 *
24 * Redistribution and use in source and binary forms, with or without
25 * modification, are permitted provided that the following conditions
26 * are met:
27 *
28 * 1. Redistributions of source code must retain the above copyright
29 * notice, this list of conditions and the following disclaimer.
30 *
31 * 2. Redistributions in binary form must reproduce the above copyright
32 * notice, this list of conditions and the following disclaimer in
33 * the documentation and/or other materials provided with the
34 * distribution.
35 *
36 * 3. All advertising materials mentioning features or use of this
37 * software must display the following acknowledgment:
38 * "This product includes software developed by the Apache Group
39 * for use in the Apache HTTP server project (http://www.apache.org/)."
40 *
41 * 4. The names "Apache Server" and "Apache Group" must not be used to
42 * endorse or promote products derived from this software without
43 * prior written permission.
44 *
45 * 5. Redistributions of any form whatsoever must retain the following
46 * acknowledgment:
47 * "This product includes software developed by the Apache Group
48 * for use in the Apache HTTP server project (http://www.apache.org/)."
49 *
50 * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
51 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
53 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR
54 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
55 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
56 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
57 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
59 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
60 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
61 * OF THE POSSIBILITY OF SUCH DAMAGE.
62 * ====================================================================
63 *
64 * This software consists of voluntary contributions made by many
65 * individuals on behalf of the Apache Group and was originally based
66 * on public domain software written at the National Center for
67 * Supercomputing Applications, University of Illinois, Urbana-Champaign.
68 * For more information on the Apache Group and the Apache HTTP server
69 * project, please see <http://www.apache.org/>.
70 *
71 */
72 2
73 3
74/* DEFINES */ 4/* DEFINES */
75#define MYSQL_ERROR(mysql) ((mysql)?(mysql_error(mysql)):"MySQL server has gone away") 5#define MYSQL_ERROR(mysql) ((mysql)?(mysql_error(mysql)):"MySQL server has gone away")
76
77#define ERRLEVEL APLOG_ERR|APLOG_NOERRNO 6#define ERRLEVEL APLOG_ERR|APLOG_NOERRNO
78 7#define DEBUGLEVEL APLOG_INFO|APLOG_NOERRNO
79#undef DEBUG 8/* (DEBUG and WANT_SSL_LOGGING are defined in the Makefile DEFS line.) */
80#ifdef DEBUG
81 #define DEBUGLEVEL APLOG_INFO|APLOG_NOERRNO
82#endif
83 9
84 10
85 11
@@ -92,24 +18,35 @@
92#include "http_config.h" 18#include "http_config.h"
93#include "http_log.h" 19#include "http_log.h"
94#include "http_core.h" 20#include "http_core.h"
95#if MODULE_MAGIC_NUMBER >= 19980324 21
22/* M_M_N is defined in /usr/local/Apache/include/ap_mmn.h, 19990320 as of this writing. */
23#if MODULE_MAGIC_NUMBER >= 19980324 /* 1.3b6 or later */
96 #include "ap_compat.h" 24 #include "ap_compat.h"
97#endif 25#endif
98 26
99#ifdef WANT_SSL_LOGGING 27#ifdef WANT_SSL_LOGGING /* Defined in Makefile */
100 #include "/usr/local/src/apache_1.3.22/src/modules/ssl/mod_ssl.h" 28 #include "mod_ssl.h"
101#endif 29#endif
102 30
103 31
104 32
105/* DECLARATIONS */ 33/* DECLARATIONS */
106module mysql_log_module; 34module mysql_log_module;
107MYSQL log_sql_server, *mysql_log = NULL; 35
108char *log_db_name = NULL, *db_host = NULL, *db_user = NULL, *db_pwd = NULL, *cookie_name = NULL; 36MYSQL sql_server, *mysql_log = NULL;
37
38char *db_name = NULL;
39char *db_host = NULL;
40char *db_user = NULL;
41char *db_pwd = NULL;
42char *cookie_name = NULL;
109 43
110typedef const char *(*item_key_func) (request_rec *, char *); 44typedef const char *(*item_key_func) (request_rec *, char *);
45
111typedef struct { 46typedef struct {
112 char *referer_table_name, *agent_table_name, *transfer_table_name; 47 char *referer_table_name;
48 char *agent_table_name;
49 char *transfer_table_name;
113 array_header *referer_ignore_list; 50 array_header *referer_ignore_list;
114 array_header *transfer_ignore_list; 51 array_header *transfer_ignore_list;
115 array_header *remhost_ignore_list; 52 array_header *remhost_ignore_list;
@@ -118,29 +55,7 @@ typedef struct {
118 55
119 56
120 57
121#if MODULE_MAGIC_NUMBER < 19970103 /* Defined in /usr/local/Apache/include/ap_mmn.h, 19990320 as of this writing. */ 58/* FUNCTIONS */
122extern const char *log_request_protocol(request_rec *r, char *a);
123extern const char *log_request_method(request_rec *r, char *a);
124extern const char *log_remote_host(request_rec *r, char *a);
125extern const char *log_remote_logname(request_rec *r, char *a);
126extern const char *log_remote_user(request_rec *r, char *a);
127extern const char *log_request_time(request_rec *r, char *a);
128extern const char *log_request_timestamp(request_rec *r, char *a);
129extern const char *log_request_duration(request_rec *r, char *a);
130extern const char *log_request_line(request_rec *r, char *a);
131extern const char *log_request_file(request_rec *r, char *a);
132extern const char *log_request_uri(request_rec *r, char *a);
133extern const char *log_status(request_rec *r, char *a);
134extern const char *log_bytes_sent(request_rec *r, char *a);
135extern const char *log_header_in(request_rec *r, char *a);
136extern const char *log_header_out(request_rec *r, char *a);
137extern const char *log_note(request_rec *r, char *a);
138extern const char *log_env_var(request_rec *r, char *a);
139extern const char *log_virtual_host(request_rec *r, char *a);
140extern const char *log_server_port(request_rec *r, char *a);
141extern const char *log_child_pid(request_rec *r, char *a);
142#else
143
144static char *format_integer(pool *p, int i) 59static char *format_integer(pool *p, int i)
145{ 60{
146 char dummy[40]; 61 char dummy[40];
@@ -162,17 +77,17 @@ static char *pfmt(pool *p, int i)
162 * value to the calling entity. 77 * value to the calling entity.
163 */ 78 */
164 79
165static const char *log_remote_host(request_rec *r, char *a) 80static const char *extract_remote_host(request_rec *r, char *a)
166{ 81{
167 return (char *) get_remote_host(r->connection, r->per_dir_config, REMOTE_NAME); 82 return (char *) get_remote_host(r->connection, r->per_dir_config, REMOTE_NAME);
168} 83}
169 84
170static const char *log_remote_logname(request_rec *r, char *a) 85static const char *extract_remote_logname(request_rec *r, char *a)
171{ 86{
172 return (char *) get_remote_logname(r); 87 return (char *) get_remote_logname(r);
173} 88}
174 89
175static const char *log_remote_user(request_rec *r, char *a) 90static const char *extract_remote_user(request_rec *r, char *a)
176{ 91{
177 char *rvalue = r->connection->user; 92 char *rvalue = r->connection->user;
178 93
@@ -185,7 +100,7 @@ static const char *log_remote_user(request_rec *r, char *a)
185} 100}
186 101
187#ifdef WANT_SSL_LOGGING 102#ifdef WANT_SSL_LOGGING
188static const char *log_ssl_keysize(request_rec *r, char *a) 103static const char *extract_ssl_keysize(request_rec *r, char *a)
189{ 104{
190 char *result = NULL; 105 char *result = NULL;
191 106
@@ -202,7 +117,7 @@ static const char *log_ssl_keysize(request_rec *r, char *a)
202 } 117 }
203} 118}
204 119
205static const char *log_ssl_maxkeysize(request_rec *r, char *a) 120static const char *extract_ssl_maxkeysize(request_rec *r, char *a)
206{ 121{
207 char *result = NULL; 122 char *result = NULL;
208 123
@@ -219,7 +134,7 @@ static const char *log_ssl_maxkeysize(request_rec *r, char *a)
219 } 134 }
220} 135}
221 136
222static const char *log_ssl_cipher(request_rec *r, char *a) 137static const char *extract_ssl_cipher(request_rec *r, char *a)
223{ 138{
224 char *result = NULL; 139 char *result = NULL;
225 140
@@ -232,42 +147,42 @@ static const char *log_ssl_cipher(request_rec *r, char *a)
232 result = NULL; 147 result = NULL;
233 return result; 148 return result;
234 } else { 149 } else {
235 return "0"; 150 return "-";
236 } 151 }
237} 152}
238#endif /* WANT_SSL_LOGGING */ 153#endif /* WANT_SSL_LOGGING */
239 154
240static const char *log_request_method(request_rec *r, char *a) 155static const char *extract_request_method(request_rec *r, char *a)
241{ 156{
242 return r->method; 157 return r->method;
243} 158}
244 159
245static const char *log_request_protocol(request_rec *r, char *a) 160static const char *extract_request_protocol(request_rec *r, char *a)
246{ 161{
247 return r->protocol; 162 return r->protocol;
248} 163}
249 164
250static const char *log_request_line(request_rec *r, char *a) 165static const char *extract_request_line(request_rec *r, char *a)
251{ 166{
252 return r->the_request; 167 return r->the_request;
253} 168}
254 169
255static const char *log_request_file(request_rec *r, char *a) 170static const char *extract_request_file(request_rec *r, char *a)
256{ 171{
257 return r->filename; 172 return r->filename;
258} 173}
259 174
260static const char *log_request_uri(request_rec *r, char *a) 175static const char *extract_request_uri(request_rec *r, char *a)
261{ 176{
262 return r->uri; 177 return r->uri;
263} 178}
264 179
265static const char *log_status(request_rec *r, char *a) 180static const char *extract_status(request_rec *r, char *a)
266{ 181{
267 return pfmt(r->pool, r->status); 182 return pfmt(r->pool, r->status);
268} 183}
269 184
270static const char *log_bytes_sent(request_rec *r, char *a) 185static const char *extract_bytes_sent(request_rec *r, char *a)
271{ 186{
272 if (!r->sent_bodyct) { 187 if (!r->sent_bodyct) {
273 return "-"; 188 return "-";
@@ -280,12 +195,12 @@ static const char *log_bytes_sent(request_rec *r, char *a)
280 } 195 }
281} 196}
282 197
283static const char *log_header_in(request_rec *r, char *a) 198static const char *extract_header_in(request_rec *r, char *a)
284{ 199{
285 return table_get(r->headers_in, a); 200 return table_get(r->headers_in, a);
286} 201}
287 202
288static const char *log_header_out(request_rec *r, char *a) 203static const char *extract_header_out(request_rec *r, char *a)
289{ 204{
290 const char *cp = table_get(r->headers_out, a); 205 const char *cp = table_get(r->headers_out, a);
291 if (!strcasecmp(a, "Content-type") && r->content_type) { 206 if (!strcasecmp(a, "Content-type") && r->content_type) {
@@ -297,7 +212,7 @@ static const char *log_header_out(request_rec *r, char *a)
297 return table_get(r->err_headers_out, a); 212 return table_get(r->err_headers_out, a);
298} 213}
299 214
300static const char *log_request_time(request_rec *r, char *a) 215static const char *extract_request_time(request_rec *r, char *a)
301{ 216{
302 int timz; 217 int timz;
303 struct tm *t; 218 struct tm *t;
@@ -320,7 +235,7 @@ static const char *log_request_time(request_rec *r, char *a)
320 return pstrdup(r->pool, tstr); 235 return pstrdup(r->pool, tstr);
321} 236}
322 237
323static const char *log_request_duration(request_rec *r, char *a) 238static const char *extract_request_duration(request_rec *r, char *a)
324{ 239{
325 char duration[22]; /* Long enough for 2^64 */ 240 char duration[22]; /* Long enough for 2^64 */
326 241
@@ -328,12 +243,12 @@ static const char *log_request_duration(request_rec *r, char *a)
328 return pstrdup(r->pool, duration); 243 return pstrdup(r->pool, duration);
329} 244}
330 245
331static const char *log_virtual_host(request_rec *r, char *a) 246static const char *extract_virtual_host(request_rec *r, char *a)
332{ 247{
333 return pstrdup(r->pool, r->server->server_hostname); 248 return pstrdup(r->pool, r->server->server_hostname);
334} 249}
335 250
336static const char *log_server_port(request_rec *r, char *a) 251static const char *extract_server_port(request_rec *r, char *a)
337{ 252{
338 char portnum[22]; 253 char portnum[22];
339 254
@@ -341,14 +256,14 @@ static const char *log_server_port(request_rec *r, char *a)
341 return pstrdup(r->pool, portnum); 256 return pstrdup(r->pool, portnum);
342} 257}
343 258
344static const char *log_child_pid(request_rec *r, char *a) 259static const char *extract_child_pid(request_rec *r, char *a)
345{ 260{
346 char pidnum[22]; 261 char pidnum[22];
347 ap_snprintf(pidnum, sizeof(pidnum), "%ld", (long) getpid()); 262 ap_snprintf(pidnum, sizeof(pidnum), "%ld", (long) getpid());
348 return pstrdup(r->pool, pidnum); 263 return pstrdup(r->pool, pidnum);
349} 264}
350 265
351static const char *log_referer(request_rec *r, char *a) 266static const char *extract_referer(request_rec *r, char *a)
352{ 267{
353 const char *tempref; 268 const char *tempref;
354 269
@@ -361,7 +276,7 @@ static const char *log_referer(request_rec *r, char *a)
361 } 276 }
362} 277}
363 278
364static const char *log_agent(request_rec *r, char *a) 279static const char *extract_agent(request_rec *r, char *a)
365{ 280{
366 const char *tempag; 281 const char *tempag;
367 282
@@ -374,7 +289,7 @@ static const char *log_agent(request_rec *r, char *a)
374 } 289 }
375} 290}
376 291
377static const char *log_cookie(request_rec *r, char *a) 292static const char *extract_cookie(request_rec *r, char *a)
378{ 293{
379 const char *cookiestr; 294 const char *cookiestr;
380 char *cookieend; 295 char *cookieend;
@@ -396,7 +311,6 @@ static const char *log_cookie(request_rec *r, char *a)
396 return cookiebuf; 311 return cookiebuf;
397 } 312 }
398 } 313 }
399
400 314
401 cookiestr = (char *)table_get(r->headers_in, "cookie"); 315 cookiestr = (char *)table_get(r->headers_in, "cookie");
402 if (cookiestr != NULL) { 316 if (cookiestr != NULL) {
@@ -414,7 +328,6 @@ static const char *log_cookie(request_rec *r, char *a)
414 } 328 }
415 } 329 }
416 330
417
418 cookiestr = table_get(r->headers_out, "set-cookie"); 331 cookiestr = table_get(r->headers_out, "set-cookie");
419 if (cookiestr != NULL) { 332 if (cookiestr != NULL) {
420 #ifdef DEBUG 333 #ifdef DEBUG
@@ -434,8 +347,7 @@ static const char *log_cookie(request_rec *r, char *a)
434 return "-"; 347 return "-";
435} 348}
436 349
437 350static const char *extract_request_timestamp(request_rec *r, char *a)
438const char *log_request_timestamp(request_rec *r, char *a)
439{ 351{
440 char tstr[32]; 352 char tstr[32];
441 353
@@ -443,19 +355,18 @@ const char *log_request_timestamp(request_rec *r, char *a)
443 return pstrdup(r->pool, tstr); 355 return pstrdup(r->pool, tstr);
444} 356}
445 357
446static const char *log_note(request_rec *r, char *a) 358static const char *extract_note(request_rec *r, char *a)
447{ 359{
448 return table_get(r->notes, a); 360 return table_get(r->notes, a);
449} 361}
450 362
451static const char *log_env_var(request_rec *r, char *a) 363static const char *extract_env_var(request_rec *r, char *a)
452{ 364{
453 return table_get(r->subprocess_env, a); 365 return table_get(r->subprocess_env, a);
454} 366}
455#endif /* MODULE_MAGIC_NUMBER */
456 367
368/* End declarations of various extract_ functions */
457 369
458/* End declarations of various log_ functions */
459 370
460 371
461struct log_mysql_item_list { 372struct log_mysql_item_list {
@@ -466,39 +377,39 @@ struct log_mysql_item_list {
466 int string_contents; 377 int string_contents;
467 } log_mysql_item_keys[] = { 378 } log_mysql_item_keys[] = {
468 379
469 { 'A', log_agent, "agent", 1, 1 }, 380 { 'A', extract_agent, "agent", 1, 1 },
470 { 'b', log_bytes_sent, "bytes_sent", 0, 0 }, 381 { 'b', extract_bytes_sent, "bytes_sent", 0, 0 },
471 { 'c', log_cookie, "cookie", 0, 1 }, 382 { 'c', extract_cookie, "cookie", 0, 1 },
472 { 'e', log_env_var, "env_var", 0, 1 }, 383 { 'e', extract_env_var, "env_var", 0, 1 },
473 { 'f', log_request_file, "request_file", 0, 1 }, 384 { 'f', extract_request_file, "request_file", 0, 1 },
474 { 'H', log_request_protocol, "request_protocol", 0, 1 }, 385 { 'H', extract_request_protocol, "request_protocol", 0, 1 },
475 { 'h', log_remote_host, "remote_host", 0, 1 }, 386 { 'h', extract_remote_host, "remote_host", 0, 1 },
476 { 'i', log_header_in, "header_in", 0, 1 }, 387 { 'i', extract_header_in, "header_in", 0, 1 },
477 { 'l', log_remote_logname, "remote_logname", 0, 1 }, 388 { 'l', extract_remote_logname, "remote_logname", 0, 1 },
478 { 'm', log_request_method, "request_method", 0, 1 }, 389 { 'm', extract_request_method, "request_method", 0, 1 },
479 { 'n', log_note, "note", 0, 1 }, 390 { 'n', extract_note, "note", 0, 1 },
480 { 'o', log_header_out, "header_out", 0, 1 }, 391 { 'o', extract_header_out, "header_out", 0, 1 },
481 { 'P', log_child_pid, "child_pid", 0, 0 }, 392 { 'P', extract_child_pid, "child_pid", 0, 0 },
482 { 'p', log_server_port, "server_port", 0, 0 }, 393 { 'p', extract_server_port, "server_port", 0, 0 },
483 { 'R', log_referer, "referer", 1, 1 }, 394 { 'R', extract_referer, "referer", 1, 1 },
484 { 'r', log_request_line, "request_line", 1, 1 }, 395 { 'r', extract_request_line, "request_line", 1, 1 },
485 { 'S', log_request_timestamp, "time_stamp", 0, 0 }, 396 { 'S', extract_request_timestamp, "time_stamp", 0, 0 },
486 { 's', log_status, "status", 1, 0 }, 397 { 's', extract_status, "status", 1, 0 },
487 { 'T', log_request_duration, "request_duration", 1, 0 }, 398 { 'T', extract_request_duration, "request_duration", 1, 0 },
488 { 't', log_request_time, "request_time", 0, 1 }, 399 { 't', extract_request_time, "request_time", 0, 1 },
489 { 'u', log_remote_user, "remote_user", 0, 1 }, 400 { 'u', extract_remote_user, "remote_user", 0, 1 },
490 { 'U', log_request_uri, "request_uri", 1, 1 }, 401 { 'U', extract_request_uri, "request_uri", 1, 1 },
491 { 'v', log_virtual_host, "virtual_host", 0, 1 }, 402 { 'v', extract_virtual_host, "virtual_host", 0, 1 },
492 #ifdef WANT_SSL_LOGGING 403 #ifdef WANT_SSL_LOGGING
493 { 'q', log_ssl_keysize, "ssl_keysize", 0, 1 }, 404 { 'q', extract_ssl_keysize, "ssl_keysize", 0, 1 },
494 { 'Q', log_ssl_maxkeysize, "ssl_maxkeysize", 0, 1 }, 405 { 'Q', extract_ssl_maxkeysize, "ssl_maxkeysize", 0, 1 },
495 { 'z', log_ssl_cipher, "ssl_cipher", 0, 1 }, 406 { 'z', extract_ssl_cipher, "ssl_cipher", 0, 1 },
496 #endif 407 #endif
497 {'\0'} 408 {'\0'}
498}; 409};
499 410
500 411
501/* Routine to escape 'dangerous' characters that would otherwise 412/* Routine to escape the 'dangerous' characters that would otherwise
502 * corrupt the INSERT string: ', \, and " 413 * corrupt the INSERT string: ', \, and "
503 */ 414 */
504const char *mysql_escape_log(const char *str, pool *p) 415const char *mysql_escape_log(const char *str, pool *p)
@@ -528,7 +439,7 @@ const char *mysql_escape_log(const char *str, pool *p)
528 /* Pre-allocate a new string that could hold twice the original, which would only 439 /* Pre-allocate a new string that could hold twice the original, which would only
529 * happen if the whole original string was 'dangerous' characters. 440 * happen if the whole original string was 'dangerous' characters.
530 */ 441 */
531 tmp_str = (char *) palloc(p, length *2 + 1); 442 tmp_str = (char *) palloc(p, length * 2 + 1);
532 if (!tmp_str) { 443 if (!tmp_str) {
533 return str; 444 return str;
534 } 445 }
@@ -552,16 +463,15 @@ const char *mysql_escape_log(const char *str, pool *p)
552 } 463 }
553} 464}
554 465
555 466void open_logdb_link()
556void open_log_dblink()
557{ 467{
558 if (mysql_log != NULL) { /* virtual database link shared with main server */ 468 if (mysql_log != NULL) { /* virtual database link shared with main server */
559 return; 469 return;
560 } 470 }
561 if (log_db_name) { /* open an SQL link */ 471 if (db_name) { /* open an SQL link */
562 mysql_log = mysql_connect(&log_sql_server, db_host, db_user, db_pwd); 472 mysql_log = mysql_connect(&sql_server, db_host, db_user, db_pwd);
563 if (mysql_log) { /* link opened */ 473 if (mysql_log) { /* link opened */
564 if (mysql_select_db(mysql_log, log_db_name) != 0) { /* unable to select database */ 474 if (mysql_select_db(mysql_log, db_name) != 0) { /* unable to select database */
565 mysql_close(mysql_log); 475 mysql_close(mysql_log);
566 mysql_log = NULL; 476 mysql_log = NULL;
567 } 477 }
@@ -569,23 +479,72 @@ void open_log_dblink()
569 } 479 }
570} 480}
571 481
572 482int safe_mysql_query(request_rec *r, const char *query)
573void *make_log_mysql_state(pool *p, server_rec *s)
574{ 483{
575 log_mysql_state *cls = (log_mysql_state *) palloc(p, sizeof(log_mysql_state)); 484 int retval = 1;
485 struct timespec delay, remainder;
486 int ret;
487 char *str;
488 void (*handler) (int);
576 489
577 cls->referer_table_name = cls->agent_table_name = cls->transfer_table_name = ""; 490 /* A failed mysql_query() may send a SIGPIPE, so we ignore that signal momentarily. */
578 cls->referer_ignore_list = make_array(p, 1, sizeof(char *)); 491 handler = signal(SIGPIPE, SIG_IGN);
579 cls->transfer_ignore_list = make_array(p, 1, sizeof(char *)); 492
580 cls->remhost_ignore_list = make_array(p, 1, sizeof(char *)); 493 /* If there's no DB link, or if we run the query and it gacks, try to be graceful */
581 cls->transfer_log_format = ""; 494 if ( !mysql_log ||
582 return (void *) cls; 495 (
496 (retval = mysql_query(mysql_log, query)) &&
497 (mysql_errno(mysql_log) != 0)
498 )
499 )
500
501 { /* We need to restart the server link */
502 mysql_log = NULL;
503 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"MySQL: connection lost, attempting reconnect");
504
505 open_logdb_link();
506
507 if (mysql_log == NULL) { /* still unable to link */
508 signal(SIGPIPE, handler);
509 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"MySQL: reconnect failed");
510 return retval;
511 }
512
513 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"MySQL: reconnect successful");
514 retval = mysql_query(mysql_log, query);
515 }
516
517 /* Restore SIGPIPE to its original handler function */
518 signal(SIGPIPE, handler);
519
520 if (retval) {
521 /* Attempt a single re-try... First sleep for a tiny amount of time. */
522 delay.tv_sec = 0;
523 delay.tv_nsec = 500000000; /* max is 999999999 (nine nines) */
524 ret = nanosleep(&delay, &remainder);
525 if (ret && errno != EINTR)
526 perror("nanosleep");
527
528 /* Now re-attempt */
529 retval = mysql_query(mysql_log,query);
530
531 if (retval) {
532 str = pstrcat(r->pool, "MySQL insert failed: ", query, NULL);
533 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,str);
534 str = pstrcat(r->pool, "MySQL failure reason: ", MYSQL_ERROR(mysql_log), NULL);
535 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,str);
536 } else {
537 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"MySQL: insert successful after a delayed retry.");
538 }
539 }
540 return retval;
583} 541}
584 542
543
544
585const char *set_referer_log_mysql_table(cmd_parms *parms, void *dummy, char *arg) 545const char *set_referer_log_mysql_table(cmd_parms *parms, void *dummy, char *arg)
586{ 546{
587 log_mysql_state *cls = get_module_config(parms->server->module_config, 547 log_mysql_state *cls = get_module_config(parms->server->module_config, &mysql_log_module);
588 &mysql_log_module);
589 548
590 cls->referer_table_name = arg; 549 cls->referer_table_name = arg;
591 return NULL; 550 return NULL;
@@ -594,8 +553,7 @@ const char *set_referer_log_mysql_table(cmd_parms *parms, void *dummy, char *arg
594 553
595const char *set_agent_log_mysql_table(cmd_parms *parms, void *dummy, char *arg) 554const char *set_agent_log_mysql_table(cmd_parms *parms, void *dummy, char *arg)
596{ 555{
597 log_mysql_state *cls = get_module_config(parms->server->module_config, 556 log_mysql_state *cls = get_module_config(parms->server->module_config, &mysql_log_module);
598 &mysql_log_module);
599 557
600 cls->agent_table_name = arg; 558 cls->agent_table_name = arg;
601 return NULL; 559 return NULL;
@@ -604,8 +562,7 @@ const char *set_agent_log_mysql_table(cmd_parms *parms, void *dummy, char *arg)
604 562
605const char *set_transfer_log_mysql_table(cmd_parms *parms, void *dummy, char *arg) 563const char *set_transfer_log_mysql_table(cmd_parms *parms, void *dummy, char *arg)
606{ 564{
607 log_mysql_state *cls = get_module_config(parms->server->module_config, 565 log_mysql_state *cls = get_module_config(parms->server->module_config, &mysql_log_module);
608 &mysql_log_module);
609 566
610 cls->transfer_table_name = arg; 567 cls->transfer_table_name = arg;
611 return NULL; 568 return NULL;
@@ -614,8 +571,7 @@ const char *set_transfer_log_mysql_table(cmd_parms *parms, void *dummy, char *ar
614 571
615const char *set_transfer_log_format(cmd_parms *parms, void *dummy, char *arg) 572const char *set_transfer_log_format(cmd_parms *parms, void *dummy, char *arg)
616{ 573{
617 log_mysql_state *cls = get_module_config(parms->server->module_config, 574 log_mysql_state *cls = get_module_config(parms->server->module_config, &mysql_log_module);
618 &mysql_log_module);
619 575
620 cls->transfer_log_format = arg; 576 cls->transfer_log_format = arg;
621 return NULL; 577 return NULL;
@@ -624,7 +580,7 @@ const char *set_transfer_log_format(cmd_parms *parms, void *dummy, char *arg)
624 580
625const char *set_log_mysql_db(cmd_parms *parms, void *dummy, char *arg) 581const char *set_log_mysql_db(cmd_parms *parms, void *dummy, char *arg)
626{ 582{
627 log_db_name = arg; 583 db_name = arg;
628 return NULL; 584 return NULL;
629} 585}
630 586
@@ -682,103 +638,68 @@ const char *add_remhost_mysql_ignore(cmd_parms *parms, void *dummy, char *arg)
682 return NULL; 638 return NULL;
683} 639}
684 640
641
642/*
643 * Apache-specific hooks into the module code
644 * that are defined in the array 'mysql_lgog_module' (at EOF)
645 */
646
647
648/* Set up space for the various major configuration options */
649void *log_mysql_make_state(pool *p, server_rec *s)
650{
651 log_mysql_state *cls = (log_mysql_state *) palloc(p, sizeof(log_mysql_state));
652
653 cls->referer_table_name = cls->agent_table_name = cls->transfer_table_name = "";
654
655 cls->referer_ignore_list = make_array(p, 1, sizeof(char *));
656 cls->transfer_ignore_list = make_array(p, 1, sizeof(char *));
657 cls->remhost_ignore_list = make_array(p, 1, sizeof(char *));
658
659 cls->transfer_log_format = "";
660 return (void *) cls;
661}
662
663
664/* Setup of the available httpd.conf configuration commands.
665 * command, function called, NULL, where available, how many arguments, verbose description
666 */
685command_rec log_mysql_cmds[] = { 667command_rec log_mysql_cmds[] = {
686 {"MySQLRefererLogTable", set_referer_log_mysql_table, NULL, RSRC_CONF, TAKE1, 668 {"MySQLRefererLogTable", set_referer_log_mysql_table, NULL, RSRC_CONF, TAKE1,
687 "The MySQL table that holds the referer log"} 669 "The MySQL table that holds the referer log"}
688 , 670 ,
689 {"MySQLAgentLogTable", set_agent_log_mysql_table, NULL, RSRC_CONF, TAKE1, 671 {"MySQLAgentLogTable", set_agent_log_mysql_table, NULL, RSRC_CONF, TAKE1,
690 "The MySQL table that holds the agent log"} 672 "The MySQL table that holds the agent log"}
691 , 673 ,
692 {"MySQLTransferLogTable", set_transfer_log_mysql_table, NULL, RSRC_CONF, TAKE1, 674 {"MySQLTransferLogTable", set_transfer_log_mysql_table, NULL, RSRC_CONF, TAKE1,
693 "The MySQL table that holds the transfer log"} 675 "The MySQL table that holds the transfer log"}
694 , 676 ,
695 {"MySQLTransferLogFormat", set_transfer_log_format, NULL, RSRC_CONF, TAKE1, 677 {"MySQLTransferLogFormat", set_transfer_log_format, NULL, RSRC_CONF, TAKE1,
696 "Instruct the module what information to log to the MySQL transfer log"} 678 "Instruct the module what information to log to the MySQL transfer log"}
697 , 679 ,
698 {"MySQLRefererIgnore", add_referer_mysql_ignore, NULL, RSRC_CONF, ITERATE, 680 {"MySQLRefererIgnore", add_referer_mysql_ignore, NULL, RSRC_CONF, ITERATE,
699 "List of referers to ignore, accesses that match will not be logged to MySQL"} 681 "List of referers to ignore. Accesses that match will not be logged to MySQL"}
700 , 682 ,
701 {"MySQLRequestIgnore", add_transfer_mysql_ignore, NULL, RSRC_CONF, ITERATE, 683 {"MySQLRequestIgnore", add_transfer_mysql_ignore, NULL, RSRC_CONF, ITERATE,
702 "List of URIs to ignore, accesses that match will not be logged to MySQL"} 684 "List of URIs to ignore. Accesses that match will not be logged to MySQL"}
703 , 685 ,
704 {"MySQLRemhostIgnore", add_remhost_mysql_ignore, NULL, RSRC_CONF, ITERATE, 686 {"MySQLRemhostIgnore", add_remhost_mysql_ignore, NULL, RSRC_CONF, ITERATE,
705 "List of remote hosts to ignore, accesses that match will not be logged to MySQL"} 687 "List of remote hosts to ignore. Accesses that match will not be logged to MySQL"}
706 , 688 ,
707 {"MySQLDatabase", set_log_mysql_db, NULL, RSRC_CONF, TAKE1, 689 {"MySQLDatabase", set_log_mysql_db, NULL, RSRC_CONF, TAKE1,
708 "The name of the MySQL database for logging"} 690 "The name of the MySQL database for logging"}
709 , 691 ,
710 {"MySQLWhichCookie", set_log_mysql_cookie, NULL, RSRC_CONF, TAKE1, 692 {"MySQLWhichCookie", set_log_mysql_cookie, NULL, RSRC_CONF, TAKE1,
711 "The CookieName that you want logged when using the 'c' config directive"} 693 "The CookieName that you want logged when using the 'c' config directive"}
712 , 694 ,
713 {"MySQLLoginInfo", set_log_mysql_info, NULL, RSRC_CONF, TAKE3, 695 {"MySQLLoginInfo", set_log_mysql_info, NULL, RSRC_CONF, TAKE3,
714 "The MySQL host, user-id and password for logging"} 696 "The MySQL host, user-id and password for logging"}
715 , 697 ,
716 {NULL} 698 {NULL}
717}; 699};
718 700
719 701
720int safe_mysql_query(request_rec *r, const char *query) 702
721{
722 int error = 1;
723 struct timespec delay, remainder;
724 int ret;
725 char *str;
726 void (*handler) (int);
727
728 /* A failed mysql_query() may send a SIGPIPE, so we ignore that signal momentarily. */
729 handler = signal(SIGPIPE, SIG_IGN);
730
731 /* If there's no DB link, or if we run the query and it gacks, try to be graceful */
732 if ( !mysql_log ||
733 (
734 (error = mysql_query(mysql_log, query)) &&
735 !strcasecmp(mysql_error(mysql_log), "MySQL server has gone away")
736 )
737 )
738
739 { /* We need to restart the server link */
740 mysql_log = NULL;
741 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"MySQL: connection lost, attempting reconnect");
742
743 open_log_dblink();
744
745 if (mysql_log == NULL) { /* still unable to link */
746 signal(SIGPIPE, handler);
747 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"MySQL: reconnect failed.");
748 return error;
749 }
750
751 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"MySQL: reconnect successful.");
752 error = mysql_query(mysql_log, query);
753 }
754
755 /* Restore SIGPIPE to its original handler function */
756 signal(SIGPIPE, handler);
757
758 if (error) {
759 /* Attempt a single re-try... First sleep for a tiny amount of time. */
760 delay.tv_sec = 0;
761 delay.tv_nsec = 500000000; /* max is 999999999 (nine nines) */
762 ret = nanosleep(&delay, &remainder);
763 if (ret && errno != EINTR)
764 perror("nanosleep");
765
766 /* Now re-attempt */
767 error = mysql_query(mysql_log,query);
768
769 if (error) {
770 str = pstrcat(r->pool, "MySQL query failed: ", query, NULL);
771 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,str);
772 str = pstrcat(r->pool, "MySQL failure reason: ", MYSQL_ERROR(mysql_log), NULL);
773 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,str);
774 } else {
775 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"MySQL: insert successful after a delayed retry.");
776 }
777 }
778 return error;
779}
780
781
782/* Routine to perform the actual construction and execution of the relevant 703/* Routine to perform the actual construction and execution of the relevant
783 * INSERT statements. 704 * INSERT statements.
784 */ 705 */
@@ -805,7 +726,7 @@ int log_mysql_transaction(request_rec *orig)
805 } 726 }
806 727
807 if (mysql_log == NULL) { /* mysql link not up, hopefully we can do something about it */ 728 if (mysql_log == NULL) { /* mysql link not up, hopefully we can do something about it */
808 open_log_dblink(); 729 open_logdb_link();
809 if (mysql_log == NULL) { 730 if (mysql_log == NULL) {
810 return OK; 731 return OK;
811 } 732 }
@@ -932,13 +853,20 @@ int log_mysql_transaction(request_rec *orig)
932} 853}
933 854
934 855
856/* Called on the exit of an httpd child process */
857static void log_mysql_child_exit(server_rec *s, pool *p)
858{
859 mysql_close(mysql_log);
860}
935 861
862
863/* The configuration array that sets up the hooks into the module. */
936module mysql_log_module = { 864module mysql_log_module = {
937 STANDARD_MODULE_STUFF, 865 STANDARD_MODULE_STUFF,
938 NULL, /* initializer */ 866 NULL, /* initializer */
939 NULL, /* create per-dir config */ 867 NULL, /* create per-dir config */
940 NULL, /* merge per-dir config */ 868 NULL, /* merge per-dir config */
941 make_log_mysql_state, /* server config */ 869 log_mysql_make_state, /* server config */
942 NULL, /* merge server config */ 870 NULL, /* merge server config */
943 log_mysql_cmds, /* command table */ 871 log_mysql_cmds, /* command table */
944 NULL, /* handlers */ 872 NULL, /* handlers */
@@ -949,5 +877,11 @@ module mysql_log_module = {
949 NULL, /* type_checker */ 877 NULL, /* type_checker */
950 NULL, /* fixups */ 878 NULL, /* fixups */
951 log_mysql_transaction, /* logger */ 879 log_mysql_transaction, /* logger */
952 NULL /* header parser */ 880 NULL, /* header parser */
881#if MODULE_MAGIC_NUMBER >= 19970728 /* 1.3-dev or later support these additionals... */
882 NULL, /* child_init */
883 log_mysql_child_exit, /* process exit/cleanup */
884 NULL /* [#0] post read-request */
885#endif
886
953}; 887};