diff options
Diffstat (limited to 'mod_log_sql.c')
| -rw-r--r-- | mod_log_sql.c | 324 |
1 files changed, 205 insertions, 119 deletions
diff --git a/mod_log_sql.c b/mod_log_sql.c index 3fc7ace..117111b 100644 --- a/mod_log_sql.c +++ b/mod_log_sql.c | |||
| @@ -1,11 +1,11 @@ | |||
| 1 | /* $Id: mod_log_sql.c,v 1.19 2002/11/27 07:13:58 helios Exp $ */ | 1 | /* $Id: mod_log_sql.c,v 1.20 2002/12/10 19:43:21 helios Exp $ */ |
| 2 | 2 | ||
| 3 | /* --------* | 3 | /* --------* |
| 4 | * DEFINES * | 4 | * DEFINES * |
| 5 | * --------*/ | 5 | * --------*/ |
| 6 | 6 | ||
| 7 | /* The enduser may wish to modify this */ | 7 | /* The enduser may wish to modify this */ |
| 8 | #define DEBUG | 8 | #undef DEBUG |
| 9 | 9 | ||
| 10 | /* The enduser won't modify these */ | 10 | /* The enduser won't modify these */ |
| 11 | #define MYSQL_ERROR(mysql) ((mysql)?(mysql_error(mysql)):"MySQL server has gone away") | 11 | #define MYSQL_ERROR(mysql) ((mysql)?(mysql_error(mysql)):"MySQL server has gone away") |
| @@ -20,11 +20,13 @@ | |||
| 20 | #include <time.h> | 20 | #include <time.h> |
| 21 | #include <stdio.h> | 21 | #include <stdio.h> |
| 22 | #include <stdlib.h> | 22 | #include <stdlib.h> |
| 23 | #include <string.h> | ||
| 23 | #include "httpd.h" | 24 | #include "httpd.h" |
| 24 | #include "http_config.h" | 25 | #include "http_config.h" |
| 25 | #include "http_log.h" | 26 | #include "http_log.h" |
| 26 | #include "http_core.h" | 27 | #include "http_core.h" |
| 27 | #include "mysql.h" | 28 | #include "mysql.h" |
| 29 | #include "mysqld_error.h" | ||
| 28 | 30 | ||
| 29 | #if MODULE_MAGIC_NUMBER >= 19980324 /* M_M_N is defined in /usr/local/Apache/include/ap_mmn.h, 19990320 as of this writing. */ | 31 | #if MODULE_MAGIC_NUMBER >= 19980324 /* M_M_N is defined in /usr/local/Apache/include/ap_mmn.h, 19990320 as of this writing. */ |
| 30 | #include "ap_compat.h" | 32 | #include "ap_compat.h" |
| @@ -73,8 +75,8 @@ typedef const char *(*item_key_func) (request_rec *, char *); | |||
| 73 | * Each child process has its own segregated copy of this structure. | 75 | * Each child process has its own segregated copy of this structure. |
| 74 | */ | 76 | */ |
| 75 | typedef struct { | 77 | typedef struct { |
| 76 | int table_made; | ||
| 77 | array_header *transfer_ignore_list; | 78 | array_header *transfer_ignore_list; |
| 79 | array_header *transfer_accept_list; | ||
| 78 | array_header *remhost_ignore_list; | 80 | array_header *remhost_ignore_list; |
| 79 | array_header *notes_list; | 81 | array_header *notes_list; |
| 80 | array_header *hout_list; | 82 | array_header *hout_list; |
| @@ -94,6 +96,9 @@ typedef struct { | |||
| 94 | /* -----------------* | 96 | /* -----------------* |
| 95 | * HELPER FUNCTIONS * | 97 | * HELPER FUNCTIONS * |
| 96 | * -----------------*/ | 98 | * -----------------*/ |
| 99 | |||
| 100 | int safe_create_tables(log_sql_state *cls, request_rec *r); | ||
| 101 | |||
| 97 | static char *format_integer(pool *p, int i) | 102 | static char *format_integer(pool *p, int i) |
| 98 | { | 103 | { |
| 99 | char dummy[40]; | 104 | char dummy[40]; |
| @@ -484,7 +489,7 @@ static const char *extract_request_timestamp(request_rec *r, char *a) | |||
| 484 | { | 489 | { |
| 485 | char tstr[32]; | 490 | char tstr[32]; |
| 486 | 491 | ||
| 487 | snprintf(tstr, 32, "%ld", time(NULL)); | 492 | ap_snprintf(tstr, 32, "%ld", time(NULL)); |
| 488 | return pstrdup(r->pool, tstr); | 493 | return pstrdup(r->pool, tstr); |
| 489 | } | 494 | } |
| 490 | 495 | ||
| @@ -665,73 +670,123 @@ void preserve_entry(request_rec *r, const char *query) | |||
| 665 | /* Parms: request record, SQL insert statement */ | 670 | /* Parms: request record, SQL insert statement */ |
| 666 | /* Returns: 0 (OK) on success */ | 671 | /* Returns: 0 (OK) on success */ |
| 667 | /* 1 if have no log handle */ | 672 | /* 1 if have no log handle */ |
| 668 | /* actual MySQL return code on error */ | 673 | /* 2 if insert delayed failed (kluge) */ |
| 674 | /* the actual MySQL return code on error */ | ||
| 669 | /*-----------------------------------------------------*/ | 675 | /*-----------------------------------------------------*/ |
| 670 | unsigned int safe_mysql_query(request_rec *r, const char *query) | 676 | unsigned int safe_mysql_query(request_rec *r, const char *query) |
| 671 | { | 677 | { |
| 672 | unsigned int retval; | 678 | int retval; |
| 673 | unsigned int real_error; | ||
| 674 | struct timespec delay, remainder; | 679 | struct timespec delay, remainder; |
| 675 | int ret; | 680 | int ret; |
| 676 | void (*handler) (int); | 681 | void (*handler) (int); |
| 677 | 682 | log_sql_state *cls; | |
| 683 | unsigned int real_error; | ||
| 684 | #ifdef WANT_DELAYED_MYSQL_INSERT | ||
| 685 | char *real_error_str; | ||
| 686 | #endif | ||
| 678 | 687 | ||
| 679 | /* A failed mysql_query() may send a SIGPIPE, so we ignore that signal momentarily. */ | 688 | /* A failed mysql_query() may send a SIGPIPE, so we ignore that signal momentarily. */ |
| 680 | handler = signal(SIGPIPE, SIG_IGN); | 689 | handler = signal(SIGPIPE, SIG_IGN); |
| 681 | 690 | ||
| 682 | /* First attempt for the query */ | 691 | /* First attempt for the query */ |
| 683 | if (mysql_log != NULL) | 692 | if (!mysql_log) { |
| 684 | retval = mysql_query(mysql_log, query); | 693 | signal(SIGPIPE, handler); |
| 685 | else | 694 | return 1; |
| 686 | return 1; | 695 | } else if (!(retval = mysql_query(mysql_log, query))) { |
| 696 | signal(SIGPIPE, handler); | ||
| 697 | return 0; | ||
| 698 | } | ||
| 687 | 699 | ||
| 688 | if ( retval != 0 ) | 700 | /* If we ran the query and it returned an error, try to be robust. |
| 689 | { | 701 | * (After all, the module thought it had a valid mysql_log connection but the query |
| 690 | /* If we ran the query and it returned an error, try to be robust. | 702 | * could have failed for a number of reasons, so we have to be extra-safe and check.) */ |
| 691 | * (After all, the module thought it had a valid mysql_log connection but the query | 703 | #ifdef WANT_DELAYED_MYSQL_INSERT |
| 692 | * could have failed for a number of reasons, so we have to be extra-safe and check.) */ | 704 | real_error_str = MYSQL_ERROR(mysql_log); |
| 693 | 705 | #else | |
| 694 | log_sql_state *cls = get_module_config(r->server->module_config, &sql_log_module); | 706 | real_error = mysql_errno(mysql_log); |
| 695 | 707 | #endif | |
| 696 | real_error = mysql_errno(mysql_log); /* What really happened? */ | 708 | |
| 697 | 709 | /* Check to see if the error is "nonexistent table" */ | |
| 698 | /* Something went wrong, so start by trying to restart the db link. */ | 710 | #ifdef WANT_DELAYED_MYSQL_INSERT |
| 699 | ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"mod_log_sql: first attempt failed, API said: error %d, %s", real_error, MYSQL_ERROR(mysql_log)); | 711 | if ((strstr(real_error_str, "Table")) && (strstr(real_error_str,"doesn't exist"))) { |
| 700 | mysql_close(mysql_log); | 712 | #else |
| 701 | mysql_log = NULL; | 713 | if (real_error == ER_NO_SUCH_TABLE) { |
| 702 | open_logdb_link(r->server); | 714 | #endif |
| 703 | 715 | if (create_tables) { | |
| 704 | if (mysql_log == NULL) { /* still unable to link */ | 716 | ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"mod_log_sql: table doesn't exist...creating now"); |
| 705 | signal(SIGPIPE, handler); | 717 | cls = get_module_config(r->server->module_config, &sql_log_module); |
| 706 | ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"mod_log_sql: reconnect failed, unable to reach database. SQL logging stopped until child regains a db connection."); | 718 | if (safe_create_tables(cls, r)) { |
| 707 | ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"mod_log_sql: log entries are being preserved in %s", cls->preserve_file); | 719 | ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"mod_log_sql: child attempted but failed to create one or more tables for %s, preserving query", ap_get_server_name(r)); |
| 708 | return 1; | 720 | preserve_entry(r, query); |
| 709 | } else | 721 | retval = mysql_errno(mysql_log); |
| 710 | ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"mod_log_sql: reconnect successful"); | 722 | } else { |
| 711 | 723 | ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"mod_log_sql: tables successfully created - retrying query"); | |
| 712 | /* First sleep for a tiny amount of time. */ | 724 | if (mysql_query(mysql_log, query)) { |
| 713 | delay.tv_sec = 0; | 725 | ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"mod_log_sql: giving up, preserving query"); |
| 714 | delay.tv_nsec = 250000000; /* max is 999999999 (nine nines) */ | 726 | preserve_entry(r, query); |
| 715 | ret = nanosleep(&delay, &remainder); | 727 | retval = mysql_errno(mysql_log); |
| 716 | if (ret && errno != EINTR) | 728 | } else |
| 717 | ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"mod_log_sql: nanosleep unsuccessful"); | 729 | ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"mod_log_sql: query successful after table creation"); |
| 718 | 730 | retval = 0; | |
| 719 | /* Then make our second attempt */ | 731 | } |
| 720 | retval = mysql_query(mysql_log,query); | 732 | } else { |
| 721 | 733 | ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"mod_log_sql, table doesn't exist, creation denied by configuration, preserving query"); | |
| 722 | /* If this one also failed, log that and append to our local offline file */ | 734 | preserve_entry(r, query); |
| 723 | if ( retval != 0 ) | 735 | retval = ER_NO_SUCH_TABLE; |
| 724 | { | 736 | } |
| 725 | real_error = mysql_errno(mysql_log); | 737 | /* Restore SIGPIPE to its original handler function */ |
| 726 | ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"mod_log_sql: second attempt failed, API said: error %d, %s", real_error, MYSQL_ERROR(mysql_log)); | 738 | signal(SIGPIPE, handler); |
| 727 | retval = real_error; | 739 | return retval; |
| 728 | } else | ||
| 729 | ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"mod_log_sql: second attempt successful"); | ||
| 730 | } | 740 | } |
| 731 | 741 | ||
| 742 | /* Handle all other types of errors */ | ||
| 743 | |||
| 744 | cls = get_module_config(r->server->module_config, &sql_log_module); | ||
| 745 | |||
| 746 | /* Something went wrong, so start by trying to restart the db link. */ | ||
| 747 | #ifdef WANT_DELAYED_MYSQL_INSERT | ||
| 748 | real_error = 2; | ||
| 749 | #else | ||
| 750 | real_error = mysql_errno(mysql_log); | ||
| 751 | #endif | ||
| 752 | ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"mod_log_sql: first attempt failed, API said: error %d, \"%s\"", real_error, MYSQL_ERROR(mysql_log)); | ||
| 753 | mysql_close(mysql_log); | ||
| 754 | mysql_log = NULL; | ||
| 755 | open_logdb_link(r->server); | ||
| 756 | |||
| 757 | if (mysql_log == NULL) { /* still unable to link */ | ||
| 758 | signal(SIGPIPE, handler); | ||
| 759 | ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"mod_log_sql: reconnect failed, unable to reach database. SQL logging stopped until child regains a db connection."); | ||
| 760 | ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"mod_log_sql: log entries are being preserved in %s", cls->preserve_file); | ||
| 761 | return 1; | ||
| 762 | } else | ||
| 763 | ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"mod_log_sql: db reconnect successful"); | ||
| 764 | |||
| 765 | /* First sleep for a tiny amount of time. */ | ||
| 766 | delay.tv_sec = 0; | ||
| 767 | delay.tv_nsec = 250000000; /* max is 999999999 (nine nines) */ | ||
| 768 | ret = nanosleep(&delay, &remainder); | ||
| 769 | if (ret && errno != EINTR) | ||
| 770 | ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"mod_log_sql: nanosleep unsuccessful"); | ||
| 771 | |||
| 772 | /* Then make our second attempt */ | ||
| 773 | retval = mysql_query(mysql_log,query); | ||
| 774 | |||
| 775 | /* If this one also failed, log that and append to our local offline file */ | ||
| 776 | if (retval) { | ||
| 777 | #ifdef WANT_DELAYED_MYSQL_INSERT | ||
| 778 | real_error = 2; | ||
| 779 | #else | ||
| 780 | real_error = mysql_errno(mysql_log); | ||
| 781 | #endif | ||
| 782 | ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"mod_log_sql: second attempt failed, API said: error %d, \"%s\" -- preserving", real_error, MYSQL_ERROR(mysql_log)); | ||
| 783 | preserve_entry(r, query); | ||
| 784 | retval = real_error; | ||
| 785 | } else | ||
| 786 | ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"mod_log_sql: second attempt successful"); | ||
| 787 | |||
| 732 | /* Restore SIGPIPE to its original handler function */ | 788 | /* Restore SIGPIPE to its original handler function */ |
| 733 | signal(SIGPIPE, handler); | 789 | signal(SIGPIPE, handler); |
| 734 | |||
| 735 | return retval; | 790 | return retval; |
| 736 | } | 791 | } |
| 737 | 792 | ||
| @@ -811,35 +866,29 @@ int safe_create_tables(log_sql_state *cls, request_rec *r) | |||
| 811 | #endif | 866 | #endif |
| 812 | 867 | ||
| 813 | /* Assume that things worked unless told otherwise */ | 868 | /* Assume that things worked unless told otherwise */ |
| 814 | cls->table_made = 1; | ||
| 815 | retval = 0; | 869 | retval = 0; |
| 816 | 870 | ||
| 817 | if ((create_results = safe_mysql_query(r, create_access)) != 0) { | 871 | if ((create_results = safe_mysql_query(r, create_access))) { |
| 818 | cls->table_made = 0; | ||
| 819 | ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"mod_log_sql: failed to create access table"); | 872 | ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"mod_log_sql: failed to create access table"); |
| 820 | retval = create_results; | 873 | retval = create_results; |
| 821 | } | 874 | } |
| 822 | 875 | ||
| 823 | if ((create_results = safe_mysql_query(r, create_notes)) != 0) { | 876 | if ((create_results = safe_mysql_query(r, create_notes))) { |
| 824 | cls->table_made = 0; | ||
| 825 | ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"mod_log_sql: failed to create notes table"); | 877 | ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"mod_log_sql: failed to create notes table"); |
| 826 | retval = create_results; | 878 | retval = create_results; |
| 827 | } | 879 | } |
| 828 | 880 | ||
| 829 | if ((create_results = safe_mysql_query(r, create_hin)) != 0) { | 881 | if ((create_results = safe_mysql_query(r, create_hin))) { |
| 830 | cls->table_made = 0; | ||
| 831 | ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"mod_log_sql: failed to create header_out table"); | 882 | ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"mod_log_sql: failed to create header_out table"); |
| 832 | retval = create_results; | 883 | retval = create_results; |
| 833 | } | 884 | } |
| 834 | 885 | ||
| 835 | if ((create_results = safe_mysql_query(r, create_hout)) != 0) { | 886 | if ((create_results = safe_mysql_query(r, create_hout))) { |
| 836 | cls->table_made = 0; | ||
| 837 | ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"mod_log_sql: failed to create header_in table"); | 887 | ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"mod_log_sql: failed to create header_in table"); |
| 838 | retval = create_results; | 888 | retval = create_results; |
| 839 | } | 889 | } |
| 840 | 890 | ||
| 841 | if ((create_results = safe_mysql_query(r, create_cookies)) != 0) { | 891 | if ((create_results = safe_mysql_query(r, create_cookies))) { |
| 842 | cls->table_made = 0; | ||
| 843 | ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"mod_log_sql: failed to create cookies table"); | 892 | ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"mod_log_sql: failed to create cookies table"); |
| 844 | retval = create_results; | 893 | retval = create_results; |
| 845 | } | 894 | } |
| @@ -872,8 +921,8 @@ const char *set_log_sql_machine_id(cmd_parms *parms, void *dummy, char *arg) | |||
| 872 | 921 | ||
| 873 | const char *set_log_sql_create(cmd_parms *parms, void *dummy, int flag) | 922 | const char *set_log_sql_create(cmd_parms *parms, void *dummy, int flag) |
| 874 | { | 923 | { |
| 875 | if (massvirtual != 0) | 924 | if (massvirtual) |
| 876 | ap_log_error(APLOG_MARK,WARNINGLEVEL,parms->server,"mod_log_sql: do not set LogSQLCreateTables when LogSQLMassVirtualHosting is On. Ignoring."); | 925 | ap_log_error(APLOG_MARK,WARNINGLEVEL,parms->server,"mod_log_sql: do not set LogSQLCreateTables when LogSQLMassVirtualHosting is On. Ignoring."); |
| 877 | else | 926 | else |
| 878 | create_tables = ( flag ? 1 : 0); | 927 | create_tables = ( flag ? 1 : 0); |
| 879 | return NULL; | 928 | return NULL; |
| @@ -994,6 +1043,16 @@ const char *set_log_sql_tcp_port(cmd_parms *parms, void *dummy, char *arg) | |||
| 994 | return NULL; | 1043 | return NULL; |
| 995 | } | 1044 | } |
| 996 | 1045 | ||
| 1046 | const char *add_log_sql_transfer_accept(cmd_parms *parms, void *dummy, char *arg) | ||
| 1047 | { | ||
| 1048 | char **addme; | ||
| 1049 | log_sql_state *cls = get_module_config(parms->server->module_config, &sql_log_module); | ||
| 1050 | |||
| 1051 | addme = push_array(cls->transfer_accept_list); | ||
| 1052 | *addme = pstrdup(cls->transfer_accept_list->pool, arg); | ||
| 1053 | return NULL; | ||
| 1054 | } | ||
| 1055 | |||
| 997 | const char *add_log_sql_transfer_ignore(cmd_parms *parms, void *dummy, char *arg) | 1056 | const char *add_log_sql_transfer_ignore(cmd_parms *parms, void *dummy, char *arg) |
| 998 | { | 1057 | { |
| 999 | char **addme; | 1058 | char **addme; |
| @@ -1072,8 +1131,9 @@ const char *add_log_sql_cookie(cmd_parms *parms, void *dummy, char *arg) | |||
| 1072 | */ | 1131 | */ |
| 1073 | static void log_sql_child_init(server_rec *s, pool *p) | 1132 | static void log_sql_child_init(server_rec *s, pool *p) |
| 1074 | { | 1133 | { |
| 1075 | int retval; | 1134 | int retval; |
| 1076 | 1135 | ||
| 1136 | /* Open a link to the database */ | ||
| 1077 | retval = open_logdb_link(s); | 1137 | retval = open_logdb_link(s); |
| 1078 | if (retval == 0) | 1138 | if (retval == 0) |
| 1079 | ap_log_error(APLOG_MARK,ERRLEVEL,s,"mod_log_sql: child spawned but unable to open database link"); | 1139 | ap_log_error(APLOG_MARK,ERRLEVEL,s,"mod_log_sql: child spawned but unable to open database link"); |
| @@ -1140,12 +1200,12 @@ void *log_sql_make_state(pool *p, server_rec *s) | |||
| 1140 | cls->preserve_file = "/tmp/sql-preserve"; | 1200 | cls->preserve_file = "/tmp/sql-preserve"; |
| 1141 | 1201 | ||
| 1142 | cls->transfer_ignore_list = make_array(p, 1, sizeof(char *)); | 1202 | cls->transfer_ignore_list = make_array(p, 1, sizeof(char *)); |
| 1203 | cls->transfer_accept_list = make_array(p, 1, sizeof(char *)); | ||
| 1143 | cls->remhost_ignore_list = make_array(p, 1, sizeof(char *)); | 1204 | cls->remhost_ignore_list = make_array(p, 1, sizeof(char *)); |
| 1144 | cls->notes_list = make_array(p, 1, sizeof(char *)); | 1205 | cls->notes_list = make_array(p, 1, sizeof(char *)); |
| 1145 | cls->hin_list = make_array(p, 1, sizeof(char *)); | 1206 | cls->hin_list = make_array(p, 1, sizeof(char *)); |
| 1146 | cls->hout_list = make_array(p, 1, sizeof(char *)); | 1207 | cls->hout_list = make_array(p, 1, sizeof(char *)); |
| 1147 | cls->cookie_list = make_array(p, 1, sizeof(char *)); | 1208 | cls->cookie_list = make_array(p, 1, sizeof(char *)); |
| 1148 | cls->table_made = 0; | ||
| 1149 | cls->cookie_name = NULL; | 1209 | cls->cookie_name = NULL; |
| 1150 | 1210 | ||
| 1151 | return (void *) cls; | 1211 | return (void *) cls; |
| @@ -1177,6 +1237,9 @@ command_rec log_sql_cmds[] = { | |||
| 1177 | {"LogSQLMachineID", set_log_sql_machine_id, NULL, RSRC_CONF, TAKE1, | 1237 | {"LogSQLMachineID", set_log_sql_machine_id, NULL, RSRC_CONF, TAKE1, |
| 1178 | "Machine ID that the module will log, useful in web clusters to differentiate machines"} | 1238 | "Machine ID that the module will log, useful in web clusters to differentiate machines"} |
| 1179 | , | 1239 | , |
| 1240 | {"LogSQLRequestAccept", add_log_sql_transfer_accept, NULL, RSRC_CONF, ITERATE, | ||
| 1241 | "List of URIs to accept for logging. Accesses that don't match will not be logged"} | ||
| 1242 | , | ||
| 1180 | {"LogSQLRequestIgnore", add_log_sql_transfer_ignore, NULL, RSRC_CONF, ITERATE, | 1243 | {"LogSQLRequestIgnore", add_log_sql_transfer_ignore, NULL, RSRC_CONF, ITERATE, |
| 1181 | "List of URIs to ignore. Accesses that match will not be logged to database"} | 1244 | "List of URIs to ignore. Accesses that match will not be logged to database"} |
| 1182 | , | 1245 | , |
| @@ -1240,18 +1303,18 @@ int log_sql_transaction(request_rec *orig) | |||
| 1240 | /* We handle mass virtual hosting differently. Dynamically determine the name | 1303 | /* We handle mass virtual hosting differently. Dynamically determine the name |
| 1241 | * of the table from the virtual server's name, and flag it for creation. | 1304 | * of the table from the virtual server's name, and flag it for creation. |
| 1242 | */ | 1305 | */ |
| 1243 | if ( massvirtual == 1 ) { | 1306 | if (massvirtual) { |
| 1244 | char *access_base = "access_"; | 1307 | char *access_base = "access_"; |
| 1245 | char *notes_base = "notes_"; | 1308 | char *notes_base = "notes_"; |
| 1246 | char *hout_base = "headout_"; | 1309 | char *hout_base = "headout_"; |
| 1247 | char *hin_base = "headin_"; | 1310 | char *hin_base = "headin_"; |
| 1248 | char *cookie_base = "cookies_"; | 1311 | char *cookie_base = "cookies_"; |
| 1249 | char *a_tablename; | 1312 | char *a_tablename; |
| 1250 | char *n_tablename; | 1313 | char *n_tablename; |
| 1251 | char *i_tablename; | 1314 | char *i_tablename; |
| 1252 | char *o_tablename; | 1315 | char *o_tablename; |
| 1253 | char *c_tablename; | 1316 | char *c_tablename; |
| 1254 | int i; | 1317 | unsigned int i; |
| 1255 | 1318 | ||
| 1256 | /* Find memory long enough to hold the table name + \0. */ | 1319 | /* Find memory long enough to hold the table name + \0. */ |
| 1257 | a_tablename = ap_pstrcat(orig->pool, access_base, ap_get_server_name(orig), NULL); | 1320 | a_tablename = ap_pstrcat(orig->pool, access_base, ap_get_server_name(orig), NULL); |
| @@ -1308,7 +1371,7 @@ int log_sql_transaction(request_rec *orig) | |||
| 1308 | const char *unique_id; | 1371 | const char *unique_id; |
| 1309 | const char *formatted_item; | 1372 | const char *formatted_item; |
| 1310 | int i, j, length; | 1373 | int i, j, length; |
| 1311 | int result; | 1374 | int proceed; |
| 1312 | 1375 | ||
| 1313 | for (r = orig; r->next; r = r->next) { | 1376 | for (r = orig; r->next; r = r->next) { |
| 1314 | continue; | 1377 | continue; |
| @@ -1317,16 +1380,29 @@ int log_sql_transaction(request_rec *orig) | |||
| 1317 | /* The following is a stolen upsetting mess of pointers, I'm sorry. | 1380 | /* The following is a stolen upsetting mess of pointers, I'm sorry. |
| 1318 | * Anyone with the motiviation and/or the time should feel free | 1381 | * Anyone with the motiviation and/or the time should feel free |
| 1319 | * to make this cleaner. :) */ | 1382 | * to make this cleaner. :) */ |
| 1320 | ptrptr2 = (char **) (cls->transfer_ignore_list->elts + (cls->transfer_ignore_list->nelts * cls->transfer_ignore_list->elt_size)); | 1383 | ptrptr2 = (char **) (cls->transfer_accept_list->elts + (cls->transfer_accept_list->nelts * cls->transfer_accept_list->elt_size)); |
| 1384 | |||
| 1385 | /* Go through each element of the accept list and compare it to the | ||
| 1386 | * request_uri. If we don't get a match, return without logging */ | ||
| 1387 | if ((r->uri) && (cls->transfer_accept_list->nelts)) { | ||
| 1388 | proceed = 0; | ||
| 1389 | for (ptrptr = (char **) cls->transfer_accept_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->transfer_accept_list->elt_size)) | ||
| 1390 | if (strstr(r->uri, *ptrptr)) { | ||
| 1391 | proceed = 1; | ||
| 1392 | break; | ||
| 1393 | } | ||
| 1394 | if (!proceed) | ||
| 1395 | return OK; | ||
| 1396 | } | ||
| 1321 | 1397 | ||
| 1322 | /* Go through each element of the ignore list and compare it to the | 1398 | /* Go through each element of the ignore list and compare it to the |
| 1323 | * request_uri. If we get a match, return without logging */ | 1399 | * request_uri. If we get a match, return without logging */ |
| 1400 | ptrptr2 = (char **) (cls->transfer_ignore_list->elts + (cls->transfer_ignore_list->nelts * cls->transfer_ignore_list->elt_size)); | ||
| 1324 | if (r->uri) { | 1401 | if (r->uri) { |
| 1325 | for (ptrptr = (char **) cls->transfer_ignore_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->transfer_ignore_list->elt_size)) { | 1402 | for (ptrptr = (char **) cls->transfer_ignore_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->transfer_ignore_list->elt_size)) |
| 1326 | if (strstr(r->uri, *ptrptr)) { | 1403 | if (strstr(r->uri, *ptrptr)) { |
| 1327 | return OK; | 1404 | return OK; |
| 1328 | } | 1405 | } |
| 1329 | } | ||
| 1330 | } | 1406 | } |
| 1331 | 1407 | ||
| 1332 | /* Go through each element of the ignore list and compare it to the | 1408 | /* Go through each element of the ignore list and compare it to the |
| @@ -1334,11 +1410,10 @@ int log_sql_transaction(request_rec *orig) | |||
| 1334 | ptrptr2 = (char **) (cls->remhost_ignore_list->elts + (cls->remhost_ignore_list->nelts * cls->remhost_ignore_list->elt_size)); | 1410 | ptrptr2 = (char **) (cls->remhost_ignore_list->elts + (cls->remhost_ignore_list->nelts * cls->remhost_ignore_list->elt_size)); |
| 1335 | thehost = get_remote_host(r->connection, r->per_dir_config, REMOTE_NAME); | 1411 | thehost = get_remote_host(r->connection, r->per_dir_config, REMOTE_NAME); |
| 1336 | if (thehost) { | 1412 | if (thehost) { |
| 1337 | for (ptrptr = (char **) cls->remhost_ignore_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->remhost_ignore_list->elt_size)) { | 1413 | for (ptrptr = (char **) cls->remhost_ignore_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->remhost_ignore_list->elt_size)) |
| 1338 | if (strstr(thehost, *ptrptr)) { | 1414 | if (strstr(thehost, *ptrptr)) { |
| 1339 | return OK; | 1415 | return OK; |
| 1340 | } | 1416 | } |
| 1341 | } | ||
| 1342 | } | 1417 | } |
| 1343 | 1418 | ||
| 1344 | length = strlen(cls->transfer_log_format); | 1419 | length = strlen(cls->transfer_log_format); |
| @@ -1530,7 +1605,7 @@ int log_sql_transaction(request_rec *orig) | |||
| 1530 | if (mysql_log == NULL) { | 1605 | if (mysql_log == NULL) { |
| 1531 | /* Unable to re-establish a DB link, so assume that it's really | 1606 | /* Unable to re-establish a DB link, so assume that it's really |
| 1532 | * gone and send the entry to the preserve file instead. | 1607 | * gone and send the entry to the preserve file instead. |
| 1533 | * This short-circuits safe_mysql_query during a db outage and therefore | 1608 | * This short-circuits safe_mysql_query() during a db outage and therefore |
| 1534 | * we don't keep logging the db error over and over. | 1609 | * we don't keep logging the db error over and over. |
| 1535 | */ | 1610 | */ |
| 1536 | preserve_entry(orig, access_query); | 1611 | preserve_entry(orig, access_query); |
| @@ -1554,52 +1629,20 @@ int log_sql_transaction(request_rec *orig) | |||
| 1554 | /* ---> So as of here we have a non-null value of mysql_log. <--- */ | 1629 | /* ---> So as of here we have a non-null value of mysql_log. <--- */ |
| 1555 | /* ---> i.e. we have a good MySQL connection. <--- */ | 1630 | /* ---> i.e. we have a good MySQL connection. <--- */ |
| 1556 | 1631 | ||
| 1557 | |||
| 1558 | /* Make the tables if we're supposed to. */ | ||
| 1559 | if ((cls->table_made != 1) && (create_tables != 0)) { | ||
| 1560 | result = safe_create_tables(cls, orig); | ||
| 1561 | if (result != 0) | ||
| 1562 | ap_log_error(APLOG_MARK,ERRLEVEL,orig->server,"mod_log_sql: child attempted but failed to create one or more tables for %s", ap_get_server_name(orig)); | ||
| 1563 | else | ||
| 1564 | ap_log_error(APLOG_MARK,NOTICELEVEL,orig->server,"mod_log_sql: no problems creating tables for %s", ap_get_server_name(orig)); | ||
| 1565 | } | ||
| 1566 | |||
| 1567 | /* Make the access-table insert */ | 1632 | /* Make the access-table insert */ |
| 1568 | result = safe_mysql_query(orig, access_query); | 1633 | safe_mysql_query(orig, access_query); |
| 1569 | |||
| 1570 | /* It failed, but NOT because table didn't exist */ | ||
| 1571 | if ( (result != 0) && (result != 1146) ) | ||
| 1572 | preserve_entry(orig,access_query); | ||
| 1573 | |||
| 1574 | /* It failed because table didn't exist */ | ||
| 1575 | if (result == 1146) { | ||
| 1576 | ap_log_error(APLOG_MARK,ERRLEVEL,orig->server,"mod_log_sql: hmm, table didn't yet exist; creating"); | ||
| 1577 | result = safe_create_tables(cls, orig); | ||
| 1578 | if (result != 0) { | ||
| 1579 | ap_log_error(APLOG_MARK,ERRLEVEL,orig->server,"mod_log_sql: child attempted but failed to create one or more tables for %s, preserving query", ap_get_server_name(orig)); | ||
| 1580 | preserve_entry(orig,access_query); | ||
| 1581 | } else { | ||
| 1582 | ap_log_error(APLOG_MARK,ERRLEVEL,orig->server,"mod_log_sql: table successfully created, query will now be retried"); | ||
| 1583 | result = safe_mysql_query(orig, access_query); | ||
| 1584 | if (result != 0 ) { | ||
| 1585 | ap_log_error(APLOG_MARK,ERRLEVEL,orig->server,"mod_log_sql: giving up, preserving query"); | ||
| 1586 | preserve_entry(orig,access_query); | ||
| 1587 | return OK; | ||
| 1588 | } | ||
| 1589 | } | ||
| 1590 | } | ||
| 1591 | 1634 | ||
| 1592 | /* Log the optional notes, headers, etc. */ | 1635 | /* Log the optional notes, headers, etc. */ |
| 1593 | if ( note_query != NULL ) | 1636 | if (note_query) |
| 1594 | safe_mysql_query(orig, note_query); | 1637 | safe_mysql_query(orig, note_query); |
| 1595 | 1638 | ||
| 1596 | if ( hout_query != NULL ) | 1639 | if (hout_query) |
| 1597 | safe_mysql_query(orig, hout_query); | 1640 | safe_mysql_query(orig, hout_query); |
| 1598 | 1641 | ||
| 1599 | if ( hin_query != NULL ) | 1642 | if (hin_query) |
| 1600 | safe_mysql_query(orig, hin_query); | 1643 | safe_mysql_query(orig, hin_query); |
| 1601 | 1644 | ||
| 1602 | if ( cookie_query != NULL ) | 1645 | if (cookie_query) |
| 1603 | safe_mysql_query(orig, cookie_query); | 1646 | safe_mysql_query(orig, cookie_query); |
| 1604 | 1647 | ||
| 1605 | return OK; | 1648 | return OK; |
| @@ -1634,3 +1677,46 @@ module sql_log_module = { | |||
| 1634 | #endif | 1677 | #endif |
| 1635 | 1678 | ||
| 1636 | }; | 1679 | }; |
| 1680 | |||
| 1681 | |||
| 1682 | |||
| 1683 | /* Make the tables if we're supposed to. */ | ||
| 1684 | /* | ||
| 1685 | if ((cls->table_made != 1) && (create_tables != 0)) { | ||
| 1686 | result = safe_create_tables(cls, orig); | ||
| 1687 | if (result != 0) | ||
| 1688 | ap_log_error(APLOG_MARK,ERRLEVEL,orig->server,"mod_log_sql: child attempted but failed to create one or more tables for %s", ap_get_server_name(orig)); | ||
| 1689 | else | ||
| 1690 | ap_log_error(APLOG_MARK,NOTICELEVEL,orig->server,"mod_log_sql: no problems creating tables for %s", ap_get_server_name(orig)); | ||
| 1691 | } | ||
| 1692 | */ | ||
| 1693 | |||
| 1694 | /* It failed, but NOT because table didn't exist */ | ||
| 1695 | /* | ||
| 1696 | if ( (result) && (result != ER_NO_SUCH_TABLE) ) | ||
| 1697 | preserve_entry(orig,access_query); | ||
| 1698 | */ | ||
| 1699 | |||
| 1700 | /* It failed because table didn't exist */ | ||
| 1701 | /* | ||
| 1702 | if (result == ER_NO_SUCH_TABLE) | ||
| 1703 | if (create_tables) { | ||
| 1704 | ap_log_error(APLOG_MARK,ERRLEVEL,orig->server,"mod_log_sql: access table doesn't exist...creating now"); | ||
| 1705 | if ((result = safe_create_tables(cls, orig))) { | ||
| 1706 | ap_log_error(APLOG_MARK,ERRLEVEL,orig->server,"mod_log_sql: child attempted but failed to create one or more tables for %s, preserving query", ap_get_server_name(orig)); | ||
| 1707 | preserve_entry(orig,access_query); | ||
| 1708 | } else { | ||
| 1709 | ap_log_error(APLOG_MARK,ERRLEVEL,orig->server,"mod_log_sql: table(s) successfully created - retrying insert"); | ||
| 1710 | if ((result = safe_mysql_query(orig, access_query))) { | ||
| 1711 | ap_log_error(APLOG_MARK,ERRLEVEL,orig->server,"mod_log_sql: giving up, preserving query"); | ||
| 1712 | preserve_entry(orig,access_query); | ||
| 1713 | return OK; | ||
| 1714 | } else | ||
| 1715 | ap_log_error(APLOG_MARK_ERRLEVEL,orig->server,"mod_log_sql: insert successful after table creation"); | ||
| 1716 | } | ||
| 1717 | } else { | ||
| 1718 | ap_log_error(APLOG_MARK,ERRLEVEL,orig->server,"mod_log_sql: access table doesn't exist...not allowed to create, giving up, preserving query"); | ||
| 1719 | preserve_entry(orig,access_query); | ||
| 1720 | return OK; | ||
| 1721 | } | ||
| 1722 | */ | ||
