cel_pgsql.c File Reference

PostgreSQL CEL logger. More...

#include "asterisk.h"
#include <libpq-fe.h>
#include "asterisk/config.h"
#include "asterisk/options.h"
#include "asterisk/channel.h"
#include "asterisk/cel.h"
#include "asterisk/module.h"
#include "asterisk/logger.h"

Include dependency graph for cel_pgsql.c:

Go to the source code of this file.

Data Structures

struct  columns
struct  psql_columns

Defines

#define CEL_SHOW_USERDEF_DEFAULT   0
 show_user_def is off by default
#define DATE_FORMAT   "%Y-%m-%d %T.%6q"
#define LENGTHEN_BUF1(size)
#define LENGTHEN_BUF2(size)
#define PGSQL_BACKEND_NAME   "CEL PGSQL backend"
#define SEP   (first ? "" : ",")

Functions

static void __fini_psql_columns (void)
static void __init_psql_columns (void)
static void __reg_module (void)
static void __unreg_module (void)
static int load_module (void)
static int my_load_module (int reload)
static int my_unload_module (void)
static void pgsql_log (struct ast_event *event)
static void pgsql_reconnect (void)
static int process_my_load_module (struct ast_config *cfg)
static int reload (void)
static int unload_module (void)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "PostgreSQL CEL Backend" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_EXTENDED, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CDR_DRIVER, }
static struct ast_module_infoast_module_info = &__mod_info
static unsigned char cel_show_user_def
static char * config = "cel_pgsql.conf"
static PGconn * conn = NULL
static int connected = 0
static int maxsize = 512
static int maxsize2 = 512
static char * pgappname
static char * pgdbname
static char * pgdbport
static char * pgdbuser
static char * pghostname
static char * pgpassword
static ast_mutex_t pgsql_lock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 }
static PGresult * result = NULL
static char * table
static int usegmtime = 0


Detailed Description

PostgreSQL CEL logger.

Author:
Steve Murphy <murf@digium.com> PostgreSQL http://www.postgresql.org/
See also

Definition in file cel_pgsql.c.


Define Documentation

#define CEL_SHOW_USERDEF_DEFAULT   0

show_user_def is off by default

Definition at line 78 of file cel_pgsql.c.

#define DATE_FORMAT   "%Y-%m-%d %T.%6q"

Definition at line 59 of file cel_pgsql.c.

#define LENGTHEN_BUF1 ( size   ) 

Definition at line 99 of file cel_pgsql.c.

#define LENGTHEN_BUF2 ( size   ) 

Definition at line 113 of file cel_pgsql.c.

#define PGSQL_BACKEND_NAME   "CEL PGSQL backend"

Definition at line 61 of file cel_pgsql.c.

Referenced by my_load_module(), and my_unload_module().

#define SEP   (first ? "" : ",")

Referenced by pgsql_log().


Function Documentation

static void __fini_psql_columns ( void   )  [static]

Definition at line 97 of file cel_pgsql.c.

00100 { \

static void __init_psql_columns ( void   )  [static]

Definition at line 97 of file cel_pgsql.c.

00100 { \

static void __reg_module ( void   )  [static]

Definition at line 650 of file cel_pgsql.c.

static void __unreg_module ( void   )  [static]

Definition at line 650 of file cel_pgsql.c.

static int load_module ( void   )  [static]

Definition at line 634 of file cel_pgsql.c.

References my_load_module().

00635 {
00636    return my_load_module(0);
00637 }

static int my_load_module ( int  reload  )  [static]

Definition at line 607 of file cel_pgsql.c.

References ast_cel_backend_register(), ast_config_destroy(), ast_config_load, ast_log, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, LOG_WARNING, my_unload_module(), NULL, PGSQL_BACKEND_NAME, pgsql_log(), and process_my_load_module().

00608 {
00609    struct ast_config *cfg;
00610    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
00611 
00612    if ((cfg = ast_config_load(config, config_flags)) == NULL || cfg == CONFIG_STATUS_FILEINVALID) {
00613       ast_log(LOG_WARNING, "Unable to load config for PostgreSQL CEL's: %s\n", config);
00614       return AST_MODULE_LOAD_DECLINE;
00615    } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
00616       return AST_MODULE_LOAD_SUCCESS;
00617    }
00618 
00619    if (reload) {
00620       my_unload_module();
00621    }
00622 
00623    process_my_load_module(cfg);
00624    ast_config_destroy(cfg);
00625 
00626    if (ast_cel_backend_register(PGSQL_BACKEND_NAME, pgsql_log)) {
00627       ast_log(LOG_WARNING, "Unable to subscribe to CEL events for pgsql\n");
00628       return AST_MODULE_LOAD_DECLINE;
00629    }
00630 
00631    return AST_MODULE_LOAD_SUCCESS;
00632 }

static int my_unload_module ( void   )  [static]

Definition at line 383 of file cel_pgsql.c.

References ast_cel_backend_unregister(), ast_free, AST_RWLIST_REMOVE_HEAD, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, columns::list, NULL, and PGSQL_BACKEND_NAME.

00384 {
00385    struct columns *current;
00386 
00387    ast_cel_backend_unregister(PGSQL_BACKEND_NAME);
00388    AST_RWLIST_WRLOCK(&psql_columns);
00389    if (conn) {
00390       PQfinish(conn);
00391       conn = NULL;
00392    }
00393    if (pghostname) {
00394       ast_free(pghostname);
00395       pghostname = NULL;
00396    }
00397    if (pgdbname) {
00398       ast_free(pgdbname);
00399       pgdbname = NULL;
00400    }
00401    if (pgdbuser) {
00402       ast_free(pgdbuser);
00403       pgdbuser = NULL;
00404    }
00405    if (pgpassword) {
00406       ast_free(pgpassword);
00407       pgpassword = NULL;
00408    }
00409    if (pgappname) {
00410       ast_free(pgappname);
00411       pgappname = NULL;
00412    }
00413    if (pgdbport) {
00414       ast_free(pgdbport);
00415       pgdbport = NULL;
00416    }
00417    if (table) {
00418       ast_free(table);
00419       table = NULL;
00420    }
00421    while ((current = AST_RWLIST_REMOVE_HEAD(&psql_columns, list))) {
00422       ast_free(current);
00423    }
00424    AST_RWLIST_UNLOCK(&psql_columns);
00425    return 0;
00426 }

static void pgsql_log ( struct ast_event event  )  [static]

Definition at line 155 of file cel_pgsql.c.

References ast_cel_event_record::account_code, ast_cel_event_record::amaflag, ast_cel_event_record::application_data, ast_cel_event_record::application_name, AST_CEL_EVENT_RECORD_VERSION, ast_cel_fill_record(), AST_CEL_USER_DEFINED, ast_debug, ast_free, ast_localtime(), ast_log, ast_mutex_lock, ast_mutex_unlock, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_str_append(), ast_str_buffer(), ast_str_create(), ast_str_set(), ast_str_strlen(), ast_strftime(), buf, ast_cel_event_record::caller_id_ani, ast_cel_event_record::caller_id_dnid, ast_cel_event_record::caller_id_name, ast_cel_event_record::caller_id_num, ast_cel_event_record::caller_id_rdnis, ast_cel_event_record::channel_name, ast_cel_event_record::context, DATE_FORMAT, ast_cel_event_record::event_name, ast_cel_event_record::event_time, ast_cel_event_record::event_type, ast_cel_event_record::extension, ast_cel_event_record::extra, first, LENGTHEN_BUF1, LENGTHEN_BUF2, ast_cel_event_record::linked_id, LOG_ERROR, LOG_NOTICE, LOG_WARNING, maxsize2, columns::name, NULL, ast_cel_event_record::peer, ast_cel_event_record::peer_account, pgsql_lock, pgsql_reconnect(), SEP, columns::type, ast_cel_event_record::unique_id, ast_cel_event_record::user_defined_name, ast_cel_event_record::user_field, value, and ast_cel_event_record::version.

00156 {
00157    struct ast_tm tm;
00158    char timestr[128];
00159    char *pgerror;
00160    struct ast_cel_event_record record = {
00161       .version = AST_CEL_EVENT_RECORD_VERSION,
00162    };
00163 
00164    if (ast_cel_fill_record(event, &record)) {
00165       return;
00166    }
00167 
00168    ast_mutex_lock(&pgsql_lock);
00169 
00170    ast_localtime(&record.event_time, &tm, usegmtime ? "GMT" : NULL);
00171    ast_strftime(timestr, sizeof(timestr), DATE_FORMAT, &tm);
00172 
00173    if ((!connected) && pghostname && pgdbuser && pgpassword && pgdbname) {
00174       pgsql_reconnect();
00175       if (PQstatus(conn) != CONNECTION_BAD) {
00176          connected = 1;
00177       } else {
00178          pgerror = PQerrorMessage(conn);
00179          ast_log(LOG_ERROR, "cel_pgsql: Unable to connect to database server %s.  Calls will not be logged!\n", pghostname);
00180          ast_log(LOG_ERROR, "cel_pgsql: Reason: %s\n", pgerror);
00181          PQfinish(conn);
00182          conn = NULL;
00183       }
00184    }
00185    if (connected) {
00186       struct columns *cur;
00187       struct ast_str *sql = ast_str_create(maxsize), *sql2 = ast_str_create(maxsize2);
00188       char buf[257], escapebuf[513];
00189       const char *value;
00190       int first = 1;
00191 
00192       if (!sql || !sql2) {
00193          goto ast_log_cleanup;
00194       }
00195 
00196       ast_str_set(&sql, 0, "INSERT INTO %s (", table);
00197       ast_str_set(&sql2, 0, " VALUES (");
00198 
00199 #define SEP (first ? "" : ",")
00200 
00201       AST_RWLIST_RDLOCK(&psql_columns);
00202       AST_RWLIST_TRAVERSE(&psql_columns, cur, list) {
00203          LENGTHEN_BUF1(strlen(cur->name) + 2);
00204          ast_str_append(&sql, 0, "%s\"%s\"", first ? "" : ",", cur->name);
00205 
00206          if (strcmp(cur->name, "eventtime") == 0) {
00207             if (strncmp(cur->type, "int", 3) == 0) {
00208                LENGTHEN_BUF2(13);
00209                ast_str_append(&sql2, 0, "%s%ld", SEP, (long) record.event_time.tv_sec);
00210             } else if (strncmp(cur->type, "float", 5) == 0) {
00211                LENGTHEN_BUF2(31);
00212                ast_str_append(&sql2, 0, "%s%f",
00213                   SEP,
00214                   (double) record.event_time.tv_sec +
00215                   (double) record.event_time.tv_usec / 1000000.0);
00216             } else {
00217                /* char, hopefully */
00218                LENGTHEN_BUF2(31);
00219                ast_localtime(&record.event_time, &tm, usegmtime ? "GMT" : NULL);
00220                ast_strftime(buf, sizeof(buf), DATE_FORMAT, &tm);
00221                ast_str_append(&sql2, 0, "%s'%s'", SEP, buf);
00222             }
00223          } else if (strcmp(cur->name, "eventtype") == 0) {
00224             if (cur->type[0] == 'i') {
00225                /* Get integer, no need to escape anything */
00226                LENGTHEN_BUF2(5);
00227                ast_str_append(&sql2, 0, "%s%d", SEP, (int) record.event_type);
00228             } else if (strncmp(cur->type, "float", 5) == 0) {
00229                LENGTHEN_BUF2(31);
00230                ast_str_append(&sql2, 0, "%s%f", SEP, (double) record.event_type);
00231             } else {
00232                /* Char field, probably */
00233                const char *event_name;
00234 
00235                event_name = (!cel_show_user_def
00236                   && record.event_type == AST_CEL_USER_DEFINED)
00237                   ? record.user_defined_name : record.event_name;
00238                LENGTHEN_BUF2(strlen(event_name) + 1);
00239                ast_str_append(&sql2, 0, "%s'%s'", SEP, event_name);
00240             }
00241          } else if (strcmp(cur->name, "amaflags") == 0) {
00242             if (strncmp(cur->type, "int", 3) == 0) {
00243                /* Integer, no need to escape anything */
00244                LENGTHEN_BUF2(13);
00245                ast_str_append(&sql2, 0, "%s%u", SEP, record.amaflag);
00246             } else {
00247                /* Although this is a char field, there are no special characters in the values for these fields */
00248                LENGTHEN_BUF2(31);
00249                ast_str_append(&sql2, 0, "%s'%u'", SEP, record.amaflag);
00250             }
00251          } else {
00252             /* Arbitrary field, could be anything */
00253             if (strcmp(cur->name, "userdeftype") == 0) {
00254                value = record.user_defined_name;
00255             } else if (strcmp(cur->name, "cid_name") == 0) {
00256                value = record.caller_id_name;
00257             } else if (strcmp(cur->name, "cid_num") == 0) {
00258                value = record.caller_id_num;
00259             } else if (strcmp(cur->name, "cid_ani") == 0) {
00260                value = record.caller_id_ani;
00261             } else if (strcmp(cur->name, "cid_rdnis") == 0) {
00262                value = record.caller_id_rdnis;
00263             } else if (strcmp(cur->name, "cid_dnid") == 0) {
00264                value = record.caller_id_dnid;
00265             } else if (strcmp(cur->name, "exten") == 0) {
00266                value = record.extension;
00267             } else if (strcmp(cur->name, "context") == 0) {
00268                value = record.context;
00269             } else if (strcmp(cur->name, "channame") == 0) {
00270                value = record.channel_name;
00271             } else if (strcmp(cur->name, "appname") == 0) {
00272                value = record.application_name;
00273             } else if (strcmp(cur->name, "appdata") == 0) {
00274                value = record.application_data;
00275             } else if (strcmp(cur->name, "accountcode") == 0) {
00276                value = record.account_code;
00277             } else if (strcmp(cur->name, "peeraccount") == 0) {
00278                value = record.peer_account;
00279             } else if (strcmp(cur->name, "uniqueid") == 0) {
00280                value = record.unique_id;
00281             } else if (strcmp(cur->name, "linkedid") == 0) {
00282                value = record.linked_id;
00283             } else if (strcmp(cur->name, "userfield") == 0) {
00284                value = record.user_field;
00285             } else if (strcmp(cur->name, "peer") == 0) {
00286                value = record.peer;
00287             } else if (strcmp(cur->name, "extra") == 0) {
00288                value = record.extra;
00289             } else {
00290                value = NULL;
00291             }
00292 
00293             if (value == NULL) {
00294                ast_str_append(&sql2, 0, "%sDEFAULT", SEP);
00295             } else if (strncmp(cur->type, "int", 3) == 0) {
00296                long long whatever;
00297                if (value && sscanf(value, "%30lld", &whatever) == 1) {
00298                   LENGTHEN_BUF2(26);
00299                   ast_str_append(&sql2, 0, "%s%lld", SEP, whatever);
00300                } else {
00301                   LENGTHEN_BUF2(2);
00302                   ast_str_append(&sql2, 0, "%s0", SEP);
00303                }
00304             } else if (strncmp(cur->type, "float", 5) == 0) {
00305                long double whatever;
00306                if (value && sscanf(value, "%30Lf", &whatever) == 1) {
00307                   LENGTHEN_BUF2(51);
00308                   ast_str_append(&sql2, 0, "%s%30Lf", SEP, whatever);
00309                } else {
00310                   LENGTHEN_BUF2(2);
00311                   ast_str_append(&sql2, 0, "%s0", SEP);
00312                }
00313                /* XXX Might want to handle dates, times, and other misc fields here XXX */
00314             } else {
00315                if (value) {
00316                   PQescapeStringConn(conn, escapebuf, value, strlen(value), NULL);
00317                } else {
00318                   escapebuf[0] = '\0';
00319                }
00320                LENGTHEN_BUF2(strlen(escapebuf) + 3);
00321                ast_str_append(&sql2, 0, "%s'%s'", SEP, escapebuf);
00322             }
00323          }
00324          first = 0;
00325       }
00326       AST_RWLIST_UNLOCK(&psql_columns);
00327       LENGTHEN_BUF1(ast_str_strlen(sql2) + 2);
00328       ast_str_append(&sql, 0, ")%s)", ast_str_buffer(sql2));
00329 
00330       ast_debug(3, "Inserting a CEL record: [%s].\n", ast_str_buffer(sql));
00331       /* Test to be sure we're still connected... */
00332       /* If we're connected, and connection is working, good. */
00333       /* Otherwise, attempt reconnect.  If it fails... sorry... */
00334       if (PQstatus(conn) == CONNECTION_OK) {
00335          connected = 1;
00336       } else {
00337          ast_log(LOG_WARNING, "Connection was lost... attempting to reconnect.\n");
00338          PQreset(conn);
00339          if (PQstatus(conn) == CONNECTION_OK) {
00340             ast_log(LOG_NOTICE, "Connection reestablished.\n");
00341             connected = 1;
00342          } else {
00343             pgerror = PQerrorMessage(conn);
00344             ast_log(LOG_ERROR, "Unable to reconnect to database server %s. Calls will not be logged!\n", pghostname);
00345             ast_log(LOG_ERROR, "Reason: %s\n", pgerror);
00346             PQfinish(conn);
00347             conn = NULL;
00348             connected = 0;
00349             goto ast_log_cleanup;
00350          }
00351       }
00352       result = PQexec(conn, ast_str_buffer(sql));
00353       if (PQresultStatus(result) != PGRES_COMMAND_OK) {
00354          pgerror = PQresultErrorMessage(result);
00355          ast_log(LOG_WARNING, "Failed to insert call detail record into database!\n");
00356          ast_log(LOG_WARNING, "Reason: %s\n", pgerror);
00357          ast_log(LOG_WARNING, "Connection may have been lost... attempting to reconnect.\n");
00358          PQreset(conn);
00359          if (PQstatus(conn) == CONNECTION_OK) {
00360             ast_log(LOG_NOTICE, "Connection reestablished.\n");
00361             connected = 1;
00362             PQclear(result);
00363             result = PQexec(conn, ast_str_buffer(sql));
00364             if (PQresultStatus(result) != PGRES_COMMAND_OK) {
00365                pgerror = PQresultErrorMessage(result);
00366                ast_log(LOG_ERROR, "HARD ERROR!  Attempted reconnection failed.  DROPPING CALL RECORD!\n");
00367                ast_log(LOG_ERROR, "Reason: %s\n", pgerror);
00368             }
00369          }
00370          PQclear(result);
00371          goto ast_log_cleanup;
00372       }
00373       PQclear(result);
00374 
00375 ast_log_cleanup:
00376       ast_free(sql);
00377       ast_free(sql2);
00378    }
00379 
00380    ast_mutex_unlock(&pgsql_lock);
00381 }

static void pgsql_reconnect ( void   )  [static]

Definition at line 126 of file cel_pgsql.c.

References ast_free, ast_log, ast_str_append(), ast_str_buffer(), ast_str_create(), ast_str_set(), ast_strlen_zero, LOG_ERROR, and NULL.

00127 {
00128    struct ast_str *conn_info = ast_str_create(128);
00129    if (!conn_info) {
00130       ast_log(LOG_ERROR, "Failed to allocate memory for connection string.\n");
00131       return;
00132    }
00133 
00134    if (conn) {
00135       PQfinish(conn);
00136       conn = NULL;
00137    }
00138 
00139    ast_str_set(&conn_info, 0, "host=%s port=%s dbname=%s user=%s",
00140       pghostname, pgdbport, pgdbname, pgdbuser);
00141 
00142    if (!ast_strlen_zero(pgappname)) {
00143       ast_str_append(&conn_info, 0, " application_name=%s", pgappname);
00144    }
00145 
00146    if (!ast_strlen_zero(pgpassword)) {
00147       ast_str_append(&conn_info, 0, " password=%s", pgpassword);
00148    }
00149 
00150    conn = PQconnectdb(ast_str_buffer(conn_info));
00151    ast_free(conn_info);
00152 }

static int process_my_load_module ( struct ast_config cfg  )  [static]

Definition at line 433 of file cel_pgsql.c.

References ast_calloc, ast_debug, ast_free, ast_log, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, AST_RWLIST_INSERT_TAIL, ast_strdup, ast_strlen_zero, ast_true(), ast_variable_browse(), ast_variable_retrieve(), ast_verb, CEL_SHOW_USERDEF_DEFAULT, columns::hasdefault, columns::len, columns::list, LOG_ERROR, LOG_WARNING, columns::name, columns::notnull, NULL, option_debug, pgsql_reconnect(), tmp(), columns::type, unload_module, and var.

Referenced by my_load_module().

00434 {
00435    struct ast_variable *var;
00436    char *pgerror;
00437    const char *tmp;
00438    PGresult *result;
00439    struct columns *cur;
00440 
00441    if (!(var = ast_variable_browse(cfg, "global"))) {
00442       ast_log(LOG_WARNING,"CEL pgsql config file missing global section.\n");
00443       return AST_MODULE_LOAD_DECLINE;
00444    }
00445    if (!(tmp = ast_variable_retrieve(cfg,"global","hostname"))) {
00446       ast_log(LOG_WARNING,"PostgreSQL server hostname not specified.  Assuming unix socket connection\n");
00447       tmp = "";   /* connect via UNIX-socket by default */
00448    }
00449    if (pghostname)
00450       ast_free(pghostname);
00451    if (!(pghostname = ast_strdup(tmp))) {
00452       ast_log(LOG_WARNING,"PostgreSQL Ran out of memory copying host info\n");
00453       return AST_MODULE_LOAD_DECLINE;
00454    }
00455    if (!(tmp = ast_variable_retrieve(cfg, "global", "dbname"))) {
00456       ast_log(LOG_WARNING,"PostgreSQL database not specified.  Assuming asterisk\n");
00457       tmp = "asteriskceldb";
00458    }
00459    if (pgdbname)
00460       ast_free(pgdbname);
00461    if (!(pgdbname = ast_strdup(tmp))) {
00462       ast_log(LOG_WARNING,"PostgreSQL Ran out of memory copying dbname info\n");
00463       return AST_MODULE_LOAD_DECLINE;
00464    }
00465    if (!(tmp = ast_variable_retrieve(cfg, "global", "user"))) {
00466       ast_log(LOG_WARNING,"PostgreSQL database user not specified.  Assuming asterisk\n");
00467       tmp = "asterisk";
00468    }
00469    if (pgdbuser)
00470       ast_free(pgdbuser);
00471    if (!(pgdbuser = ast_strdup(tmp))) {
00472       ast_log(LOG_WARNING,"PostgreSQL Ran out of memory copying user info\n");
00473       return AST_MODULE_LOAD_DECLINE;
00474    }
00475    if (!(tmp = ast_variable_retrieve(cfg, "global", "password"))) {
00476       ast_log(LOG_WARNING, "PostgreSQL database password not specified.  Assuming blank\n");
00477       tmp = "";
00478    }
00479    if (pgpassword)
00480       ast_free(pgpassword);
00481    if (!(pgpassword = ast_strdup(tmp))) {
00482       ast_log(LOG_WARNING,"PostgreSQL Ran out of memory copying password info\n");
00483       return AST_MODULE_LOAD_DECLINE;
00484    }
00485    if (!(tmp = ast_variable_retrieve(cfg, "global", "appname"))) {
00486       tmp = "";
00487    }
00488    if (pgappname) {
00489       ast_free(pgappname);
00490    }
00491    if (!(pgappname = ast_strdup(tmp))) {
00492       ast_log(LOG_WARNING,"PostgreSQL Ran out of memory copying appname info\n");
00493       return AST_MODULE_LOAD_DECLINE;
00494    }
00495 
00496    if (!(tmp = ast_variable_retrieve(cfg,"global","port"))) {
00497       ast_log(LOG_WARNING,"PostgreSQL database port not specified.  Using default 5432.\n");
00498       tmp = "5432";
00499    }
00500    if (pgdbport)
00501       ast_free(pgdbport);
00502    if (!(pgdbport = ast_strdup(tmp))) {
00503       ast_log(LOG_WARNING,"PostgreSQL Ran out of memory copying port info\n");
00504       return AST_MODULE_LOAD_DECLINE;
00505    }
00506    if (!(tmp = ast_variable_retrieve(cfg, "global", "table"))) {
00507       ast_log(LOG_WARNING,"CEL table not specified.  Assuming cel\n");
00508       tmp = "cel";
00509    }
00510    if (table)
00511       ast_free(table);
00512    if (!(table = ast_strdup(tmp))) {
00513       return AST_MODULE_LOAD_DECLINE;
00514    }
00515    cel_show_user_def = CEL_SHOW_USERDEF_DEFAULT;
00516    if ((tmp = ast_variable_retrieve(cfg, "global", "show_user_defined"))) {
00517       cel_show_user_def = ast_true(tmp) ? 1 : 0;
00518    }
00519    if ((tmp = ast_variable_retrieve(cfg, "global", "usegmtime"))) {
00520       usegmtime = ast_true(tmp);
00521    } else {
00522       usegmtime = 0;
00523    }
00524    if (option_debug) {
00525       if (ast_strlen_zero(pghostname)) {
00526          ast_debug(3, "cel_pgsql: using default unix socket\n");
00527       } else {
00528          ast_debug(3, "cel_pgsql: got hostname of %s\n", pghostname);
00529       }
00530       ast_debug(3, "cel_pgsql: got port of %s\n", pgdbport);
00531       ast_debug(3, "cel_pgsql: got user of %s\n", pgdbuser);
00532       ast_debug(3, "cel_pgsql: got dbname of %s\n", pgdbname);
00533       ast_debug(3, "cel_pgsql: got password of %s\n", pgpassword);
00534       ast_debug(3, "cel_pgsql: got sql table name of %s\n", table);
00535       ast_debug(3, "cel_pgsql: got show_user_defined of %s\n",
00536          cel_show_user_def ? "Yes" : "No");
00537    }
00538 
00539    pgsql_reconnect();
00540    if (PQstatus(conn) != CONNECTION_BAD) {
00541       char sqlcmd[512];
00542       char *fname, *ftype, *flen, *fnotnull, *fdef;
00543       char *tableptr;
00544       int i, rows;
00545 
00546       ast_debug(1, "Successfully connected to PostgreSQL database.\n");
00547       connected = 1;
00548 
00549       /* Remove any schema name from the table */
00550       if ((tableptr = strrchr(table, '.'))) {
00551          tableptr++;
00552       } else {
00553          tableptr = table;
00554       }
00555 
00556       /* Query the columns */
00557       snprintf(sqlcmd, sizeof(sqlcmd), "select a.attname, t.typname, a.attlen, a.attnotnull, d.adsrc from pg_class c, pg_type t, pg_attribute a left outer join pg_attrdef d on a.atthasdef and d.adrelid = a.attrelid and d.adnum = a.attnum where c.oid = a.attrelid and a.atttypid = t.oid and (a.attnum > 0) and c.relname = '%s' order by c.relname, attnum", tableptr);
00558       result = PQexec(conn, sqlcmd);
00559       if (PQresultStatus(result) != PGRES_TUPLES_OK) {
00560          pgerror = PQresultErrorMessage(result);
00561          ast_log(LOG_ERROR, "Failed to query database columns: %s\n", pgerror);
00562          PQclear(result);
00563          unload_module();
00564          return AST_MODULE_LOAD_DECLINE;
00565       }
00566 
00567       rows = PQntuples(result);
00568       for (i = 0; i < rows; i++) {
00569          fname = PQgetvalue(result, i, 0);
00570          ftype = PQgetvalue(result, i, 1);
00571          flen = PQgetvalue(result, i, 2);
00572          fnotnull = PQgetvalue(result, i, 3);
00573          fdef = PQgetvalue(result, i, 4);
00574          ast_verb(4, "Found column '%s' of type '%s'\n", fname, ftype);
00575          cur = ast_calloc(1, sizeof(*cur) + strlen(fname) + strlen(ftype) + 2);
00576          if (cur) {
00577             sscanf(flen, "%30d", &cur->len);
00578             cur->name = (char *)cur + sizeof(*cur);
00579             cur->type = (char *)cur + sizeof(*cur) + strlen(fname) + 1;
00580             strcpy(cur->name, fname);
00581             strcpy(cur->type, ftype);
00582             if (*fnotnull == 't') {
00583                cur->notnull = 1;
00584             } else {
00585                cur->notnull = 0;
00586             }
00587             if (!ast_strlen_zero(fdef)) {
00588                cur->hasdefault = 1;
00589             } else {
00590                cur->hasdefault = 0;
00591             }
00592             AST_RWLIST_INSERT_TAIL(&psql_columns, cur, list);
00593          }
00594       }
00595       PQclear(result);
00596    } else {
00597       pgerror = PQerrorMessage(conn);
00598       ast_log(LOG_ERROR, "cel_pgsql: Unable to connect to database server %s.  CALLS WILL NOT BE LOGGED!!\n", pghostname);
00599       ast_log(LOG_ERROR, "cel_pgsql: Reason: %s\n", pgerror);
00600       connected = 0;
00601       PQfinish(conn);
00602       conn = NULL;
00603    }
00604    return AST_MODULE_LOAD_SUCCESS;
00605 }

static int reload ( void   )  [static]

Definition at line 639 of file cel_pgsql.c.

References my_load_module().

00640 {
00641    return my_load_module(1);
00642 }

static int unload_module ( void   )  [static]

Definition at line 428 of file cel_pgsql.c.

References my_unload_module().

00429 {
00430    return my_unload_module();
00431 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "PostgreSQL CEL Backend" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_EXTENDED, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CDR_DRIVER, } [static]

Definition at line 650 of file cel_pgsql.c.

Definition at line 650 of file cel_pgsql.c.

unsigned char cel_show_user_def [static]

TRUE if we should set the eventtype field to USER_DEFINED on user events.

Definition at line 81 of file cel_pgsql.c.

char* config = "cel_pgsql.conf" [static]

Definition at line 63 of file cel_pgsql.c.

PGconn* conn = NULL [static]

Definition at line 85 of file cel_pgsql.c.

int connected = 0 [static]

Definition at line 73 of file cel_pgsql.c.

int maxsize = 512 [static]

Definition at line 74 of file cel_pgsql.c.

int maxsize2 = 512 [static]

Definition at line 74 of file cel_pgsql.c.

char* pgappname [static]

Definition at line 69 of file cel_pgsql.c.

char* pgdbname [static]

Definition at line 66 of file cel_pgsql.c.

char* pgdbport [static]

Definition at line 70 of file cel_pgsql.c.

char* pgdbuser [static]

Definition at line 67 of file cel_pgsql.c.

char* pghostname [static]

Definition at line 65 of file cel_pgsql.c.

char* pgpassword [static]

Definition at line 68 of file cel_pgsql.c.

ast_mutex_t pgsql_lock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 } [static]

Definition at line 83 of file cel_pgsql.c.

PGresult* result = NULL [static]

Examples:
/tmp/asterisk-trunk/trunk/main/app.c.

Definition at line 86 of file cel_pgsql.c.

Referenced by __ast_channel_alloc(), __ast_string_field_alloc_space(), __astman_get_header(), _rl_compat_sub(), acf_meetme_info(), action_updateconfig(), ast_build_string(), ast_build_string_va(), ast_config_internal_load(), ast_config_load2(), ast_format_cap_get_compatible_format(), ast_format_cap_get_format_framing(), ast_gethostbyname(), ast_log_full(), ast_msg_has_destination(), ast_parse_arg(), ast_privacy_check(), AST_TEST_DEFINE(), ast_websocket_client_create(), astman_verify_session_readpermissions(), astman_verify_session_writepermissions(), blackfilter_cmp_fn(), chat(), check_eval(), check_sip_domain(), cli_complete_endpoint(), cli_complete_registration(), cli_complete_show(), closefrom(), complete_show_sorcery_object(), complete_sip_peer(), complete_sip_registered_peer(), complete_sip_user(), config_module(), config_mysql(), config_pgsql(), cops_connect(), data_result_generate(), db_get_common(), destroy_pgsql(), detzcode(), detzcode64(), dial_exec_full(), dns_query_recurring_resolution_callback(), error(), fax_detect_framehook(), fax_gateway_attach(), fax_gateway_detect_t38(), fax_gateway_framehook(), fax_gateway_start(), find_recording(), find_result(), find_table(), generic_fax_exec(), gmtsub(), handle_request_invite(), handle_speechrecognize(), handle_standard_bridge_enter_message(), handle_updates(), history_expand(), history_tokenize(), inform(), invalid_record_test(), launch_ha_netscript(), ldap_loadentry(), listfilter(), localized_config_load(), localized_config_load_with_comments(), localsub(), mallocconcat(), malloccopy(), match_filter(), mgcpsock_read(), mwi_thread(), my_load_module(), MYSQL_exec(), nominal_test(), odbc_datastore_free(), off_nominal_test(), ogg_vorbis_open(), op_func(), P3(), parsefilearg(), pgsql_log(), phoneprov_callback(), radius_log(), read_credentials(), realtime_ldap_base_ap(), realtime_multi_mysql(), realtime_multi_pgsql(), realtime_mysql(), realtime_pgsql(), receivefax_exec(), require_pgsql(), say(), scan_dir(), sendfax_exec(), sip_report_security_event(), speech_grammar(), speech_read(), speech_score(), speech_text(), store_pgsql(), t30_phase_e_handler(), test_results(), testtime_write(), tmcomp(), tzload(), update2_ldap(), update2_pgsql(), update_ldap(), update_pgsql(), and whitefilter_cmp_fn().

char* table [static]

Definition at line 71 of file cel_pgsql.c.

int usegmtime = 0 [static]

Definition at line 75 of file cel_pgsql.c.


Generated on Thu Apr 16 06:29:29 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6