#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" |
See also
Definition in file cdr_pgsql_ng.c.
#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.
anonymous enum |
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 };
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 }
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(), reload(), and smdi_load().
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_channel_spy_read_frame(), 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(), dundi_lookup(), dundi_lookup_internal(), find_result(), get_member_status(), httpstatus_callback(), 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.