Mon Mar 31 07:39:20 2008

Asterisk developer's documentation


cdr_pgsql_ng.c File Reference

Advanced PostgreSQL CDR logger. More...

#include <asterisk.h>
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <pgsql/libpq-fe.h>
#include <asterisk/config.h>
#include <asterisk/options.h>
#include <asterisk/channel.h>
#include <asterisk/cdr.h>
#include <asterisk/module.h>
#include <asterisk/logger.h>

Include dependency graph for cdr_pgsql_ng.c:

Go to the source code of this file.

Data Structures

struct  query

Defines

#define AST_MODULE   "cdr_pgsql_ng"
#define DATE_FORMAT   "%Y-%m-%d %T"

Enumerations

enum  {
  CFG_HOSTNAME, CFG_DBNAME, CFG_TABLE, CFG_DBPORT,
  CFG_USER, CFG_PASSWORD, CFG_MAX
}

Functions

static AST_LIST_HEAD_STATIC (queries, query)
 AST_MODULE_INFO_STANDARD (ASTERISK_GPL_KEY,"PostgreSQL CDR Backend new generation")
 AST_MUTEX_DEFINE_STATIC (pgsql_lock)
static int cdr_pgsql_connect (void)
static char * cdr_pgsql_read_config (struct ast_config *cfg, const char const *section, const char *option, char *def, const char *log)
static int database_first_connect (struct ast_config *cfg)
static int load_module (void)
static int pgsql_log (struct ast_cdr *cdr)
static int pgsql_test_connection (void)
static int reload (void)
static int unload_module (void)

Variables

static char * config [CFG_MAX]
static char * config_file = "cdr_pgsql_ng.conf"
static PGconn * conn
static int connected = 0
static char * insertcmd = NULL
static const char * insertcmd_in
static char * name = "pgsql_ng"
static PGresult * result
static char * tdesc = "PostgreSQL CDR Backend new generation"


Detailed Description

Advanced PostgreSQL CDR logger.

Author:
Denis Smirnov <ds@seiros.ru>
See also

Definition in file cdr_pgsql_ng.c.


Define Documentation

#define AST_MODULE   "cdr_pgsql_ng"

Definition at line 15 of file cdr_pgsql_ng.c.

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

Definition at line 36 of file cdr_pgsql_ng.c.


Enumeration Type Documentation

anonymous enum

Enumerator:
CFG_HOSTNAME 
CFG_DBNAME 
CFG_TABLE 
CFG_DBPORT 
CFG_USER 
CFG_PASSWORD 
CFG_MAX 

Definition at line 65 of file cdr_pgsql_ng.c.

00065      {
00066    CFG_HOSTNAME,
00067    CFG_DBNAME,
00068    CFG_TABLE,
00069    CFG_DBPORT,
00070    CFG_USER,
00071    CFG_PASSWORD,
00072    CFG_MAX
00073 };


Function Documentation

static AST_LIST_HEAD_STATIC ( queries  ,
query   
) [static]

AST_MODULE_INFO_STANDARD ( ASTERISK_GPL_KEY  ,
"PostgreSQL CDR Backend new generation"   
)

AST_MUTEX_DEFINE_STATIC ( pgsql_lock   ) 

static int cdr_pgsql_connect ( void   )  [static]

Definition at line 77 of file cdr_pgsql_ng.c.

References ast_log(), CFG_DBNAME, CFG_DBPORT, CFG_HOSTNAME, CFG_PASSWORD, CFG_USER, config, conn, connected, insertcmd, LOG_DEBUG, LOG_ERROR, option_debug, and result.

Referenced by database_first_connect(), and pgsql_test_connection().

00078 {
00079    char *pgerror;
00080 
00081    conn = PQsetdbLogin(config[CFG_HOSTNAME], config[CFG_DBPORT], NULL, NULL, config[CFG_DBNAME], config[CFG_USER], config[CFG_PASSWORD]);
00082    if (PQstatus(conn) != CONNECTION_BAD) {
00083       if (option_debug)
00084          ast_log(LOG_DEBUG, "Successfully connected to PostgreSQL database.\n");
00085       connected = 1;
00086    } else {
00087       pgerror = PQerrorMessage(conn);
00088       ast_log(LOG_ERROR, "Unable to connect to database server\n");
00089       ast_log(LOG_ERROR, "Reason: %s\n", pgerror);
00090       return -1;
00091    }
00092    result = PQprepare(conn, "", insertcmd, 16, NULL);
00093    if (PQresultStatus(result) != PGRES_COMMAND_OK) {
00094       char *pgerror = PQresultErrorMessage(result);
00095       ast_log(LOG_ERROR, "Can't prepare insert statement!\n");
00096       ast_log(LOG_ERROR, "Reason: %s\n", pgerror);
00097    }
00098    return 0;
00099 }

static char* cdr_pgsql_read_config ( struct ast_config cfg,
const char const *  section,
const char *  option,
char *  def,
const char *  log 
) [static]

Definition at line 175 of file cdr_pgsql_ng.c.

References ast_log(), ast_variable_retrieve(), LOG_WARNING, S_OR, and strdup.

Referenced by database_first_connect().

00176 {
00177    const char *tmp = ast_variable_retrieve(cfg, section, option);
00178    if (tmp == NULL) {
00179       ast_log(LOG_WARNING, "%s not specified, assuming %s\n", log, S_OR(def, "blank"));
00180       /* This needed, because memory would be freed */
00181       return strdup(def);
00182    }
00183    return strdup(tmp);
00184 }

static int database_first_connect ( struct ast_config cfg  )  [static]

Definition at line 186 of file cdr_pgsql_ng.c.

References asprintf, ast_log(), ast_variable_browse(), cdr_pgsql_connect(), cdr_pgsql_read_config(), CFG_DBNAME, CFG_DBPORT, CFG_HOSTNAME, CFG_MAX, CFG_PASSWORD, CFG_TABLE, CFG_USER, config, free, insertcmd, insertcmd_in, LOG_DEBUG, LOG_ERROR, LOG_WARNING, and option_debug.

Referenced by load_module(), and reload().

00187 {
00188    int res = 0, i;
00189 
00190    for (i = 0; i < CFG_MAX; i++)
00191       config[i] = NULL;
00192 
00193    if (ast_variable_browse(cfg, "global") == NULL) {
00194       /* nothing configured */
00195       ast_log(LOG_WARNING, "cdr_pgsql not configured, exiting\n");
00196       return 0;
00197    }
00198 
00199    config[CFG_HOSTNAME] = cdr_pgsql_read_config(cfg, "global", "hostname", "", "PostgreSQL server hostname");
00200    config[CFG_DBNAME] = cdr_pgsql_read_config(cfg, "global", "dbname", "asterisk", "PostgreSQL database");
00201    config[CFG_USER] = cdr_pgsql_read_config(cfg, "global", "dbuser", "asterisk", "PostgreSQL database user");
00202    config[CFG_PASSWORD] = cdr_pgsql_read_config(cfg, "global", "password", "", "PostgreSQL database password");
00203    config[CFG_DBPORT] = cdr_pgsql_read_config(cfg, "global", "port", "5432", "PostgreSQL database port");
00204    config[CFG_TABLE] = cdr_pgsql_read_config(cfg, "global", "table", "cdr", "CDR table");
00205 
00206    for (i = 0; i < CFG_MAX; i++) {
00207       if (config[i] == NULL) {
00208          ast_log(LOG_ERROR, "Out of memory error\n");
00209          for (i = 0; i < CFG_MAX; i++)
00210             if (config[i]) {
00211                free(config[i]);
00212                config[i] = 0;
00213             }
00214          return -1;
00215       }
00216    }
00217 
00218    if (option_debug) {
00219       ast_log(LOG_DEBUG, "got hostname of %s\ngot port of %s\ngot user of %s\ngot dbname of %s\ngot password of %s\ngot sql table name of %s\n", config[CFG_HOSTNAME], config[CFG_DBPORT],
00220             config[CFG_USER], config[CFG_DBNAME], config[CFG_PASSWORD], config[CFG_TABLE]);
00221    }
00222    if (insertcmd)
00223       free(insertcmd);
00224 
00225    asprintf(&insertcmd, insertcmd_in, config[CFG_TABLE]);
00226 
00227    cdr_pgsql_connect();
00228    return res;
00229 }

static int load_module ( void   )  [static]

Definition at line 231 of file cdr_pgsql_ng.c.

References ast_cdr_register(), ast_config_destroy(), ast_config_load(), ast_log(), config_file, database_first_connect(), LOG_ERROR, LOG_WARNING, name, pgsql_log(), and tdesc.

00232 {
00233    struct ast_config *cfg;
00234    int res;
00235 
00236    cfg = ast_config_load(config_file);
00237    if (!cfg) {
00238       ast_log(LOG_WARNING, "Unable to load config for PostgreSQL CDR's: %s\n", config_file);
00239       return 0;
00240    }
00241 
00242    res = database_first_connect(cfg);
00243    ast_config_destroy(cfg);
00244 
00245    res = ast_cdr_register(name, tdesc, pgsql_log);
00246    if (res)
00247       ast_log(LOG_ERROR, "Unable to register PGSQL CDR handling\n");
00248    return res;
00249 }

static int pgsql_log ( struct ast_cdr cdr  )  [static]

Return SQL INSERT string with CDR data

Definition at line 129 of file cdr_pgsql_ng.c.

References ast_cdr::accountcode, ast_cdr::amaflags, amaflags, ast_cdr_disp2str(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_cdr::billsec, ast_cdr::channel, ast_cdr::clid, conn, DATE_FORMAT, ast_cdr::dcontext, ast_cdr::disposition, ast_cdr::dst, ast_cdr::dstchannel, ast_cdr::duration, ast_cdr::lastapp, ast_cdr::lastdata, localtime_r, LOG_ERROR, pgsql_test_connection(), result, ast_cdr::src, ast_cdr::start, ast_cdr::uniqueid, and ast_cdr::userfield.

00130 {
00131    int i;
00132    struct tm tm;
00133    char timestr[128];
00134    char duration[64];
00135    char billsec[64];
00136    char amaflags[64];
00137    char *params[16] = {
00138       timestr,
00139       cdr->clid,
00140       cdr->src,
00141       cdr->dst,
00142       cdr->dcontext,
00143       cdr->channel,
00144       cdr->dstchannel,
00145       cdr->lastapp,
00146       cdr->lastdata,
00147       duration,
00148       billsec,
00149       ast_cdr_disp2str(cdr->disposition),
00150       amaflags,
00151       cdr->accountcode,
00152       cdr->uniqueid,
00153       cdr->userfield
00154    };
00155 
00156    localtime_r(&cdr->start.tv_sec, &tm);
00157    strftime(timestr, sizeof(timestr), DATE_FORMAT, &tm);
00158 
00159    snprintf(duration, sizeof(duration), "%ld", cdr->duration);
00160    snprintf(billsec, sizeof(billsec), "%ld", cdr->billsec);
00161    snprintf(amaflags, sizeof(amaflags), "%ld", cdr->amaflags);
00162 
00163    ast_mutex_lock(&pgsql_lock);
00164    pgsql_test_connection();
00165    result = PQexecPrepared(conn, "", 16, (const char *const *) params, NULL, NULL, 0);
00166    if (PQresultStatus(result) != PGRES_COMMAND_OK) {
00167       char *pgerror = PQresultErrorMessage(result);
00168       ast_log(LOG_ERROR, "Failed to insert call detail record into database!\n");
00169       ast_log(LOG_ERROR, "Reason: %s\n", pgerror);
00170    }
00171    ast_mutex_unlock(&pgsql_lock);
00172    return 0;
00173 }

static int pgsql_test_connection ( void   )  [static]

Definition at line 101 of file cdr_pgsql_ng.c.

References ast_log(), cdr_pgsql_connect(), conn, connected, and LOG_ERROR.

Referenced by pgsql_log().

00102 {
00103    char *pgerror;
00104    if (!connected) {
00105       /* Trying to reconnect to database if not connected */
00106       if (cdr_pgsql_connect() == -1)
00107          return -1;
00108    }
00109 
00110    /* Test to be sure we're still connected... */
00111    /* If we're connected, and connection is working, good. */
00112    /* Otherwise, attempt reconnect.  If it fails... sorry... */
00113    if (PQstatus(conn) != CONNECTION_OK) {
00114       ast_log(LOG_ERROR, "Connection was lost... attempting to reconnect.\n");
00115       PQreset(conn);
00116       if (PQstatus(conn) == CONNECTION_OK) {
00117          ast_log(LOG_ERROR, "Connection reestablished.\n");
00118       } else {
00119          pgerror = PQerrorMessage(conn);
00120          ast_log(LOG_ERROR, "Unable to reconnect to database server\n");
00121          ast_log(LOG_ERROR, "Reason: %s\n", pgerror);
00122          return -1;
00123       }
00124    }
00125    return 0;
00126 }

static int reload ( void   )  [static]

Definition at line 272 of file cdr_pgsql_ng.c.

References ast_config_destroy(), ast_config_load(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), CFG_MAX, config, config_file, conn, database_first_connect(), free, LOG_ERROR, and LOG_WARNING.

00273 {
00274    struct ast_config *cfg;
00275    int i;
00276 
00277    cfg = ast_config_load(config_file);
00278    if (!cfg) {
00279       ast_log(LOG_WARNING, "Unable to load config for PostgreSQL CDR's: %s\n", config_file);
00280       return -1;
00281    }
00282 
00283    ast_mutex_lock(&pgsql_lock);
00284    /* Free connection and old config */
00285    if (conn)
00286       PQfinish(conn);
00287 
00288    for (i = 0; i < CFG_MAX; i++)
00289       if (config[i])
00290          free(config[i]);
00291 
00292    if (database_first_connect(cfg) != 0)
00293       ast_log(LOG_ERROR, "Error in reloading config, data would be cached\n");
00294    ast_config_destroy(cfg);
00295 
00296    ast_mutex_unlock(&pgsql_lock);
00297    return 0;
00298 }

static int unload_module ( void   )  [static]

Definition at line 251 of file cdr_pgsql_ng.c.

References ast_cdr_unregister(), ast_mutex_lock(), ast_mutex_unlock(), CFG_MAX, config, conn, free, insertcmd, and name.

00252 {
00253    unsigned int i;
00254    /* CDR module must be unregistered before unset variables */
00255    ast_cdr_unregister(name);
00256    /* XXX: there can be race */
00257    ast_mutex_lock(&pgsql_lock);
00258    if (conn)
00259       PQfinish(conn);
00260    /* Free config memory there */
00261    for (i = 0; i < CFG_MAX; i++)
00262       if (config[i])
00263          free(config[i]);
00264 
00265    if (insertcmd)
00266       free(insertcmd);
00267 
00268    ast_mutex_unlock(&pgsql_lock);
00269    return 0;
00270 }


Variable Documentation

char* config[CFG_MAX] [static]

Definition at line 75 of file cdr_pgsql_ng.c.

char* config_file = "cdr_pgsql_ng.conf" [static]

Definition at line 49 of file cdr_pgsql_ng.c.

Referenced by load_module(), and reload().

PGconn* conn [static]

Definition at line 54 of file cdr_pgsql_ng.c.

int connected = 0 [static]

Definition at line 50 of file cdr_pgsql_ng.c.

char* insertcmd = NULL [static]

Definition at line 42 of file cdr_pgsql_ng.c.

Referenced by cdr_pgsql_connect(), database_first_connect(), and unload_module().

const char* insertcmd_in [static]

Initial value:

 "INSERT INTO %s "
   "(calldate,clid,src,dst,dcontext,channel,dstchannel,"
   "lastapp,lastdata,duration,billsec,disposition,amaflags," "accountcode,uniqueid,userfield) VALUES ($1, $2, $3, $4, $5," "$6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16)"

Definition at line 43 of file cdr_pgsql_ng.c.

Referenced by database_first_connect().

char* name = "pgsql_ng" [static]

Definition at line 48 of file cdr_pgsql_ng.c.

PGresult* result [static]

Definition at line 55 of file cdr_pgsql_ng.c.

Referenced by __ast_string_field_alloc_space(), ast_app_getdata(), ast_build_string(), ast_build_string_va(), ast_config_internal_load(), ast_config_load(), ast_config_load_with_comments(), ast_gethostbyname(), ast_privacy_check(), ast_rtp_lookup_pt(), ast_speech_results_free(), ast_speech_results_get(), astman_verify_session_readpermissions(), astman_verify_session_writepermissions(), cdr_pgsql_connect(), check_sip_domain(), complete_sip_peer(), complete_sip_user(), complete_skinny_reset(), config_mysql(), config_pgsql(), detzcode(), detzcode64(), dundi_lookup(), dundi_lookup_internal(), find_result(), get_member_status(), gmtsub(), handle_logger_reload(), httpstatus_callback(), localsub(), mgcpsock_read(), MYSQL_exec(), ogg_vorbis_open(), osp_check_destination(), osp_lookup(), osp_next(), osplookup_exec(), ospnext_exec(), pgsql_log(), radius_log(), read_samples(), realtime_multi_mysql(), realtime_multi_pgsql(), realtime_mysql(), realtime_pgsql(), speech_grammar(), speech_read(), speech_score(), speech_text(), static_callback(), tmcomp(), and update_pgsql().

char* tdesc = "PostgreSQL CDR Backend new generation" [static]

Definition at line 47 of file cdr_pgsql_ng.c.


Generated on Mon Mar 31 07:39:20 2008 for Asterisk - the Open Source PBX by  doxygen 1.5.1