Main Page | Modules | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages

awdb.h

Go to the documentation of this file.
00001 
00002 /*
00003 ** Copyright (C) 2003 Russell Leighton
00004 **
00005 ** This program is free software; you can redistribute it and/or modify
00006 ** it under the terms of the GNU General Public License as published by
00007 ** the Free Software Foundation; either version 2 of the License, or
00008 ** (at your option) any later version.
00009 **
00010 ** This program is distributed in the hope that it will be useful,
00011 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 ** GNU General Public License for more details.
00014 **
00015 ** You should have received a copy of the GNU General Public License
00016 ** along with this program; if not, write to the Free Software
00017 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00018 */
00019 
00020 
00021 #ifndef __AW_DB__
00022 #define __AW_DB__
00023 
00024 #include "monitor.h"
00025 
00026 #include "regexmatch.h"
00027 
00046 /*
00047 
00048 Changes:
00049 
00050 */
00051 
00055 typedef struct {
00056 
00057   aw_event_sig_t
00058    connect,                  /* could connect */
00059    noconnect,                /* could NOT connect */
00060    complete,                 /* sql completed successfully */
00061    time;                     /* sql completed successfully and this is how long it took */
00062 
00063 } aw_db_cevents_t;
00064 
00065 
00069 typedef struct {
00070 
00071   float64_t                  /* generate event if count of sql rows is  [min,max] */
00072    min,
00073    max;
00074 
00075   aw_event_sig_t
00076    cevent;                     
00077 
00078 } aw_db_counter_t;
00079 
00080 
00084 typedef struct {
00085 
00086   aw_event_sig_t
00087    match,                    /* regex matched */
00088    nomatch;                  /* regex did NOT match */
00089 
00090 } aw_db_revents_t;
00091 
00095 typedef struct {
00096 
00097   aw_db_revents_t
00098     revents;
00099 
00100   /* regex string */
00101   const byte_t
00102    *regex;
00103 
00104   /* holds substitution string, may be NULL */
00105   const byte_t
00106    *subst;
00107 
00108 } aw_db_regex_t;
00109 
00113 typedef struct {
00114 
00115   aw_db_revents_t
00116     revents;
00117 
00118   /* holds compiled regular expression  */
00119   regex_t
00120    pattern;
00121 
00122   /* holds substitution string, may be NULL */
00123   byte_t
00124    *subst;
00125 
00126 } aw_db_rwatcher_t;
00127 
00128 
00129 /* #################################### Functions ################################################# */
00130 
00131 
00141 void aw_db_handler_rmatch(aw_handler_args_t *args, 
00142                           aw_event_t *event, 
00143                           byte_t *row_as_string,
00144                           u_int32_t nwatchers, 
00145                           aw_db_rwatcher_t *watchers,
00146                           u_int32_t *match_markers);
00147 
00148 
00149 
00150 /* #################  Macros for generic code common to all supported databases #################### */
00151 
00152 
00153 #define AW_DB_DISCONNECT_POOL(CONN_TYPE)                                                                                    \
00154 do {                                                                                                                        \
00155  CONN_TYPE                                                                                                                  \
00156   *conn;                                                                                                                    \
00157  while( (conn = aw_llt_getobj(key, dbpool)) != NULL ) free_connection(conn);                                                \
00158 } while(0);
00159 
00160 #define MAX_CONNECTION_DELAY 60
00161 
00162 #define AW_DB_CONNECT(CONN_TYPE, PREFIX)                                                                                    \
00163 do {                                                                                                                        \
00164   /* capped exponential backoff in case of failed connections */                                                            \
00165   if (state->connection_attempts > 0) {                                                                                     \
00166     struct timespec                                                                                                         \
00167       sleep_interval ;                                                                                                      \
00168     u_int32_t                                                                                                               \
00169       shift = (state->connection_attempts<31)?state->connection_attempts:30; /* don't shift into sign bit! */               \
00170                                                                                                                             \
00171     sleep_interval.tv_sec = (1 << shift);                                                                                   \
00172     if (sleep_interval.tv_sec > MAX_CONNECTION_DELAY ||                                                                     \
00173         sleep_interval.tv_sec <= 0 /* in case you messed up the shift :) */ ) sleep_interval.tv_sec = MAX_CONNECTION_DELAY; \
00174                                                                                                                             \
00175     sleep_interval.tv_nsec = 0;                                                                                             \
00176                                                                                                                             \
00177     aw_nanosleep(&sleep_interval);                                                                                          \
00178                                                                                                                             \
00179   }/* end if */                                                                                                             \
00180                                                                                                                             \
00181   /* get the connection */                                                                                                  \
00182   {                                                                                                                         \
00183     CONN_TYPE                                                                                                               \
00184       *conn;                                                                                                                \
00185     byte_t                                                                                                                \
00186       key[128];                                                                                                             \
00187                                                                                                                             \
00188     /* in connection pool? */                                                                                               \
00189     make_connection_key(key, sizeof(key), cinfo);                                                                           \
00190     conn = aw_llt_getobj(key, dbpool);                                                                                      \
00191                                                                                                                             \
00192     if (conn == NULL) { /* must need a new a connection... */                                                               \
00193                                                                                                                             \
00194       conn = make_connection(cinfo,logger);                                                                         \
00195       if (conn == NULL) goto error;                                                                                         \
00196                                                                                                                             \
00197     } else { /* found connection in the pool */                                                                             \
00198                                                                                                                             \
00199       /* keep sure the connection still works */                                                                            \
00200       if ( ! isvalid_connection(conn) ) {                                                                                   \
00201                                                                                                                             \
00202         /* ... if not, cleanup and then try to make a new one */                                                            \
00203         free_connection(conn);                                                                                              \
00204         conn = make_connection(cinfo, logger);                                                                       \
00205         if (conn == NULL) goto error;                                                                                       \
00206                                                                                                                             \
00207       }/* end if */                                                                                                         \
00208                                                                                                                             \
00209     }/* end if */                                                                                                           \
00210                                                                                                                             \
00211     /* now connected  */                                                                                                    \
00212     state->connected = 1;                                                                                                   \
00213                                                                                                                             \
00214     state->conn = conn;                                                                                                     \
00215   }                                                                                                                         \
00216                                                                                                                             \
00217   /* success */                                                                                                             \
00218   state->connection_attempts = 0;                                                                                           \
00219                                                                                                                             \
00220   return;                                                                                                                   \
00221                                                                                                                             \
00222  error:; /* conn == NULL !!! */                                                                                             \
00223                                                                                                                             \
00224   aw_log(logger, AW_ERROR_LOG_LEVEL, "Failed to create " #PREFIX " connection");                                            \
00225                                                                                                                             \
00226   /* not connected  */                                                                                                      \
00227   state->connected = -1;                                                                                                    \
00228                                                                                                                             \
00229   state->conn = NULL;                                                                                                       \
00230                                                                                                                             \
00231   state->connection_attempts++;                                                                                             \
00232                                                                                                                             \
00233   /* disconnect all because likely we have connectivity issue */                                                            \
00234   aw_ ## PREFIX ## _disconnect_all (cinfo, state, logger);                                                                  \
00235 } while (0);
00236 
00237 
00238 #define AW_DB_DISCONNECT_ALL(PREFIX)                                                                                        \
00239 do {                                                                                                                        \
00240   byte_t                                                                                                                  \
00241     key[128];                                                                                                               \
00242                                                                                                                             \
00243   /* close this one */                                                                                                      \
00244   aw_ ## PREFIX ## _disconnect (cinfo, state, logger, 1);                                                                   \
00245                                                                                                                             \
00246   /* close the pool */                                                                                                      \
00247   make_connection_key(key, sizeof(key), cinfo);                                                                             \
00248                                                                                                                             \
00249   disconnect_all(key);                                                                                                      \
00250 } while(0); 
00251 
00252 #define AW_DB_DISCONNECT(PREFIX)                                                                                            \
00253 do {                                                                                                                        \
00254   if (state->conn != NULL) {                                                                                                \
00255     byte_t                                                                                                                \
00256       key[256];                                                                                                             \
00257                                                                                                                             \
00258     if (close) { /* usually means error */                                                                                  \
00259                                                                                                                             \
00260       free_connection(state->conn);                                                                                         \
00261                                                                                                                             \
00262     } else { /* cache */                                                                                                    \
00263       int32_t                                                                                                               \
00264         r = (rand()*100.0F)/RAND_MAX;                                                                                       \
00265                                                                                                                             \
00266       make_connection_key(key, sizeof(key), cinfo);                                                                         \
00267                                                                                                                             \
00268       /* 5% of the time we free a connection we will just close it,                                                         \
00269          and ALL others...this prevents accumulation of open                                                                \
00270          connections that were a result of a spike of contentious requests                                                  \
00271       */                                                                                                                    \
00272       if ( r < 5 ) {                                                                                                        \
00273                                                                                                                             \
00274         /* me */                                                                                                            \
00275         free_connection(state->conn);                                                                                       \
00276                                                                                                                             \
00277         /* all the rest like me */                                                                                          \
00278         disconnect_all(key);                                                                                                \
00279                                                                                                                             \
00280       } else { /* put live connection back in pool for re-use */                                                            \
00281                                                                                                                             \
00282         aw_llt_putobj(key, state->conn, dbpool);                                                                            \
00283                                                                                                                             \
00284       }/* end else */                                                                                                       \
00285                                                                                                                             \
00286     }/* end else */                                                                                                         \
00287                                                                                                                             \
00288     /* reset */                                                                                                             \
00289     state->conn = NULL;                                                                                                     \
00290                                                                                                                             \
00291   }/* end if */                                                                                                             \
00292                                                                                                                             \
00293   state->prev_connected = state->connected; /* remember */                                                                  \
00294                                                                                                                             \
00295   state->connected = -1; /* mark as down */                                                                                 \
00296 } while(0);
00297 
00298 
00299 #endif
Aware 0.11.1 Copyright (C) 1998-2005 Russell Leighton (russ@elegant-software.com)