Fri Jul 24 00:41:19 2009

Asterisk developer's documentation


cdr_pgsql.c File Reference

PostgreSQL CDR logger. More...

#include "asterisk.h"
#include <time.h>
#include <libpq-fe.h>
#include "asterisk/config.h"
#include "asterisk/channel.h"
#include "asterisk/cdr.h"
#include "asterisk/module.h"

Go to the source code of this file.

Data Structures

struct  columns
struct  psql_columns

Defines

#define DATE_FORMAT   "'%Y-%m-%d %T'"
#define LENGTHEN_BUF1(size)
#define LENGTHEN_BUF2(size)

Functions

static void __reg_module (void)
static void __unreg_module (void)
static int config_module (int reload)
static int load_module (void)
static int pgsql_log (struct ast_cdr *cdr)
static int reload (void)
static int unload_module (void)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "PostgreSQL CDR 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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload, }
static struct ast_module_infoast_module_info = &__mod_info
static char * config = "cdr_pgsql.conf"
static PGconn * conn = NULL
static int connected = 0
static int maxsize = 512
static int maxsize2 = 512
static char * name = "pgsql"
static char * pgdbname = NULL
static char * pgdbport = NULL
static char * pgdbuser = NULL
static char * pghostname = NULL
static char * pgpassword = NULL
static ast_mutex_t pgsql_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP )
static char * table = NULL


Detailed Description

PostgreSQL CDR logger.

Author:
Matthew D. Hardeman <mhardemn@papersoft.com>
ExtRef:
PostgreSQL http://www.postgresql.org/
See also

Definition in file cdr_pgsql.c.


Define Documentation

#define DATE_FORMAT   "'%Y-%m-%d %T'"

Definition at line 53 of file cdr_pgsql.c.

#define LENGTHEN_BUF1 ( size   ) 

Definition at line 76 of file cdr_pgsql.c.

#define LENGTHEN_BUF2 ( size   ) 

Definition at line 93 of file cdr_pgsql.c.


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 557 of file cdr_pgsql.c.

static void __unreg_module ( void   )  [static]

Definition at line 557 of file cdr_pgsql.c.

static int config_module ( int  reload  )  [static]

Definition at line 369 of file cdr_pgsql.c.

References ast_calloc, ast_cdr_register(), ast_config_destroy(), ast_config_load, ast_debug, ast_free, ast_log(), AST_MODULE_LOAD_DECLINE, AST_RWLIST_INSERT_TAIL, ast_strdup, ast_strlen_zero(), ast_variable_browse(), ast_variable_retrieve(), ast_verb, CONFIG_FLAG_FILEUNCHANGED, config_flags, CONFIG_STATUS_FILEUNCHANGED, columns::list, LOG_ERROR, LOG_WARNING, option_debug, pgsql_log(), unload_module(), and var.

Referenced by load_module(), and reload().

00370 {
00371    struct ast_variable *var;
00372    char *pgerror;
00373    struct columns *cur;
00374    PGresult *result;
00375    const char *tmp;
00376    struct ast_config *cfg;
00377    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
00378 
00379    if ((cfg = ast_config_load(config, config_flags)) == NULL) {
00380       ast_log(LOG_WARNING, "Unable to load config for PostgreSQL CDR's: %s\n", config);
00381       return -1;
00382    } else if (cfg == CONFIG_STATUS_FILEUNCHANGED)
00383       return 0;
00384 
00385    if (!(var = ast_variable_browse(cfg, "global"))) {
00386       ast_config_destroy(cfg);
00387       return 0;
00388    }
00389 
00390    if (!(tmp = ast_variable_retrieve(cfg, "global", "hostname"))) {
00391       ast_log(LOG_WARNING, "PostgreSQL server hostname not specified.  Assuming unix socket connection\n");
00392       tmp = "";   /* connect via UNIX-socket by default */
00393    }
00394 
00395    if (pghostname)
00396       ast_free(pghostname);
00397    if (!(pghostname = ast_strdup(tmp))) {
00398       ast_config_destroy(cfg);
00399       return -1;
00400    }
00401 
00402    if (!(tmp = ast_variable_retrieve(cfg, "global", "dbname"))) {
00403       ast_log(LOG_WARNING, "PostgreSQL database not specified.  Assuming asterisk\n");
00404       tmp = "asteriskcdrdb";
00405    }
00406 
00407    if (pgdbname)
00408       ast_free(pgdbname);
00409    if (!(pgdbname = ast_strdup(tmp))) {
00410       ast_config_destroy(cfg);
00411       return -1;
00412    }
00413 
00414    if (!(tmp = ast_variable_retrieve(cfg, "global", "user"))) {
00415       ast_log(LOG_WARNING, "PostgreSQL database user not specified.  Assuming asterisk\n");
00416       tmp = "asterisk";
00417    }
00418 
00419    if (pgdbuser)
00420       ast_free(pgdbuser);
00421    if (!(pgdbuser = ast_strdup(tmp))) {
00422       ast_config_destroy(cfg);
00423       return -1;
00424    }
00425 
00426    if (!(tmp = ast_variable_retrieve(cfg, "global", "password"))) {
00427       ast_log(LOG_WARNING, "PostgreSQL database password not specified.  Assuming blank\n");
00428       tmp = "";
00429    }
00430 
00431    if (pgpassword)
00432       ast_free(pgpassword);
00433    if (!(pgpassword = ast_strdup(tmp))) {
00434       ast_config_destroy(cfg);
00435       return -1;
00436    }
00437 
00438    if (!(tmp = ast_variable_retrieve(cfg, "global", "port"))) {
00439       ast_log(LOG_WARNING, "PostgreSQL database port not specified.  Using default 5432.\n");
00440       tmp = "5432";
00441    }
00442 
00443    if (pgdbport)
00444       ast_free(pgdbport);
00445    if (!(pgdbport = ast_strdup(tmp))) {
00446       ast_config_destroy(cfg);
00447       return -1;
00448    }
00449 
00450    if (!(tmp = ast_variable_retrieve(cfg, "global", "table"))) {
00451       ast_log(LOG_WARNING, "CDR table not specified.  Assuming cdr\n");
00452       tmp = "cdr";
00453    }
00454 
00455    if (table)
00456       ast_free(table);
00457    if (!(table = ast_strdup(tmp))) {
00458       ast_config_destroy(cfg);
00459       return -1;
00460    }
00461 
00462    if (option_debug) {
00463       if (ast_strlen_zero(pghostname)) {
00464          ast_debug(1, "using default unix socket\n");
00465       } else {
00466          ast_debug(1, "got hostname of %s\n", pghostname);
00467       }
00468       ast_debug(1, "got port of %s\n", pgdbport);
00469       ast_debug(1, "got user of %s\n", pgdbuser);
00470       ast_debug(1, "got dbname of %s\n", pgdbname);
00471       ast_debug(1, "got password of %s\n", pgpassword);
00472       ast_debug(1, "got sql table name of %s\n", table);
00473    }
00474 
00475    conn = PQsetdbLogin(pghostname, pgdbport, NULL, NULL, pgdbname, pgdbuser, pgpassword);
00476    if (PQstatus(conn) != CONNECTION_BAD) {
00477       char sqlcmd[512];
00478       char *fname, *ftype, *flen, *fnotnull, *fdef;
00479       char *tableptr;
00480       int i, rows;
00481       ast_debug(1, "Successfully connected to PostgreSQL database.\n");
00482       connected = 1;
00483 
00484       /* Remove any schema name from the table */
00485       if ((tableptr = strrchr(table, '.'))) {
00486          tableptr++;
00487       } else {
00488          tableptr = table;
00489       }
00490 
00491       /* Query the columns */
00492       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);
00493       result = PQexec(conn, sqlcmd);
00494       if (PQresultStatus(result) != PGRES_TUPLES_OK) {
00495          pgerror = PQresultErrorMessage(result);
00496          ast_log(LOG_ERROR, "Failed to query database columns: %s\n", pgerror);
00497          PQclear(result);
00498          unload_module();
00499          return AST_MODULE_LOAD_DECLINE;
00500       }
00501 
00502       rows = PQntuples(result);
00503       for (i = 0; i < rows; i++) {
00504          fname = PQgetvalue(result, i, 0);
00505          ftype = PQgetvalue(result, i, 1);
00506          flen = PQgetvalue(result, i, 2);
00507          fnotnull = PQgetvalue(result, i, 3);
00508          fdef = PQgetvalue(result, i, 4);
00509          ast_verb(4, "Found column '%s' of type '%s'\n", fname, ftype);
00510          cur = ast_calloc(1, sizeof(*cur) + strlen(fname) + strlen(ftype) + 2);
00511          if (cur) {
00512             sscanf(flen, "%d", &cur->len);
00513             cur->name = (char *)cur + sizeof(*cur);
00514             cur->type = (char *)cur + sizeof(*cur) + strlen(fname) + 1;
00515             strcpy(cur->name, fname);
00516             strcpy(cur->type, ftype);
00517             if (*fnotnull == 't') {
00518                cur->notnull = 1;
00519             } else {
00520                cur->notnull = 0;
00521             }
00522             if (!ast_strlen_zero(fdef)) {
00523                cur->hasdefault = 1;
00524             } else {
00525                cur->hasdefault = 0;
00526             }
00527             AST_RWLIST_INSERT_TAIL(&psql_columns, cur, list);
00528          }
00529       }
00530       PQclear(result);
00531    } else {
00532       pgerror = PQerrorMessage(conn);
00533       ast_log(LOG_ERROR, "Unable to connect to database server %s.  CALLS WILL NOT BE LOGGED!!\n", pghostname);
00534       ast_log(LOG_ERROR, "Reason: %s\n", pgerror);
00535       connected = 0;
00536    }
00537 
00538    ast_config_destroy(cfg);
00539 
00540    return ast_cdr_register(name, ast_module_info->description, pgsql_log);
00541 }

static int load_module ( void   )  [static]

Definition at line 543 of file cdr_pgsql.c.

References AST_MODULE_LOAD_DECLINE, and config_module().

00544 {
00545    return config_module(0) ? AST_MODULE_LOAD_DECLINE : 0;
00546 }

static int pgsql_log ( struct ast_cdr cdr  )  [static]

Definition at line 109 of file cdr_pgsql.c.

References ast_cdr::answer, ast_calloc, ast_cdr_getvar(), ast_debug, ast_free, ast_localtime(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strftime(), ast_verb, buf, DATE_FORMAT, ast_cdr::end, columns::hasdefault, LENGTHEN_BUF1, LENGTHEN_BUF2, columns::list, LOG_ERROR, maxsize2, columns::name, columns::notnull, pgsql_lock, ast_cdr::start, and columns::type.

Referenced by config_module().

00110 {
00111    struct ast_tm tm;
00112    char *pgerror;
00113    PGresult *result;
00114 
00115    ast_mutex_lock(&pgsql_lock);
00116 
00117    if ((!connected) && pghostname && pgdbuser && pgpassword && pgdbname) {
00118       conn = PQsetdbLogin(pghostname, pgdbport, NULL, NULL, pgdbname, pgdbuser, pgpassword);
00119       if (PQstatus(conn) != CONNECTION_BAD) {
00120          connected = 1;
00121       } else {
00122          pgerror = PQerrorMessage(conn);
00123          ast_log(LOG_ERROR, "Unable to connect to database server %s.  Calls will not be logged!\n", pghostname);
00124          ast_log(LOG_ERROR, "Reason: %s\n", pgerror);
00125          PQfinish(conn);
00126          conn = NULL;
00127       }
00128    }
00129 
00130    if (connected) {
00131       struct columns *cur;
00132       int lensql, lensql2, sizesql = maxsize, sizesql2 = maxsize2, newsize;
00133       char *sql = ast_calloc(sizeof(char), sizesql), *sql2 = ast_calloc(sizeof(char), sizesql2), *tmp, *value;
00134       char buf[257], escapebuf[513];
00135 
00136       if (!sql || !sql2) {
00137          if (sql) {
00138             ast_free(sql);
00139          }
00140          if (sql2) {
00141             ast_free(sql2);
00142          }
00143          return -1;
00144       }
00145 
00146       lensql = snprintf(sql, sizesql, "INSERT INTO %s (", table);
00147       lensql2 = snprintf(sql2, sizesql2, " VALUES (");
00148 
00149       AST_RWLIST_RDLOCK(&psql_columns);
00150       AST_RWLIST_TRAVERSE(&psql_columns, cur, list) {
00151          /* For fields not set, simply skip them */
00152          ast_cdr_getvar(cdr, cur->name, &value, buf, sizeof(buf), 0, 0);
00153          if (strcmp(cur->name, "calldate") == 0 && !value) {
00154             ast_cdr_getvar(cdr, "start", &value, buf, sizeof(buf), 0, 0);
00155          }
00156          if (!value) {
00157             if (cur->notnull && !cur->hasdefault) {
00158                /* Field is NOT NULL (but no default), must include it anyway */
00159                LENGTHEN_BUF1(strlen(cur->name) + 2);
00160                lensql += snprintf(sql + lensql, sizesql - lensql, "\"%s\",", cur->name);
00161                LENGTHEN_BUF2(3);
00162                strcat(sql2, "'',");
00163                lensql2 += 3;
00164             }
00165             continue;
00166          }
00167 
00168          LENGTHEN_BUF1(strlen(cur->name) + 2);
00169          lensql += snprintf(sql + lensql, sizesql - lensql, "\"%s\",", cur->name);
00170 
00171          if (strcmp(cur->name, "start") == 0 || strcmp(cur->name, "calldate") == 0) {
00172             if (strncmp(cur->type, "int", 3) == 0) {
00173                LENGTHEN_BUF2(12);
00174                lensql2 += snprintf(sql2 + lensql2, sizesql2 - lensql2, "%ld", cdr->start.tv_sec);
00175             } else if (strncmp(cur->type, "float", 5) == 0) {
00176                LENGTHEN_BUF2(30);
00177                lensql2 += snprintf(sql2 + lensql2, sizesql2 - lensql2, "%f", (double)cdr->start.tv_sec + (double)cdr->start.tv_usec / 1000000.0);
00178             } else {
00179                /* char, hopefully */
00180                LENGTHEN_BUF2(30);
00181                ast_localtime(&cdr->start, &tm, NULL);
00182                lensql2 += ast_strftime(sql2 + lensql2, sizesql2 - lensql2, DATE_FORMAT, &tm);
00183             }
00184          } else if (strcmp(cur->name, "answer") == 0) {
00185             if (strncmp(cur->type, "int", 3) == 0) {
00186                LENGTHEN_BUF2(12);
00187                lensql2 += snprintf(sql2 + lensql2, sizesql2 - lensql2, "%ld", cdr->answer.tv_sec);
00188             } else if (strncmp(cur->type, "float", 5) == 0) {
00189                LENGTHEN_BUF2(30);
00190                lensql2 += snprintf(sql2 + lensql2, sizesql2 - lensql2, "%f", (double)cdr->answer.tv_sec + (double)cdr->answer.tv_usec / 1000000.0);
00191             } else {
00192                /* char, hopefully */
00193                LENGTHEN_BUF2(30);
00194                ast_localtime(&cdr->start, &tm, NULL);
00195                lensql2 += ast_strftime(sql2 + lensql2, sizesql2 - lensql2, DATE_FORMAT, &tm);
00196             }
00197          } else if (strcmp(cur->name, "end") == 0) {
00198             if (strncmp(cur->type, "int", 3) == 0) {
00199                LENGTHEN_BUF2(12);
00200                lensql2 += snprintf(sql2 + lensql2, sizesql2 - lensql2, "%ld", cdr->end.tv_sec);
00201             } else if (strncmp(cur->type, "float", 5) == 0) {
00202                LENGTHEN_BUF2(30);
00203                lensql2 += snprintf(sql2 + lensql2, sizesql2 - lensql2, "%f", (double)cdr->end.tv_sec + (double)cdr->end.tv_usec / 1000000.0);
00204             } else {
00205                /* char, hopefully */
00206                LENGTHEN_BUF2(30);
00207                ast_localtime(&cdr->end, &tm, NULL);
00208                lensql2 += ast_strftime(sql2 + lensql2, sizesql2 - lensql2, DATE_FORMAT, &tm);
00209             }
00210          } else if (strcmp(cur->name, "duration") == 0 || strcmp(cur->name, "billsec") == 0) {
00211             if (cur->type[0] == 'i') {
00212                /* Get integer, no need to escape anything */
00213                ast_cdr_getvar(cdr, cur->name, &value, buf, sizeof(buf), 0, 0);
00214                LENGTHEN_BUF2(12);
00215                lensql2 += snprintf(sql2 + lensql2, sizesql2 - lensql2, "%s", value);
00216             } else if (strncmp(cur->type, "float", 5) == 0) {
00217                struct timeval *when = cur->name[0] == 'd' ? &cdr->start : &cdr->answer;
00218                LENGTHEN_BUF2(30);
00219                lensql2 += snprintf(sql2 + lensql2, sizesql2 - lensql2, "%f", (double)cdr->end.tv_sec - when->tv_sec + cdr->end.tv_usec / 1000000.0 - when->tv_usec / 1000000.0);
00220             } else {
00221                /* Char field, probably */
00222                struct timeval *when = cur->name[0] == 'd' ? &cdr->start : &cdr->answer;
00223                LENGTHEN_BUF2(30);
00224                lensql2 += snprintf(sql2 + lensql2, sizesql2 - lensql2, "'%f'", (double)cdr->end.tv_sec - when->tv_sec + cdr->end.tv_usec / 1000000.0 - when->tv_usec / 1000000.0);
00225             }
00226          } else if (strcmp(cur->name, "disposition") == 0 || strcmp(cur->name, "amaflags") == 0) {
00227             if (strncmp(cur->type, "int", 3) == 0) {
00228                /* Integer, no need to escape anything */
00229                ast_cdr_getvar(cdr, cur->name, &value, buf, sizeof(buf), 0, 1);
00230                LENGTHEN_BUF2(12);
00231                lensql2 += snprintf(sql2 + lensql2, sizesql2 - lensql2, "%s", value);
00232             } else {
00233                /* Although this is a char field, there are no special characters in the values for these fields */
00234                ast_cdr_getvar(cdr, cur->name, &value, buf, sizeof(buf), 0, 0);
00235                LENGTHEN_BUF2(30);
00236                lensql2 += snprintf(sql2 + lensql2, sizesql2 - lensql2, "'%s'", value);
00237             }
00238          } else {
00239             /* Arbitrary field, could be anything */
00240             ast_cdr_getvar(cdr, cur->name, &value, buf, sizeof(buf), 0, 0);
00241             if (strncmp(cur->type, "int", 3) == 0) {
00242                long long whatever;
00243                if (value && sscanf(value, "%lld", &whatever) == 1) {
00244                   LENGTHEN_BUF2(25);
00245                   lensql2 += snprintf(sql2 + lensql2, sizesql2 - lensql2, "%lld", whatever);
00246                } else {
00247                   LENGTHEN_BUF2(1);
00248                   lensql2 += snprintf(sql2 + lensql2, sizesql2 - lensql2, "0");
00249                }
00250             } else if (strncmp(cur->type, "float", 5) == 0) {
00251                long double whatever;
00252                if (value && sscanf(value, "%Lf", &whatever) == 1) {
00253                   LENGTHEN_BUF2(50);
00254                   lensql2 += snprintf(sql2 + lensql2, sizesql2 - lensql2, "%30Lf", whatever);
00255                } else {
00256                   LENGTHEN_BUF2(1);
00257                   lensql2 += snprintf(sql2 + lensql2, sizesql2 - lensql2, "0");
00258                }
00259             /* XXX Might want to handle dates, times, and other misc fields here XXX */
00260             } else {
00261                if (value)
00262                   PQescapeStringConn(conn, escapebuf, value, strlen(value), NULL);
00263                else
00264                   escapebuf[0] = '\0';
00265                LENGTHEN_BUF2(strlen(escapebuf) + 2);
00266                lensql2 += snprintf(sql2 + lensql2, sizesql2 - lensql2, "'%s'", escapebuf);
00267             }
00268          }
00269          LENGTHEN_BUF2(1);
00270          strcat(sql2 + lensql2, ",");
00271          lensql2++;
00272       }
00273       AST_RWLIST_UNLOCK(&psql_columns);
00274       LENGTHEN_BUF1(lensql2);
00275       sql[lensql - 1] = ')';
00276       sql2[lensql2 - 1] = ')';
00277       strcat(sql + lensql, sql2);
00278       ast_verb(11, "[%s]\n", sql);
00279 
00280       ast_debug(2, "inserting a CDR record.\n");
00281 
00282       /* Test to be sure we're still connected... */
00283       /* If we're connected, and connection is working, good. */
00284       /* Otherwise, attempt reconnect.  If it fails... sorry... */
00285       if (PQstatus(conn) == CONNECTION_OK) {
00286          connected = 1;
00287       } else {
00288          ast_log(LOG_ERROR, "Connection was lost... attempting to reconnect.\n");
00289          PQreset(conn);
00290          if (PQstatus(conn) == CONNECTION_OK) {
00291             ast_log(LOG_ERROR, "Connection reestablished.\n");
00292             connected = 1;
00293          } else {
00294             pgerror = PQerrorMessage(conn);
00295             ast_log(LOG_ERROR, "Unable to reconnect to database server %s. Calls will not be logged!\n", pghostname);
00296             ast_log(LOG_ERROR, "Reason: %s\n", pgerror);
00297             PQfinish(conn);
00298             conn = NULL;
00299             connected = 0;
00300             ast_mutex_unlock(&pgsql_lock);
00301             ast_free(sql);
00302             ast_free(sql2);
00303             return -1;
00304          }
00305       }
00306       result = PQexec(conn, sql);
00307       if (PQresultStatus(result) != PGRES_COMMAND_OK) {
00308          pgerror = PQresultErrorMessage(result);
00309          ast_log(LOG_ERROR, "Failed to insert call detail record into database!\n");
00310          ast_log(LOG_ERROR, "Reason: %s\n", pgerror);
00311          ast_log(LOG_ERROR, "Connection may have been lost... attempting to reconnect.\n");
00312          PQreset(conn);
00313          if (PQstatus(conn) == CONNECTION_OK) {
00314             ast_log(LOG_ERROR, "Connection reestablished.\n");
00315             connected = 1;
00316             PQclear(result);
00317             result = PQexec(conn, sql);
00318             if (PQresultStatus(result) != PGRES_COMMAND_OK) {
00319                pgerror = PQresultErrorMessage(result);
00320                ast_log(LOG_ERROR, "HARD ERROR!  Attempted reconnection failed.  DROPPING CALL RECORD!\n");
00321                ast_log(LOG_ERROR, "Reason: %s\n", pgerror);
00322             }
00323          }
00324          ast_mutex_unlock(&pgsql_lock);
00325          PQclear(result);
00326          ast_free(sql);
00327          ast_free(sql2);
00328          return -1;
00329       }
00330       PQclear(result);
00331       ast_free(sql);
00332       ast_free(sql2);
00333    }
00334    ast_mutex_unlock(&pgsql_lock);
00335    return 0;
00336 }

static int reload ( void   )  [static]

Definition at line 548 of file cdr_pgsql.c.

References config_module().

00549 {
00550    return config_module(1);
00551 }

static int unload_module ( void   )  [static]

Definition at line 338 of file cdr_pgsql.c.

References ast_cdr_unregister(), ast_free, AST_RWLIST_REMOVE_HEAD, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and columns::list.

00339 {
00340    struct columns *current;
00341    ast_cdr_unregister(name);
00342 
00343    /* Give all threads time to finish */
00344    usleep(1);
00345    PQfinish(conn);
00346 
00347    if (pghostname)
00348       ast_free(pghostname);
00349    if (pgdbname)
00350       ast_free(pgdbname);
00351    if (pgdbuser)
00352       ast_free(pgdbuser);
00353    if (pgpassword)
00354       ast_free(pgpassword);
00355    if (pgdbport)
00356       ast_free(pgdbport);
00357    if (table)
00358       ast_free(table);
00359 
00360    AST_RWLIST_WRLOCK(&psql_columns);
00361    while ((current = AST_RWLIST_REMOVE_HEAD(&psql_columns, list))) {
00362       ast_free(current);
00363    }
00364    AST_RWLIST_UNLOCK(&psql_columns);
00365 
00366    return 0;
00367 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "PostgreSQL CDR 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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload, } [static]

Definition at line 557 of file cdr_pgsql.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 557 of file cdr_pgsql.c.

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

Definition at line 56 of file cdr_pgsql.c.

PGconn* conn = NULL [static]

Definition at line 63 of file cdr_pgsql.c.

int connected = 0 [static]

Definition at line 58 of file cdr_pgsql.c.

Referenced by aji_initialize().

int maxsize = 512 [static]

Definition at line 59 of file cdr_pgsql.c.

int maxsize2 = 512 [static]

Definition at line 59 of file cdr_pgsql.c.

char* name = "pgsql" [static]

Definition at line 55 of file cdr_pgsql.c.

char * pgdbname = NULL [static]

Definition at line 57 of file cdr_pgsql.c.

char * pgdbport = NULL [static]

Definition at line 57 of file cdr_pgsql.c.

char * pgdbuser = NULL [static]

Definition at line 57 of file cdr_pgsql.c.

char* pghostname = NULL [static]

Definition at line 57 of file cdr_pgsql.c.

char * pgpassword = NULL [static]

Definition at line 57 of file cdr_pgsql.c.

ast_mutex_t pgsql_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static]

Definition at line 61 of file cdr_pgsql.c.

Referenced by config_pgsql(), destroy_pgsql(), parse_config(), pgsql_log(), realtime_multi_pgsql(), realtime_pgsql(), require_pgsql(), store_pgsql(), unload_module(), and update_pgsql().

char * table = NULL [static]

Definition at line 57 of file cdr_pgsql.c.


Generated on Fri Jul 24 00:41:19 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7