summaryrefslogtreecommitdiffstats
path: root/mod_log_sql.c
diff options
context:
space:
mode:
Diffstat (limited to 'mod_log_sql.c')
-rw-r--r--mod_log_sql.c488
1 files changed, 119 insertions, 369 deletions
diff --git a/mod_log_sql.c b/mod_log_sql.c
index 564f3fc..50c7964 100644
--- a/mod_log_sql.c
+++ b/mod_log_sql.c
@@ -1,4 +1,4 @@
1/* $Header: /home/cvs/mod_log_sql/mod_log_sql.c,v 1.15 2004/02/12 03:18:18 urkle Exp $ */ 1/* $Id $ */
2/* --------* 2/* --------*
3 * DEFINES * 3 * DEFINES *
4 * --------*/ 4 * --------*/
@@ -6,15 +6,6 @@
6/* The enduser may wish to modify this */ 6/* The enduser may wish to modify this */
7#define DEBUG 7#define DEBUG
8 8
9/* The enduser won't modify these */
10#define MYSQL_ERROR(mysql) ((mysql)?(mysql_error(mysql)):"MySQL server has gone away")
11
12/* ---------*
13 * INCLUDES *
14 * ---------*/
15#include "mysql.h"
16#include "mysqld_error.h"
17
18#if defined(WITH_APACHE20) 9#if defined(WITH_APACHE20)
19# include "apache20.h" 10# include "apache20.h"
20#elif defined(WITH_APACHE13) 11#elif defined(WITH_APACHE13)
@@ -69,17 +60,9 @@ typedef struct {
69 int massvirtual; 60 int massvirtual;
70 int createtables; 61 int createtables;
71 int forcepreserve; 62 int forcepreserve;
72 char *tabletype;
73 char *dbname;
74 char *dbhost;
75 char *dbuser;
76 char *dbpwd;
77 char *machid; 63 char *machid;
78 char *socketfile; 64 apr_table_t *dbparams;
79 unsigned int tcpport; 65 logsql_dbconnection db;
80 int insertdelayed;
81 MYSQL server;
82 MYSQL *server_p;
83} global_config_t; 66} global_config_t;
84 67
85static global_config_t global_config; 68static global_config_t global_config;
@@ -87,11 +70,11 @@ static global_config_t global_config;
87/* structure to hold helper function info */ 70/* structure to hold helper function info */
88typedef struct { 71typedef struct {
89 char key; /* item letter character */ 72 char key; /* item letter character */
90 log_sql_item_func *func; /* its extraction function */ 73 logsql_item_func *func; /* its extraction function */
91 const char *sql_field_name; /* its column in SQL */ 74 const char *sql_field_name; /* its column in SQL */
92 int want_orig_default; /* if it requires the original request prior to internal redirection */ 75 int want_orig_default; /* if it requires the original request prior to internal redirection */
93 int string_contents; /* if it returns a string */ 76 int string_contents; /* if it returns a string */
94} log_sql_item; 77} logsql_item;
95 78
96/* But the contents of this structure will vary by virtual server. 79/* But the contents of this structure will vary by virtual server.
97 * This permits each virtual server to vary its configuration slightly 80 * This permits each virtual server to vary its configuration slightly
@@ -114,33 +97,28 @@ typedef struct {
114 const char *transfer_table_name; 97 const char *transfer_table_name;
115 const char *transfer_log_format; 98 const char *transfer_log_format;
116 apr_pool_t *parsed_pool; 99 apr_pool_t *parsed_pool;
117 log_sql_item **parsed_log_format; 100 logsql_item **parsed_log_format;
118 const char *preserve_file; 101 const char *preserve_file;
119 const char *cookie_name; 102 const char *cookie_name;
120} logsql_state; 103} logsql_state;
121 104
122 105
123/* -----------------* 106/* list of "handlers" for log types */
124 * HELPER FUNCTIONS * 107static apr_array_header_t *logsql_item_list;
125 * -----------------*/
126
127static int safe_create_tables(logsql_state *cls, request_rec *r);
128
129static apr_array_header_t *log_sql_item_list;
130 108
131/* Registration Function for extract functions * 109/* Registration Function for extract functions *
132 * and update parse cache for transfer_log_format * 110 * and update parse cache for transfer_log_format *
133 * this is exported from the module */ 111 * this is exported from the module */
134LOGSQL_DECLARE(void) log_sql_register_item(server_rec *s, apr_pool_t *p, 112LOGSQL_DECLARE(void) log_sql_register_item(server_rec *s, apr_pool_t *p,
135 char key, log_sql_item_func *func, const char *sql_field_name, 113 char key, logsql_item_func *func, const char *sql_field_name,
136 int want_orig_default, int string_contents) 114 int want_orig_default, int string_contents)
137{ 115{
138 server_rec *ts; 116 server_rec *ts;
139 log_sql_item *item; 117 logsql_item *item;
140 if (!log_sql_item_list) 118 if (!logsql_item_list)
141 log_sql_item_list = apr_array_make(p,10, sizeof(log_sql_item)); 119 logsql_item_list = apr_array_make(p,10, sizeof(logsql_item));
142 120
143 item= apr_array_push(log_sql_item_list); 121 item= apr_array_push(logsql_item_list);
144 item->key = key; 122 item->key = key;
145 item->func = func; 123 item->func = func;
146 item->sql_field_name = sql_field_name; 124 item->sql_field_name = sql_field_name;
@@ -189,7 +167,7 @@ static const char *escape_query(const char *from_str, apr_pool_t *p)
189 return from_str; 167 return from_str;
190 } 168 }
191 169
192 if (!global_config.server_p) { 170 if (!global_config.db.connected) {
193 /* Well, I would have liked to use the current database charset. mysql is 171 /* Well, I would have liked to use the current database charset. mysql is
194 * unavailable, however, so I fall back to the slightly less respectful 172 * unavailable, however, so I fall back to the slightly less respectful
195 * mysql_escape_string() function that uses the default charset. 173 * mysql_escape_string() function that uses the default charset.
@@ -199,7 +177,7 @@ static const char *escape_query(const char *from_str, apr_pool_t *p)
199 /* MySQL is available, so I'll go ahead and respect the current charset when 177 /* MySQL is available, so I'll go ahead and respect the current charset when
200 * I perform the escape. 178 * I perform the escape.
201 */ 179 */
202 retval = mysql_real_escape_string(global_config.server_p, to_str, from_str, length); 180 retval = mysql_real_escape_string(global_config.db.handle, to_str, from_str, length);
203 } 181 }
204 182
205 if (retval) 183 if (retval)
@@ -209,42 +187,19 @@ static const char *escape_query(const char *from_str, apr_pool_t *p)
209 } 187 }
210} 188}
211 189
212static int open_logdb_link(server_rec* s) 190static logsql_opendb open_logdb_link(server_rec* s)
213{ 191{
214 /* Returns:
215 3 if preserve forced
216 2 if already connected
217 1 if successful
218 0 if unsuccessful
219 */
220
221 if (global_config.forcepreserve) 192 if (global_config.forcepreserve)
222 return 3; 193 return LOGSQL_OPENDB_PRESERVE;
223 194
224 if (global_config.server_p) 195 if (global_config.db.connected)
225 return 2; 196 return LOGSQL_OPENDB_ALREADY;
226 197
227 if ((global_config.dbname) && (global_config.dbhost) && (global_config.dbuser) && (global_config.dbpwd)) { 198 if ((global_config.dbname) && (global_config.dbhost) && (global_config.dbuser) && (global_config.dbpwd)) {
228 mysql_init(&global_config.server); 199 log_sql_mysql_connect();
229 global_config.server_p = mysql_real_connect(&global_config.server, global_config.dbhost, global_config.dbuser, global_config.dbpwd, global_config.dbname, global_config.tcpport, global_config.socketfile, 0);
230
231 if (global_config.server_p) {
232 #ifdef DEBUG
233 log_error(APLOG_MARK,APLOG_DEBUG,s,"HOST: '%s' PORT: '%d' DB: '%s' USER: '%s' SOCKET: '%s'",
234 global_config.dbhost, global_config.tcpport, global_config.dbname, global_config.dbuser, global_config.socketfile);
235 #endif
236 return 1;
237 } else {
238 #ifdef DEBUG
239 log_error(APLOG_MARK,APLOG_DEBUG,s,"mod_log_sql: database connection error: %s",MYSQL_ERROR(&global_config.server));
240 log_error(APLOG_MARK,APLOG_DEBUG,s,"HOST: '%s' PORT: '%d' DB: '%s' USER: '%s' SOCKET: '%s'",
241 global_config.dbhost, global_config.tcpport, global_config.dbname, global_config.dbuser, global_config.socketfile);
242 #endif
243 return 0;
244 }
245 } else { 200 } else {
246 log_error(APLOG_MARK,APLOG_ERR,s,"mod_log_sql: insufficient configuration info to establish database link"); 201 log_error(APLOG_MARK,APLOG_ERR,s,"mod_log_sql: insufficient configuration info to establish database link");
247 return 0; 202 return LOGSQL_OPENDB_FAIL;
248 } 203 }
249} 204}
250 205
@@ -286,245 +241,6 @@ static void preserve_entry(request_rec *r, const char *query)
286} 241}
287 242
288 243
289/*-----------------------------------------------------*
290 * safe_sql_query: perform a database query with *
291 * a degree of safety and error checking. *
292 * *
293 * Parms: request record, SQL insert statement *
294 * Returns: 0 (OK) on success *
295 * 1 if have no log handle *
296 * 2 if insert delayed failed (kluge) *
297 * the actual MySQL return code on error *
298 *-----------------------------------------------------*/
299static unsigned int safe_sql_query(request_rec *r, const char *query)
300{
301 int retval;
302 struct timespec delay, remainder;
303 int ret;
304 void (*handler) (int);
305 logsql_state *cls;
306 unsigned int real_error = 0;
307 const char *real_error_str = NULL;
308
309 /* A failed mysql_query() may send a SIGPIPE, so we ignore that signal momentarily. */
310 handler = signal(SIGPIPE, SIG_IGN);
311
312 /* First attempt for the query */
313 if (!global_config.server_p) {
314 signal(SIGPIPE, handler);
315 return 1;
316 } else if (!(retval = mysql_query(global_config.server_p, query))) {
317 signal(SIGPIPE, handler);
318 return 0;
319 }
320
321 /* If we ran the query and it returned an error, try to be robust.
322 * (After all, the module thought it had a valid mysql_log connection but the query
323 * could have failed for a number of reasons, so we have to be extra-safe and check.) */
324 if (global_config.insertdelayed) {
325 real_error_str = MYSQL_ERROR(global_config.server_p);
326 } else {
327 real_error = mysql_errno(global_config.server_p);
328 }
329
330 /* Check to see if the error is "nonexistent table" */
331 if (global_config.insertdelayed) {
332 retval = (strstr(real_error_str, "Table")) && (strstr(real_error_str,"doesn't exist"));
333 } else {
334 retval = (real_error == ER_NO_SUCH_TABLE);
335 }
336 if (retval) {
337 if (global_config.createtables) {
338 log_error(APLOG_MARK,APLOG_ERR,r->server,"mod_log_sql: table doesn't exist...creating now");
339 cls = ap_get_module_config(r->server->module_config, &log_sql_module);
340 if (safe_create_tables(cls, r)) {
341 log_error(APLOG_MARK,APLOG_ERR,r->server,"mod_log_sql: child attempted but failed to create one or more tables for %s, preserving query", ap_get_server_name(r));
342 preserve_entry(r, query);
343 retval = mysql_errno(global_config.server_p);
344 } else {
345 log_error(APLOG_MARK,APLOG_ERR,r->server,"mod_log_sql: tables successfully created - retrying query");
346 if (mysql_query(global_config.server_p, query)) {
347 log_error(APLOG_MARK,APLOG_ERR,r->server,"mod_log_sql: giving up, preserving query");
348 preserve_entry(r, query);
349 retval = mysql_errno(global_config.server_p);
350 } else
351 log_error(APLOG_MARK,APLOG_ERR,r->server,"mod_log_sql: query successful after table creation");
352 retval = 0;
353 }
354 } else {
355 log_error(APLOG_MARK,APLOG_ERR,r->server,"mod_log_sql, table doesn't exist, creation denied by configuration, preserving query");
356 preserve_entry(r, query);
357 retval = ER_NO_SUCH_TABLE;
358 }
359 /* Restore SIGPIPE to its original handler function */
360 signal(SIGPIPE, handler);
361 return retval;
362 }
363
364 /* Handle all other types of errors */
365
366 cls = ap_get_module_config(r->server->module_config, &log_sql_module);
367
368 /* Something went wrong, so start by trying to restart the db link. */
369 if (global_config.insertdelayed) {
370 real_error = 2;
371 } else {
372 real_error = mysql_errno(global_config.server_p);
373 }
374
375 log_error(APLOG_MARK,APLOG_ERR,r->server,"mod_log_sql: first attempt failed, API said: error %d, \"%s\"", real_error, MYSQL_ERROR(global_config.server_p));
376 mysql_close(global_config.server_p);
377 global_config.server_p = NULL;
378 open_logdb_link(r->server);
379
380 if (global_config.server_p == NULL) { /* still unable to link */
381 signal(SIGPIPE, handler);
382 log_error(APLOG_MARK,APLOG_ERR,r->server,"mod_log_sql: reconnect failed, unable to reach database. SQL logging stopped until child regains a db connection.");
383 log_error(APLOG_MARK,APLOG_ERR,r->server,"mod_log_sql: log entries are being preserved in %s", cls->preserve_file);
384 return 1;
385 } else
386 log_error(APLOG_MARK,APLOG_ERR,r->server,"mod_log_sql: db reconnect successful");
387
388 /* First sleep for a tiny amount of time. */
389 delay.tv_sec = 0;
390 delay.tv_nsec = 250000000; /* max is 999999999 (nine nines) */
391 ret = nanosleep(&delay, &remainder);
392 if (ret && errno != EINTR)
393 log_error(APLOG_MARK,APLOG_ERR,r->server,"mod_log_sql: nanosleep unsuccessful");
394
395 /* Then make our second attempt */
396 retval = mysql_query(global_config.server_p,query);
397
398 /* If this one also failed, log that and append to our local offline file */
399 if (retval) {
400 if (global_config.insertdelayed) {
401 real_error = 2;
402 } else {
403 real_error = mysql_errno(global_config.server_p);
404 }
405
406 log_error(APLOG_MARK,APLOG_ERR,r->server,"mod_log_sql: second attempt failed, API said: error %d, \"%s\" -- preserving", real_error, MYSQL_ERROR(global_config.server_p));
407 preserve_entry(r, query);
408 retval = real_error;
409 } else
410 log_error(APLOG_MARK,APLOG_ERR,r->server,"mod_log_sql: second attempt successful");
411
412 /* Restore SIGPIPE to its original handler function */
413 signal(SIGPIPE, handler);
414 return retval;
415}
416
417/*-----------------------------------------------------*
418 * safe_create_tables: create SQL table set for the *
419 * virtual server represented by cls. *
420 * *
421 * Parms: virtserver structure, request record *
422 * Returns: 0 on no errors *
423 * mysql error code on failure *
424 *-----------------------------------------------------*/
425static int safe_create_tables(logsql_state *cls, request_rec *r)
426{
427 int retval;
428 unsigned int create_results;
429 char *create_access = NULL;
430 char *create_notes = NULL;
431 char *create_hout = NULL;
432 char *create_hin = NULL;
433 char *create_cookies = NULL;
434
435 char *type_suffix = NULL;
436
437 char *createprefix = "create table if not exists `";
438 char *access_suffix =
439 "` (id char(19),\
440 agent varchar(255),\
441 bytes_sent int unsigned,\
442 child_pid smallint unsigned,\
443 cookie varchar(255),\
444 machine_id varchar(25),\
445 request_file varchar(255),\
446 referer varchar(255),\
447 remote_host varchar(50),\
448 remote_logname varchar(50),\
449 remote_user varchar(50),\
450 request_duration smallint unsigned,\
451 request_line varchar(255),\
452 request_method varchar(10),\
453 request_protocol varchar(10),\
454 request_time char(28),\
455 request_uri varchar(255),\
456 request_args varchar(255),\
457 server_port smallint unsigned,\
458 ssl_cipher varchar(25),\
459 ssl_keysize smallint unsigned,\
460 ssl_maxkeysize smallint unsigned,\
461 status smallint unsigned,\
462 time_stamp int unsigned,\
463 virtual_host varchar(255))";
464
465 char *notes_suffix =
466 "` (id char(19),\
467 item varchar(80),\
468 val varchar(80))";
469
470 char *headers_suffix =
471 "` (id char(19),\
472 item varchar(80),\
473 val varchar(80))";
474
475 char *cookies_suffix =
476 "` (id char(19),\
477 item varchar(80),\
478 val varchar(80))";
479 if (global_config.tabletype) {
480 type_suffix = apr_pstrcat(r->pool, " TYPE=", global_config.tabletype, NULL);
481 }
482 /* Find memory long enough to hold the whole CREATE string + \0 */
483 create_access = apr_pstrcat(r->pool, createprefix, cls->transfer_table_name, access_suffix, type_suffix, NULL);
484 create_notes = apr_pstrcat(r->pool, createprefix, cls->notes_table_name, notes_suffix, type_suffix, NULL);
485 create_hout = apr_pstrcat(r->pool, createprefix, cls->hout_table_name, headers_suffix, type_suffix, NULL);
486 create_hin = apr_pstrcat(r->pool, createprefix, cls->hin_table_name, headers_suffix, type_suffix, NULL);
487 create_cookies= apr_pstrcat(r->pool, createprefix, cls->cookie_table_name, cookies_suffix, type_suffix, NULL);
488
489 #ifdef DEBUG
490 log_error(APLOG_MARK,APLOG_DEBUG,r->server,"mod_log_sql: create string: %s", create_access);
491 log_error(APLOG_MARK,APLOG_DEBUG,r->server,"mod_log_sql: create string: %s", create_notes);
492 log_error(APLOG_MARK,APLOG_DEBUG,r->server,"mod_log_sql: create string: %s", create_hout);
493 log_error(APLOG_MARK,APLOG_DEBUG,r->server,"mod_log_sql: create string: %s", create_hin);
494 log_error(APLOG_MARK,APLOG_DEBUG,r->server,"mod_log_sql: create string: %s", create_cookies);
495 #endif
496
497 /* Assume that things worked unless told otherwise */
498 retval = 0;
499
500 if ((create_results = safe_sql_query(r, create_access))) {
501 log_error(APLOG_MARK,APLOG_ERR,r->server,"mod_log_sql: failed to create access table");
502 retval = create_results;
503 }
504
505 if ((create_results = safe_sql_query(r, create_notes))) {
506 log_error(APLOG_MARK,APLOG_ERR,r->server,"mod_log_sql: failed to create notes table");
507 retval = create_results;
508 }
509
510 if ((create_results = safe_sql_query(r, create_hin))) {
511 log_error(APLOG_MARK,APLOG_ERR,r->server,"mod_log_sql: failed to create header_in table");
512 retval = create_results;
513 }
514
515 if ((create_results = safe_sql_query(r, create_hout))) {
516 log_error(APLOG_MARK,APLOG_ERR,r->server,"mod_log_sql: failed to create header_out table");
517 retval = create_results;
518 }
519
520 if ((create_results = safe_sql_query(r, create_cookies))) {
521 log_error(APLOG_MARK,APLOG_ERR,r->server,"mod_log_sql: failed to create cookies table");
522 retval = create_results;
523 }
524
525 return retval;
526}
527
528/* ------------------------------------------------* 244/* ------------------------------------------------*
529 * Command handlers that are called according * 245 * Command handlers that are called according *
530 * to the directives found at Apache runtime. * 246 * to the directives found at Apache runtime. *
@@ -567,7 +283,6 @@ static const char *set_global_string_slot(cmd_parms *cmd,
567 *(const char **)((char *)ptr + offset) = apr_pstrdup(cmd->pool,arg); 283 *(const char **)((char *)ptr + offset) = apr_pstrdup(cmd->pool,arg);
568 return NULL; 284 return NULL;
569} 285}
570
571static const char *set_server_string_slot(cmd_parms *cmd, 286static const char *set_server_string_slot(cmd_parms *cmd,
572 void *struct_ptr, 287 void *struct_ptr,
573 const char *arg) 288 const char *arg)
@@ -591,7 +306,7 @@ static const char *set_logformat_slot(cmd_parms *cmd,
591 cfg->transfer_log_format = arg; 306 cfg->transfer_log_format = arg;
592/* apr_pool_clear(cfg->parsed_pool);*/ 307/* apr_pool_clear(cfg->parsed_pool);*/
593 cfg->parsed_log_format = apr_pcalloc(cfg->parsed_pool, 308 cfg->parsed_log_format = apr_pcalloc(cfg->parsed_pool,
594 strlen(arg) * sizeof(log_sql_item *)); 309 strlen(arg) * sizeof(logsql_item *));
595 return NULL; 310 return NULL;
596} 311}
597 312
@@ -607,16 +322,38 @@ static const char *set_server_nmv_string_slot(cmd_parms *parms,
607 return set_server_string_slot(parms,struct_ptr,arg); 322 return set_server_string_slot(parms,struct_ptr,arg);
608} 323}
609 324
610static const char *set_log_sql_info(cmd_parms *cmd, void *dummy, const char *host, const char *user, const char *pwd) 325/* Set a DB connection parameter */
326static void set_dbparam(apr_pool_t *p, const char *key,
327 const char *val);
328{
329 if (!global_config.dbparams) {
330 global_config.dbparams = apr_table_make(p,5);
331 }
332 apr_table_set(global_config.dbparams,key,val);
333}
334
335static const char *set_dbparam_slot(cmd_params *cmd,
336 void *struct_ptr,
337 const char *arg)
338{
339 const char *param = (char *)cmd->info;
340 set_dbparam(cmd->pool,param,arg);
341 return NULL;
342}
343
344/* Sets basic connection info */
345static const char *set_log_sql_info(cmd_parms *cmd, void *dummy,
346 const char *host, const char *user, const char *pwd)
611{ 347{
612 if (*host != '.') { 348 if (*host != '.') {
613 global_config.dbhost = apr_pstrdup(cmd->pool,host); 349 set_db_param_slot(cmd->pool, "host", host);
614 } 350 }
615 if (*user != '.') { 351 if (*user != '.') {
352 set_db_param_slot(cmd->pool, "user", user);
616 global_config.dbuser = apr_pstrdup(cmd->pool,user); 353 global_config.dbuser = apr_pstrdup(cmd->pool,user);
617 } 354 }
618 if (*pwd != '.') { 355 if (*pwd != '.') {
619 global_config.dbpwd = apr_pstrdup(cmd->pool,pwd); 356 set_db_param_slot(cmd->pool, "passwd", pwd);
620 } 357 }
621 return NULL; 358 return NULL;
622} 359}
@@ -673,37 +410,26 @@ static int log_sql_open(apr_pool_t *pc, apr_pool_t *p, apr_pool_t *pt, server_re
673static void log_sql_child_init(server_rec *s, apr_pool_t *p) 410static void log_sql_child_init(server_rec *s, apr_pool_t *p)
674#endif 411#endif
675{ 412{
676 int retval; 413 logsql_opendb retval;
677 /* Open a link to the database */ 414 /* Open a link to the database */
678 retval = open_logdb_link(s); 415 retval = open_logdb_link(s);
679 if (!retval) 416 switch (retval) {
417 case LOGSQL_OPENDB_FAIL:
680 log_error(APLOG_MARK,APLOG_ERR,s,"mod_log_sql: child spawned but unable to open database link"); 418 log_error(APLOG_MARK,APLOG_ERR,s,"mod_log_sql: child spawned but unable to open database link");
681 419 break;
682 #ifdef DEBUG 420 case LOGSQL_OPENDB_SUCCESS:
683 if ( (retval == 1) || (retval == 2) ) 421 case LOGSQL_OPENDB_ALREADY:
684 log_error(APLOG_MARK,APLOG_DEBUG,s,"mod_log_sql: open_logdb_link successful"); 422 log_error(APLOG_MARK,APLOG_DEBUG,s,"mod_log_sql: open_logdb_link successful");
685 if (retval == 3) 423 break;
424 case LOGSQL_OPENDB_PRESERVE:
686 log_error(APLOG_MARK,APLOG_DEBUG,s,"mod_log_sql: open_logdb_link said that preservation is forced"); 425 log_error(APLOG_MARK,APLOG_DEBUG,s,"mod_log_sql: open_logdb_link said that preservation is forced");
687 #endif 426 break;
427 }
688#if defined(WITH_APACHE20) 428#if defined(WITH_APACHE20)
689 return OK; 429 return OK;
690#endif 430#endif
691} 431}
692/*
693void *log_sql_initializer(server_rec *main_server, apr_pool_t *p)
694{
695 server_rec *s;
696
697 logsql_state main_conf = ap_get_module_config(main_server->module_config, &log_sql_module);
698 432
699 for (server_rec *s = main_server; s; s = s->next) {
700 conf = ap_get_module_config(s->module_config, &log_sql_module);
701 if (conf->transfer_log_format == NULL && s != main_server) {
702 *conf = *main_conf;
703 }
704
705}
706 */
707/* post_config / module_init */ 433/* post_config / module_init */
708#if defined(WITH_APACHE20) 434#if defined(WITH_APACHE20)
709static int log_sql_post_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s) 435static int log_sql_post_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
@@ -748,6 +474,20 @@ static void log_sql_module_init(server_rec *s, apr_pool_t *p)
748#endif 474#endif
749} 475}
750 476
477/* This function handles calling the DB module, handling errors
478 * of missing tables and lost DB connections, and falling back to
479 * preserving the DB query.
480 *
481 * Parms: request record, table type, table name, and the full SQL command
482 */
483
484static void safe_sql_insert(request_rec *r, logsql_tabletype table_type,
485 const char *table_name, const char *sql) {
486 int result;
487 if (!global_config.connected) {
488 }
489}
490
751/* This function gets called to create a per-server configuration 491/* This function gets called to create a per-server configuration
752 * record. It will always be called for the main server and 492 * record. It will always be called for the main server and
753 * for each virtual server that is established. Each server maintains 493 * for each virtual server that is established. Each server maintains
@@ -764,7 +504,7 @@ static void *log_sql_make_state(apr_pool_t *p, server_rec *s)
764 cls->transfer_log_format = DEFAULT_TRANSFER_LOG_FMT; 504 cls->transfer_log_format = DEFAULT_TRANSFER_LOG_FMT;
765 apr_pool_create(&cls->parsed_pool, p); 505 apr_pool_create(&cls->parsed_pool, p);
766 cls->parsed_log_format = apr_pcalloc(cls->parsed_pool, 506 cls->parsed_log_format = apr_pcalloc(cls->parsed_pool,
767 strlen(cls->transfer_log_format) * sizeof(log_sql_item *)); 507 strlen(cls->transfer_log_format) * sizeof(logsql_item *));
768 cls->notes_table_name = DEFAULT_NOTES_TABLE_NAME; 508 cls->notes_table_name = DEFAULT_NOTES_TABLE_NAME;
769 cls->hin_table_name = DEFAULT_HIN_TABLE_NAME; 509 cls->hin_table_name = DEFAULT_HIN_TABLE_NAME;
770 cls->hout_table_name = DEFAULT_HOUT_TABLE_NAME; 510 cls->hout_table_name = DEFAULT_HOUT_TABLE_NAME;
@@ -801,7 +541,7 @@ static void *log_sql_merge_state(apr_pool_t *p, void *basev, void *addv)
801 child->transfer_log_format = parent->transfer_log_format; 541 child->transfer_log_format = parent->transfer_log_format;
802 /*apr_pool_clear(child->parsed_pool);*/ 542 /*apr_pool_clear(child->parsed_pool);*/
803 child->parsed_log_format = apr_pcalloc(child->parsed_pool, 543 child->parsed_log_format = apr_pcalloc(child->parsed_pool,
804 strlen(child->transfer_log_format) * sizeof(log_sql_item *)); 544 strlen(child->transfer_log_format) * sizeof(logsql_item *));
805 } 545 }
806 546
807 if (child->preserve_file == DEFAULT_PRESERVE_FILE) 547 if (child->preserve_file == DEFAULT_PRESERVE_FILE)
@@ -961,7 +701,7 @@ static int log_sql_transaction(request_rec *orig)
961 * what the user has configured. */ 701 * what the user has configured. */
962 length = strlen(cls->transfer_log_format); 702 length = strlen(cls->transfer_log_format);
963 for (i = 0; i<length; i++) { 703 for (i = 0; i<length; i++) {
964 log_sql_item *item = cls->parsed_log_format[i]; 704 logsql_item *item = cls->parsed_log_format[i];
965 if (item==NULL) { 705 if (item==NULL) {
966 log_error(APLOG_MARK, APLOG_ERR, orig->server, 706 log_error(APLOG_MARK, APLOG_ERR, orig->server,
967 "Log Format '%c' unknown",cls->transfer_log_format[i]); 707 "Log Format '%c' unknown",cls->transfer_log_format[i]);
@@ -1175,7 +915,11 @@ static int log_sql_transaction(request_rec *orig)
1175 /* ---> i.e. we have a good MySQL connection. <--- */ 915 /* ---> i.e. we have a good MySQL connection. <--- */
1176 916
1177 /* Make the access-table insert */ 917 /* Make the access-table insert */
1178 safe_sql_query(orig, access_query); 918 if (safe_create_tables(orig, LOGSQL_TABLE_ACCESS, transfer_tablename)==APR_SUCCESS) {
919 safe_sql_query(orig, access_query);
920 } else {
921 preserve_entry(orig, access_query);
922 }
1179 923
1180 /* Log the optional notes, headers, etc. */ 924 /* Log the optional notes, headers, etc. */
1181 if (note_query) 925 if (note_query)
@@ -1199,6 +943,7 @@ static int log_sql_transaction(request_rec *orig)
1199 * Structure: command, function called, NULL, where available, how many arguments, verbose description 943 * Structure: command, function called, NULL, where available, how many arguments, verbose description
1200 */ 944 */
1201static const command_rec log_sql_cmds[] = { 945static const command_rec log_sql_cmds[] = {
946 /* Table names */
1202 AP_INIT_TAKE1("LogSQLTransferLogTable", set_server_nmv_string_slot, 947 AP_INIT_TAKE1("LogSQLTransferLogTable", set_server_nmv_string_slot,
1203 (void *)APR_OFFSETOF(logsql_state, transfer_table_name), RSRC_CONF, 948 (void *)APR_OFFSETOF(logsql_state, transfer_table_name), RSRC_CONF,
1204 "The database table that holds the transfer log") 949 "The database table that holds the transfer log")
@@ -1219,14 +964,21 @@ static const command_rec log_sql_cmds[] = {
1219 (void *)APR_OFFSETOF(logsql_state, cookie_table_name), RSRC_CONF, 964 (void *)APR_OFFSETOF(logsql_state, cookie_table_name), RSRC_CONF,
1220 "The database table that holds the cookie info") 965 "The database table that holds the cookie info")
1221 , 966 ,
967 AP_INIT_FLAG("LogSQLMassVirtualHosting", set_global_flag_slot,
968 (void *)APR_OFFSETOF(global_config_t, massvirtual), RSRC_CONF,
969 "Activates option(s) useful for ISPs performing mass virutal hosting")
970 ,
971 /* Log format */
1222 AP_INIT_TAKE1("LogSQLTransferLogFormat", set_logformat_slot, 972 AP_INIT_TAKE1("LogSQLTransferLogFormat", set_logformat_slot,
1223 NULL, RSRC_CONF, 973 NULL, RSRC_CONF,
1224 "Instruct the module what information to log to the database transfer log") 974 "Instruct the module what information to log to the database transfer log")
1225 , 975 ,
976 /* Machine ID */
1226 AP_INIT_TAKE1("LogSQLMachineID", set_global_string_slot, 977 AP_INIT_TAKE1("LogSQLMachineID", set_global_string_slot,
1227 (void *)APR_OFFSETOF(global_config_t, machid), RSRC_CONF, 978 (void *)APR_OFFSETOF(global_config_t, machid), RSRC_CONF,
1228 "Machine ID that the module will log, useful in web clusters to differentiate machines") 979 "Machine ID that the module will log, useful in web clusters to differentiate machines")
1229 , 980 ,
981 /* Limits on logging */
1230 AP_INIT_ITERATE("LogSQLRequestAccept", add_server_string_slot, 982 AP_INIT_ITERATE("LogSQLRequestAccept", add_server_string_slot,
1231 (void *)APR_OFFSETOF(logsql_state, transfer_accept_list), RSRC_CONF, 983 (void *)APR_OFFSETOF(logsql_state, transfer_accept_list), RSRC_CONF,
1232 "List of URIs to accept for logging. Accesses that don't match will not be logged") 984 "List of URIs to accept for logging. Accesses that don't match will not be logged")
@@ -1239,48 +991,14 @@ static const command_rec log_sql_cmds[] = {
1239 (void *)APR_OFFSETOF(logsql_state, remhost_ignore_list), RSRC_CONF, 991 (void *)APR_OFFSETOF(logsql_state, remhost_ignore_list), RSRC_CONF,
1240 "List of remote hosts to ignore. Accesses that match will not be logged to database") 992 "List of remote hosts to ignore. Accesses that match will not be logged to database")
1241 , 993 ,
1242 AP_INIT_TAKE1("LogSQLDatabase", set_global_string_slot,
1243 (void *)APR_OFFSETOF(global_config_t, dbname), RSRC_CONF,
1244 "The name of the database database for logging")
1245 ,
1246 AP_INIT_TAKE1("LogSQLWhichCookie", set_server_string_slot, 994 AP_INIT_TAKE1("LogSQLWhichCookie", set_server_string_slot,
1247 (void *)APR_OFFSETOF(logsql_state, cookie_name), RSRC_CONF, 995 (void *)APR_OFFSETOF(logsql_state, cookie_name), RSRC_CONF,
1248 "The single cookie that you want logged in the access_log when using the 'c' config directive") 996 "The single cookie that you want logged in the access_log when using the 'c' config directive")
1249 , 997 ,
1250 AP_INIT_TAKE3("LogSQLLoginInfo", set_log_sql_info, NULL, RSRC_CONF,
1251 "The database host, user-id and password for logging")
1252 ,
1253 AP_INIT_FLAG("LogSQLCreateTables", set_global_nmv_flag_slot,
1254 (void *)APR_OFFSETOF(global_config_t, createtables), RSRC_CONF,
1255 "Turn on module's capability to create its SQL tables on the fly")
1256 ,
1257 AP_INIT_FLAG("LogSQLMassVirtualHosting", set_global_flag_slot,
1258 (void *)APR_OFFSETOF(global_config_t, massvirtual), RSRC_CONF,
1259 "Activates option(s) useful for ISPs performing mass virutal hosting")
1260 ,
1261 AP_INIT_FLAG("LogSQLDelayedInserts", set_global_flag_slot,
1262 (void *)APR_OFFSETOF(global_config_t, insertdelayed), RSRC_CONF,
1263 "Whether to use delayed inserts")
1264 ,
1265 AP_INIT_FLAG("LogSQLForcePreserve", set_global_flag_slot,
1266 (void *)APR_OFFSETOF(global_config_t, forcepreserve), RSRC_CONF,
1267 "Forces logging to preserve file and bypasses database")
1268 ,
1269 AP_INIT_TAKE1("LogSQLPreserveFile", set_server_string_slot, 998 AP_INIT_TAKE1("LogSQLPreserveFile", set_server_string_slot,
1270 (void *)APR_OFFSETOF(logsql_state,preserve_file), RSRC_CONF, 999 (void *)APR_OFFSETOF(logsql_state,preserve_file), RSRC_CONF,
1271 "Name of the file to use for data preservation during database downtime") 1000 "Name of the file to use for data preservation during database downtime")
1272 , 1001 ,
1273 AP_INIT_TAKE1("LogSQLSocketFile", set_global_string_slot,
1274 (void *)APR_OFFSETOF(global_config_t, socketfile), RSRC_CONF,
1275 "Name of the file to employ for socket connections to database")
1276 ,
1277 AP_INIT_TAKE1("LogSQLTableType", set_global_string_slot,
1278 (void *)APR_OFFSETOF(global_config_t, tabletype), RSRC_CONF,
1279 "What kind of table to create (MyISAM, InnoDB,...) when creating tables")
1280 ,
1281 AP_INIT_TAKE1("LogSQLTCPPort", set_log_sql_tcp_port, NULL, RSRC_CONF,
1282 "Port number to use for TCP connections to database, defaults to 3306 if not set")
1283 ,
1284 AP_INIT_ITERATE("LogSQLWhichNotes", add_server_string_slot, 1002 AP_INIT_ITERATE("LogSQLWhichNotes", add_server_string_slot,
1285 (void *)APR_OFFSETOF(logsql_state, notes_list), RSRC_CONF, 1003 (void *)APR_OFFSETOF(logsql_state, notes_list), RSRC_CONF,
1286 "Notes that you would like to log in a separate table") 1004 "Notes that you would like to log in a separate table")
@@ -1297,6 +1015,38 @@ static const command_rec log_sql_cmds[] = {
1297 (void *)APR_OFFSETOF(logsql_state, cookie_list), RSRC_CONF, 1015 (void *)APR_OFFSETOF(logsql_state, cookie_list), RSRC_CONF,
1298 "The cookie(s) that you would like to log in a separate table") 1016 "The cookie(s) that you would like to log in a separate table")
1299 , 1017 ,
1018 /* DB connection parameters */
1019 AP_INIT_FLAG("LogSQLForcePreserve", set_global_flag_slot,
1020 (void *)APR_OFFSETOF(global_config_t, forcepreserve), RSRC_CONF,
1021 "Forces logging to preserve file and bypasses database")
1022 ,
1023 AP_INIT_FLAG("LogSQLCreateTables", set_global_nmv_flag_slot,
1024 (void *)APR_OFFSETOF(global_config_t, createtables), RSRC_CONF,
1025 "Turn on module's capability to create its SQL tables on the fly")
1026 ,
1027 AP_INIT_TAKE3("LogSQLLoginInfo", set_log_sql_info, NULL, RSRC_CONF,
1028 "The database host, user-id and password for logging")
1029 ,
1030 AP_INIT_TAKE1("LogSQLDatabase", set_dbparam_slot,
1031 (void *)"database", RSRC_CONF,
1032 "The name of the database database for logging")
1033 ,
1034 AP_INIT_TAKE1("LogSQLDelayedInserts", set_dbparam_slot,
1035 (void *)"insertdelayed", RSRC_CONF,
1036 "Whether to use delayed inserts")
1037 ,
1038 AP_INIT_TAKE1("LogSQLTableType", set_dbparam_slot,
1039 (void *)"tabletype", RSRC_CONF,
1040 "What kind of table to create (MyISAM, InnoDB,...) when creating tables")
1041 ,
1042 AP_INIT_TAKE1("LogSQLSocketFile", set_dbparam_slot,
1043 (void *)"socketfile", RSRC_CONF,
1044 "Name of the file to employ for socket connections to database")
1045 ,
1046 AP_INIT_TAKE1("LogSQLTCPPort", set_dbparam_slot,
1047 (void *)"tcpport", RSRC_CONF,
1048 "Port number to use for TCP connections to database, defaults to 3306 if not set")
1049 ,
1300 {NULL} 1050 {NULL}
1301}; 1051};
1302/* The configuration array that sets up the hooks into the module. */ 1052/* The configuration array that sets up the hooks into the module. */