Asterisk - The Open Source Telephony Project  18.5.0
Data Structures | Macros | Functions | Variables
cdr_pgsql.c File Reference

PostgreSQL CDR logger. More...

#include "asterisk.h"
#include <libpq-fe.h>
#include "asterisk/config.h"
#include "asterisk/channel.h"
#include "asterisk/cdr.h"
#include "asterisk/cli.h"
#include "asterisk/module.h"
Include dependency graph for cdr_pgsql.c:

Go to the source code of this file.

Data Structures

struct  columns
 
struct  psql_columns
 

Macros

#define DATE_FORMAT   "'%Y-%m-%d %T'"
 
#define LENGTHEN_BUF(size, var_sql)
 
#define LENGTHEN_BUF1(size)   LENGTHEN_BUF(size, sql);
 
#define LENGTHEN_BUF2(size)   LENGTHEN_BUF(size, sql2);
 
#define PGSQL_MIN_VERSION_SCHEMA   70300
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static int config_module (int reload)
 
static void empty_columns (void)
 
static char * handle_cdr_pgsql_status (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Handle the CLI command cdr show pgsql status. More...
 
static int load_module (void)
 
static int pgsql_log (struct ast_cdr *cdr)
 
static void pgsql_reconnect (void)
 
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 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 = "30ef0c93b36035ec78c9cfd712d36d9b" , .support_level = AST_MODULE_SUPPORT_EXTENDED, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CDR_DRIVER, .requires = "cdr", }
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static struct ast_cli_entry cdr_pgsql_status_cli []
 
static const char config [] = "cdr_pgsql.conf"
 
static PGconn * conn = NULL
 
static time_t connect_time = 0
 
static int connected = 0
 
static char * encoding
 
static int maxsize = 512
 
static int maxsize2 = 512
 
static const char name [] = "pgsql"
 
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_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
 
static struct psql_columns psql_columns = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }
 
static int records
 
static char * table
 
static int totalrecords = 0
 
static char * tz
 

Detailed Description

PostgreSQL CDR logger.

Author
Matthew D. Hardeman mhard.nosp@m.emn@.nosp@m.paper.nosp@m.soft.nosp@m..com PostgreSQL http://www.postgresql.org/

See also

Definition in file cdr_pgsql.c.

Macro Definition Documentation

◆ DATE_FORMAT

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

Definition at line 60 of file cdr_pgsql.c.

Referenced by pgsql_log().

◆ LENGTHEN_BUF

#define LENGTHEN_BUF (   size,
  var_sql 
)

Definition at line 104 of file cdr_pgsql.c.

◆ LENGTHEN_BUF1

#define LENGTHEN_BUF1 (   size)    LENGTHEN_BUF(size, sql);

Definition at line 119 of file cdr_pgsql.c.

Referenced by pgsql_log().

◆ LENGTHEN_BUF2

#define LENGTHEN_BUF2 (   size)    LENGTHEN_BUF(size, sql2);

Definition at line 121 of file cdr_pgsql.c.

Referenced by pgsql_log().

◆ PGSQL_MIN_VERSION_SCHEMA

#define PGSQL_MIN_VERSION_SCHEMA   70300

Definition at line 62 of file cdr_pgsql.c.

Referenced by config_module().

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 810 of file cdr_pgsql.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 810 of file cdr_pgsql.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 810 of file cdr_pgsql.c.

◆ config_module()

static int config_module ( int  reload)
static

Definition at line 524 of file cdr_pgsql.c.

References ast_alloca, ast_calloc, ast_config_destroy(), ast_config_load, ast_debug, ast_free, ast_log, AST_MODULE_LOAD_DECLINE, ast_mutex_lock, ast_mutex_unlock, AST_RWLIST_INSERT_TAIL, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_strdup, ast_strdupa, ast_strlen_zero, ast_variable_browse(), ast_variable_retrieve(), config, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, conn, connect_time, connected, DEBUG_ATLEAST, empty_columns(), encoding, columns::hasdefault, columns::len, columns::list, LOG_DEBUG, LOG_ERROR, LOG_NOTICE, LOG_WARNING, columns::name, columns::notnull, NULL, pgappname, pgdbname, pgdbport, pgdbuser, pghostname, pgpassword, pgsql_lock, PGSQL_MIN_VERSION_SCHEMA, pgsql_reconnect(), records, result, table, tmp(), columns::type, tz, unload_module(), and version.

Referenced by load_module(), and reload().

525 {
526  char *pgerror;
527  struct columns *cur;
528  PGresult *result;
529  const char *tmp;
530  struct ast_config *cfg;
531  struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
532 
533  if ((cfg = ast_config_load(config, config_flags)) == NULL || cfg == CONFIG_STATUS_FILEINVALID) {
534  ast_log(LOG_WARNING, "Unable to load config for PostgreSQL CDR's: %s\n", config);
535  return -1;
536  } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
537  return 0;
538  }
539 
541 
542  if (!ast_variable_browse(cfg, "global")) {
543  ast_config_destroy(cfg);
545  ast_log(LOG_NOTICE, "cdr_pgsql configuration contains no global section, skipping module %s.\n",
546  reload ? "reload" : "load");
547  return -1;
548  }
549 
550  if (!(tmp = ast_variable_retrieve(cfg, "global", "hostname"))) {
551  ast_log(LOG_WARNING, "PostgreSQL server hostname not specified. Assuming unix socket connection\n");
552  tmp = ""; /* connect via UNIX-socket by default */
553  }
554 
556  if (!(pghostname = ast_strdup(tmp))) {
557  ast_config_destroy(cfg);
559  return -1;
560  }
561 
562  if (!(tmp = ast_variable_retrieve(cfg, "global", "dbname"))) {
563  ast_log(LOG_WARNING, "PostgreSQL database not specified. Assuming asterisk\n");
564  tmp = "asteriskcdrdb";
565  }
566 
568  if (!(pgdbname = ast_strdup(tmp))) {
569  ast_config_destroy(cfg);
571  return -1;
572  }
573 
574  if (!(tmp = ast_variable_retrieve(cfg, "global", "user"))) {
575  ast_log(LOG_WARNING, "PostgreSQL database user not specified. Assuming asterisk\n");
576  tmp = "asterisk";
577  }
578 
580  if (!(pgdbuser = ast_strdup(tmp))) {
581  ast_config_destroy(cfg);
583  return -1;
584  }
585 
586  if (!(tmp = ast_variable_retrieve(cfg, "global", "appname"))) {
587  tmp = "";
588  }
589 
591  if (!(pgappname = ast_strdup(tmp))) {
592  ast_config_destroy(cfg);
594  return -1;
595  }
596 
597 
598  if (!(tmp = ast_variable_retrieve(cfg, "global", "password"))) {
599  ast_log(LOG_WARNING, "PostgreSQL database password not specified. Assuming blank\n");
600  tmp = "";
601  }
602 
604  if (!(pgpassword = ast_strdup(tmp))) {
605  ast_config_destroy(cfg);
607  return -1;
608  }
609 
610  if (!(tmp = ast_variable_retrieve(cfg, "global", "port"))) {
611  ast_log(LOG_WARNING, "PostgreSQL database port not specified. Using default 5432.\n");
612  tmp = "5432";
613  }
614 
616  if (!(pgdbport = ast_strdup(tmp))) {
617  ast_config_destroy(cfg);
619  return -1;
620  }
621 
622  if (!(tmp = ast_variable_retrieve(cfg, "global", "table"))) {
623  ast_log(LOG_WARNING, "CDR table not specified. Assuming cdr\n");
624  tmp = "cdr";
625  }
626 
627  ast_free(table);
628  if (!(table = ast_strdup(tmp))) {
629  ast_config_destroy(cfg);
631  return -1;
632  }
633 
634  if (!(tmp = ast_variable_retrieve(cfg, "global", "encoding"))) {
635  ast_log(LOG_WARNING, "Encoding not specified. Assuming LATIN9\n");
636  tmp = "LATIN9";
637  }
638 
640  if (!(encoding = ast_strdup(tmp))) {
641  ast_config_destroy(cfg);
643  return -1;
644  }
645 
646  if (!(tmp = ast_variable_retrieve(cfg, "global", "timezone"))) {
647  tmp = "";
648  }
649 
650  ast_free(tz);
651  tz = NULL;
652 
653  if (!ast_strlen_zero(tmp) && !(tz = ast_strdup(tmp))) {
654  ast_config_destroy(cfg);
656  return -1;
657  }
658 
659  if (DEBUG_ATLEAST(1)) {
661  ast_log(LOG_DEBUG, "using default unix socket\n");
662  } else {
663  ast_log(LOG_DEBUG, "got hostname of %s\n", pghostname);
664  }
665  ast_log(LOG_DEBUG, "got port of %s\n", pgdbport);
666  ast_log(LOG_DEBUG, "got user of %s\n", pgdbuser);
667  ast_log(LOG_DEBUG, "got dbname of %s\n", pgdbname);
668  ast_log(LOG_DEBUG, "got password of %s\n", pgpassword);
669  ast_log(LOG_DEBUG, "got application name of %s\n", pgappname);
670  ast_log(LOG_DEBUG, "got sql table name of %s\n", table);
671  ast_log(LOG_DEBUG, "got encoding of %s\n", encoding);
672  ast_log(LOG_DEBUG, "got timezone of %s\n", tz);
673  }
674 
675  pgsql_reconnect();
676 
677  if (PQstatus(conn) != CONNECTION_BAD) {
678  char sqlcmd[768];
679  char *fname, *ftype, *flen, *fnotnull, *fdef;
680  int i, rows, version;
681  ast_debug(1, "Successfully connected to PostgreSQL database.\n");
682  connected = 1;
683  connect_time = time(NULL);
684  records = 0;
685  if (PQsetClientEncoding(conn, encoding)) {
686 #ifdef HAVE_PGSQL_pg_encoding_to_char
687  ast_log(LOG_WARNING, "Failed to set encoding to '%s'. Encoding set to default '%s'\n", encoding, pg_encoding_to_char(PQclientEncoding(conn)));
688 #else
689  ast_log(LOG_WARNING, "Failed to set encoding to '%s'. Encoding set to default.\n", encoding);
690 #endif
691  }
692  version = PQserverVersion(conn);
693 
694  if (version >= PGSQL_MIN_VERSION_SCHEMA) {
695  char *schemaname, *tablename, *tmp_schemaname, *tmp_tablename;
696  if (strchr(table, '.')) {
697  tmp_schemaname = ast_strdupa(table);
698  tmp_tablename = strchr(tmp_schemaname, '.');
699  *tmp_tablename++ = '\0';
700  } else {
701  tmp_schemaname = "";
702  tmp_tablename = table;
703  }
704  tablename = ast_alloca(strlen(tmp_tablename) * 2 + 1);
705  PQescapeStringConn(conn, tablename, tmp_tablename, strlen(tmp_tablename), NULL);
706 
707  schemaname = ast_alloca(strlen(tmp_schemaname) * 2 + 1);
708  PQescapeStringConn(conn, schemaname, tmp_schemaname, strlen(tmp_schemaname), NULL);
709 
710  snprintf(sqlcmd, sizeof(sqlcmd), "SELECT a.attname, t.typname, a.attlen, a.attnotnull, pg_catalog.pg_get_expr(d.adbin, d.adrelid) adsrc, a.atttypmod FROM (((pg_catalog.pg_class c INNER JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace AND c.relname = '%s' AND n.nspname = %s%s%s) INNER JOIN pg_catalog.pg_attribute a ON (NOT a.attisdropped) AND a.attnum > 0 AND a.attrelid = c.oid) INNER JOIN pg_catalog.pg_type t ON t.oid = a.atttypid) LEFT OUTER JOIN pg_attrdef d ON a.atthasdef AND d.adrelid = a.attrelid AND d.adnum = a.attnum ORDER BY n.nspname, c.relname, attnum",
711  tablename,
712  ast_strlen_zero(schemaname) ? "" : "'", ast_strlen_zero(schemaname) ? "current_schema()" : schemaname, ast_strlen_zero(schemaname) ? "" : "'");
713  } else {
714  snprintf(sqlcmd, sizeof(sqlcmd), "SELECT a.attname, t.typname, a.attlen, a.attnotnull, d.adsrc, a.atttypmod 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", table);
715  }
716  /* Query the columns */
717  result = PQexec(conn, sqlcmd);
718  if (PQresultStatus(result) != PGRES_TUPLES_OK) {
719  pgerror = PQresultErrorMessage(result);
720  ast_log(LOG_ERROR, "Failed to query database columns: %s\n", pgerror);
721  PQclear(result);
722  unload_module();
725  }
726 
727  rows = PQntuples(result);
728  if (rows == 0) {
729  ast_log(LOG_ERROR, "cdr_pgsql: Failed to query database columns. No columns found, does the table exist?\n");
730  PQclear(result);
731  unload_module();
734  }
735 
736  /* Clear out the columns list. */
737  empty_columns();
738 
739  for (i = 0; i < rows; i++) {
740  fname = PQgetvalue(result, i, 0);
741  ftype = PQgetvalue(result, i, 1);
742  flen = PQgetvalue(result, i, 2);
743  fnotnull = PQgetvalue(result, i, 3);
744  fdef = PQgetvalue(result, i, 4);
745  if (atoi(flen) == -1) {
746  /* For varchar columns, the maximum length is encoded in a different field */
747  flen = PQgetvalue(result, i, 5);
748  }
749 
750  cur = ast_calloc(1, sizeof(*cur) + strlen(fname) + strlen(ftype) + 2);
751  if (cur) {
752  sscanf(flen, "%30d", &cur->len);
753  cur->name = (char *)cur + sizeof(*cur);
754  cur->type = (char *)cur + sizeof(*cur) + strlen(fname) + 1;
755  strcpy(cur->name, fname);
756  strcpy(cur->type, ftype);
757  if (*fnotnull == 't') {
758  cur->notnull = 1;
759  } else {
760  cur->notnull = 0;
761  }
762  if (!ast_strlen_zero(fdef)) {
763  cur->hasdefault = 1;
764  } else {
765  cur->hasdefault = 0;
766  }
770  }
771  }
772  PQclear(result);
773  } else {
774  pgerror = PQerrorMessage(conn);
775  ast_log(LOG_ERROR, "Unable to connect to database server %s. CALLS WILL NOT BE LOGGED!!\n", pghostname);
776  ast_log(LOG_ERROR, "Reason: %s\n", pgerror);
777  connected = 0;
778  PQfinish(conn);
779  conn = NULL;
780  }
781 
782  ast_config_destroy(cfg);
783 
785  return 0;
786 }
unsigned int hasdefault
Definition: cdr_pgsql.c:98
static char * pgpassword
Definition: cdr_pgsql.c:70
static char * table
Definition: cdr_pgsql.c:73
static PGconn * conn
Definition: cdr_pgsql.c:91
static const char config[]
Definition: cdr_pgsql.c:65
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1216
static ast_mutex_t pgsql_lock
Definition: cdr_pgsql.c:89
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
#define LOG_WARNING
Definition: logger.h:274
#define CONFIG_STATUS_FILEINVALID
#define PGSQL_MIN_VERSION_SCHEMA
Definition: cdr_pgsql.c:62
static int tmp()
Definition: bt_open.c:389
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
#define ast_mutex_lock(a)
Definition: lock.h:187
static char * pgappname
Definition: cdr_pgsql.c:71
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
#define LOG_DEBUG
Definition: logger.h:241
#define ast_strlen_zero(foo)
Definition: strings.h:52
static char * pgdbname
Definition: cdr_pgsql.c:68
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#define ast_config_load(filename, flags)
Load a config file.
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: extconf.c:1290
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
#define CONFIG_STATUS_FILEUNCHANGED
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:290
#define LOG_ERROR
Definition: logger.h:285
static int reload(void)
Definition: cdr_pgsql.c:798
static char * tz
Definition: cdr_pgsql.c:75
#define LOG_NOTICE
Definition: logger.h:263
static time_t connect_time
Definition: cdr_pgsql.c:80
static char version[AST_MAX_EXTENSION]
Definition: chan_ooh323.c:391
#define ast_free(a)
Definition: astmm.h:182
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
static char * pgdbport
Definition: cdr_pgsql.c:72
Structure used to handle boolean flags.
Definition: utils.h:199
static char * pghostname
Definition: cdr_pgsql.c:67
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
Definition: main/config.c:694
#define AST_RWLIST_INSERT_TAIL
Definition: linkedlists.h:740
unsigned int notnull
Definition: cdr_pgsql.c:97
static PGresult * result
Definition: cel_pgsql.c:88
static char * pgdbuser
Definition: cdr_pgsql.c:69
static int connected
Definition: cdr_pgsql.c:77
static int unload_module(void)
Definition: cdr_pgsql.c:497
static char * encoding
Definition: cdr_pgsql.c:74
#define DEBUG_ATLEAST(level)
Definition: logger.h:441
static void pgsql_reconnect(void)
Definition: cdr_pgsql.c:174
static void empty_columns(void)
Definition: cdr_pgsql.c:486
static int records
Definition: cdr_pgsql.c:82
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ empty_columns()

static void empty_columns ( void  )
static

Definition at line 486 of file cdr_pgsql.c.

References ast_free, AST_RWLIST_REMOVE_HEAD, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and columns::list.

Referenced by config_module(), and unload_module().

487 {
488  struct columns *current;
490  while ((current = AST_RWLIST_REMOVE_HEAD(&psql_columns, list))) {
491  ast_free(current);
492  }
494 
495 }
struct columns::@8 list
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
#define ast_free(a)
Definition: astmm.h:182
#define AST_RWLIST_REMOVE_HEAD
Definition: linkedlists.h:843

◆ handle_cdr_pgsql_status()

static char * handle_cdr_pgsql_status ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Handle the CLI command cdr show pgsql status.

Definition at line 125 of file cdr_pgsql.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli(), ast_cli_print_timestr_fromseconds(), buf, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, connect_time, connected, ast_cli_args::fd, NULL, pgdbname, pgdbport, pgdbuser, pghostname, records, status, table, totalrecords, and ast_cli_entry::usage.

126 {
127  switch (cmd) {
128  case CLI_INIT:
129  e->command = "cdr show pgsql status";
130  e->usage =
131  "Usage: cdr show pgsql status\n"
132  " Shows current connection status for cdr_pgsql\n";
133  return NULL;
134  case CLI_GENERATE:
135  return NULL;
136  }
137 
138  if (a->argc != e->args)
139  return CLI_SHOWUSAGE;
140 
141  if (connected) {
142  char status[256];
143  char status2[100] = "";
144  char buf[362]; /* 256+100+" for "+NULL */
145  int ctime = time(NULL) - connect_time;
146 
147  if (pgdbport) {
148  snprintf(status, 255, "Connected to %s@%s, port %s", pgdbname, pghostname, pgdbport);
149  } else {
150  snprintf(status, 255, "Connected to %s@%s", pgdbname, pghostname);
151  }
152 
153  if (pgdbuser && *pgdbuser) {
154  snprintf(status2, 99, " with username %s", pgdbuser);
155  }
156  if (table && *table) {
157  snprintf(status2, 99, " using table %s", table);
158  }
159 
160  snprintf(buf, sizeof(buf), "%s%s for ", status, status2);
161  ast_cli_print_timestr_fromseconds(a->fd, ctime, buf);
162 
163  if (records == totalrecords) {
164  ast_cli(a->fd, " Wrote %d records since last restart.\n", totalrecords);
165  } else {
166  ast_cli(a->fd, " Wrote %d records since last restart and %d records since last reconnect.\n", totalrecords, records);
167  }
168  } else {
169  ast_cli(a->fd, "Not currently connected to a PgSQL server.\n");
170  }
171  return CLI_SUCCESS;
172 }
static char * table
Definition: cdr_pgsql.c:73
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
const int argc
Definition: cli.h:160
Definition: cli.h:152
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
int args
This gets set in ast_cli_register()
Definition: cli.h:185
static int totalrecords
Definition: cdr_pgsql.c:81
static char * pgdbname
Definition: cdr_pgsql.c:68
const int fd
Definition: cli.h:159
#define CLI_SHOWUSAGE
Definition: cli.h:45
static time_t connect_time
Definition: cdr_pgsql.c:80
char * command
Definition: cli.h:186
static char * pgdbport
Definition: cdr_pgsql.c:72
const char * usage
Definition: cli.h:177
void ast_cli_print_timestr_fromseconds(int fd, int seconds, const char *prefix)
Print on cli a duration in seconds in format s year(s), s week(s), s day(s), s hour(s), s second(s)
Definition: main/cli.c:3021
static char * pghostname
Definition: cdr_pgsql.c:67
#define CLI_SUCCESS
Definition: cli.h:44
static char * pgdbuser
Definition: cdr_pgsql.c:69
static int connected
Definition: cdr_pgsql.c:77
static int records
Definition: cdr_pgsql.c:82
jack_status_t status
Definition: app_jack.c:146

◆ load_module()

static int load_module ( void  )
static

Definition at line 788 of file cdr_pgsql.c.

References ast_cdr_register(), ast_cli_register_multiple, AST_MODULE_LOAD_DECLINE, config_module(), ast_module_info::description, columns::name, and pgsql_log().

Referenced by reload().

789 {
791  if (config_module(0)) {
793  }
796 }
const char * description
Definition: module.h:352
descriptor for a cli entry.
Definition: cli.h:171
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
static struct ast_cli_entry cdr_pgsql_status_cli[]
Definition: cdr_pgsql.c:85
int ast_cdr_register(const char *name, const char *desc, ast_cdrbe be)
Register a CDR handling engine.
Definition: cdr.c:2943
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
static const char name[]
Definition: cdr_pgsql.c:64
static int pgsql_log(struct ast_cdr *cdr)
Definition: cdr_pgsql.c:214
static int config_module(int reload)
Definition: cdr_pgsql.c:524

◆ pgsql_log()

static int pgsql_log ( struct ast_cdr cdr)
static

Definition at line 214 of file cdr_pgsql.c.

References ast_cdr::answer, ast_cdr_format_var(), ast_debug, ast_free, ast_localtime(), ast_log, ast_malloc, ast_mutex_lock, ast_mutex_unlock, ast_realloc, 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(), ast_tvdiff_us(), ast_tvzero(), buf, conn, connect_time, connected, DATE_FORMAT, encoding, ast_cdr::end, columns::hasdefault, LENGTHEN_BUF1, LENGTHEN_BUF2, columns::list, LOG_ERROR, LOG_WARNING, maxsize, maxsize2, columns::name, columns::notnull, NULL, pgdbname, pgdbuser, pghostname, pgpassword, pgsql_lock, pgsql_reconnect(), records, result, ast_cdr::start, table, totalrecords, columns::type, tz, and value.

Referenced by load_module().

215 {
216  struct ast_tm tm;
217  char *pgerror;
218  PGresult *result;
219  int res = -1;
220 
222 
223  if ((!connected) && pghostname && pgdbuser && pgpassword && pgdbname) {
224  pgsql_reconnect();
225 
226  if (PQstatus(conn) != CONNECTION_BAD) {
227  connected = 1;
228  connect_time = time(NULL);
229  records = 0;
230  if (PQsetClientEncoding(conn, encoding)) {
231 #ifdef HAVE_PGSQL_pg_encoding_to_char
232  ast_log(LOG_WARNING, "Failed to set encoding to '%s'. Encoding set to default '%s'\n", encoding, pg_encoding_to_char(PQclientEncoding(conn)));
233 #else
234  ast_log(LOG_WARNING, "Failed to set encoding to '%s'. Encoding set to default.\n", encoding);
235 #endif
236  }
237  } else {
238  pgerror = PQerrorMessage(conn);
239  ast_log(LOG_ERROR, "Unable to connect to database server %s. Calls will not be logged!\n", pghostname);
240  ast_log(LOG_ERROR, "Reason: %s\n", pgerror);
241  PQfinish(conn);
242  conn = NULL;
243  }
244  }
245 
246  if (connected) {
247  struct columns *cur;
248  struct ast_str *sql = ast_str_create(maxsize), *sql2 = ast_str_create(maxsize2);
249  char buf[257];
250  char *escapebuf = NULL, *value;
251  char *separator = "";
252  size_t bufsize = 513;
253 
254  escapebuf = ast_malloc(bufsize);
255  if (!escapebuf || !sql || !sql2) {
256  goto ast_log_cleanup;
257  }
258 
259  ast_str_set(&sql, 0, "INSERT INTO %s (", table);
260  ast_str_set(&sql2, 0, " VALUES (");
261 
263  AST_RWLIST_TRAVERSE(&psql_columns, cur, list) {
264  /* For fields not set, simply skip them */
265  ast_cdr_format_var(cdr, cur->name, &value, buf, sizeof(buf), 0);
266  if (strcmp(cur->name, "calldate") == 0 && !value) {
267  ast_cdr_format_var(cdr, "start", &value, buf, sizeof(buf), 0);
268  }
269  if (!value) {
270  if (cur->notnull && !cur->hasdefault) {
271  /* Field is NOT NULL (but no default), must include it anyway */
272  LENGTHEN_BUF1(strlen(cur->name) + 2);
273  ast_str_append(&sql, 0, "%s\"%s\"", separator, cur->name);
274  LENGTHEN_BUF2(3);
275  ast_str_append(&sql2, 0, "%s''", separator);
276  separator = ", ";
277  }
278  continue;
279  }
280 
281  LENGTHEN_BUF1(strlen(cur->name) + 2);
282  ast_str_append(&sql, 0, "%s\"%s\"", separator, cur->name);
283 
284  if (strcmp(cur->name, "start") == 0 || strcmp(cur->name, "calldate") == 0) {
285  if (strncmp(cur->type, "int", 3) == 0) {
286  LENGTHEN_BUF2(13);
287  ast_str_append(&sql2, 0, "%s%ld", separator, (long) cdr->start.tv_sec);
288  } else if (strncmp(cur->type, "float", 5) == 0) {
289  LENGTHEN_BUF2(31);
290  ast_str_append(&sql2, 0, "%s%f", separator, (double)cdr->start.tv_sec + (double)cdr->start.tv_usec / 1000000.0);
291  } else {
292  /* char, hopefully */
293  LENGTHEN_BUF2(31);
294  ast_localtime(&cdr->start, &tm, tz);
295  ast_strftime(buf, sizeof(buf), DATE_FORMAT, &tm);
296  ast_str_append(&sql2, 0, "%s%s", separator, buf);
297  }
298  } else if (strcmp(cur->name, "answer") == 0) {
299  if (strncmp(cur->type, "int", 3) == 0) {
300  LENGTHEN_BUF2(13);
301  ast_str_append(&sql2, 0, "%s%ld", separator, (long) cdr->answer.tv_sec);
302  } else if (strncmp(cur->type, "float", 5) == 0) {
303  LENGTHEN_BUF2(31);
304  ast_str_append(&sql2, 0, "%s%f", separator, (double)cdr->answer.tv_sec + (double)cdr->answer.tv_usec / 1000000.0);
305  } else {
306  /* char, hopefully */
307  LENGTHEN_BUF2(31);
308  ast_localtime(&cdr->answer, &tm, tz);
309  ast_strftime(buf, sizeof(buf), DATE_FORMAT, &tm);
310  ast_str_append(&sql2, 0, "%s%s", separator, buf);
311  }
312  } else if (strcmp(cur->name, "end") == 0) {
313  if (strncmp(cur->type, "int", 3) == 0) {
314  LENGTHEN_BUF2(13);
315  ast_str_append(&sql2, 0, "%s%ld", separator, (long) cdr->end.tv_sec);
316  } else if (strncmp(cur->type, "float", 5) == 0) {
317  LENGTHEN_BUF2(31);
318  ast_str_append(&sql2, 0, "%s%f", separator, (double)cdr->end.tv_sec + (double)cdr->end.tv_usec / 1000000.0);
319  } else {
320  /* char, hopefully */
321  LENGTHEN_BUF2(31);
322  ast_localtime(&cdr->end, &tm, tz);
323  ast_strftime(buf, sizeof(buf), DATE_FORMAT, &tm);
324  ast_str_append(&sql2, 0, "%s%s", separator, buf);
325  }
326  } else if (strcmp(cur->name, "duration") == 0 || strcmp(cur->name, "billsec") == 0) {
327  if (cur->type[0] == 'i') {
328  /* Get integer, no need to escape anything */
329  ast_cdr_format_var(cdr, cur->name, &value, buf, sizeof(buf), 0);
330  LENGTHEN_BUF2(13);
331  ast_str_append(&sql2, 0, "%s%s", separator, value);
332  } else if (strncmp(cur->type, "float", 5) == 0) {
333  struct timeval *when = cur->name[0] == 'd' ? &cdr->start : ast_tvzero(cdr->answer) ? &cdr->end : &cdr->answer;
334  LENGTHEN_BUF2(31);
335  ast_str_append(&sql2, 0, "%s%f", separator, (double) (ast_tvdiff_us(cdr->end, *when) / 1000000.0));
336  } else {
337  /* Char field, probably */
338  struct timeval *when = cur->name[0] == 'd' ? &cdr->start : ast_tvzero(cdr->answer) ? &cdr->end : &cdr->answer;
339  LENGTHEN_BUF2(31);
340  ast_str_append(&sql2, 0, "%s'%f'", separator, (double) (ast_tvdiff_us(cdr->end, *when) / 1000000.0));
341  }
342  } else if (strcmp(cur->name, "disposition") == 0 || strcmp(cur->name, "amaflags") == 0) {
343  if (strncmp(cur->type, "int", 3) == 0) {
344  /* Integer, no need to escape anything */
345  ast_cdr_format_var(cdr, cur->name, &value, buf, sizeof(buf), 1);
346  LENGTHEN_BUF2(13);
347  ast_str_append(&sql2, 0, "%s%s", separator, value);
348  } else {
349  /* Although this is a char field, there are no special characters in the values for these fields */
350  ast_cdr_format_var(cdr, cur->name, &value, buf, sizeof(buf), 0);
351  LENGTHEN_BUF2(31);
352  ast_str_append(&sql2, 0, "%s'%s'", separator, value);
353  }
354  } else {
355  /* Arbitrary field, could be anything */
356  ast_cdr_format_var(cdr, cur->name, &value, buf, sizeof(buf), 0);
357  if (strncmp(cur->type, "int", 3) == 0) {
358  long long whatever;
359  if (value && sscanf(value, "%30lld", &whatever) == 1) {
360  LENGTHEN_BUF2(26);
361  ast_str_append(&sql2, 0, "%s%lld", separator, whatever);
362  } else {
363  LENGTHEN_BUF2(2);
364  ast_str_append(&sql2, 0, "%s0", separator);
365  }
366  } else if (strncmp(cur->type, "float", 5) == 0) {
367  long double whatever;
368  if (value && sscanf(value, "%30Lf", &whatever) == 1) {
369  LENGTHEN_BUF2(51);
370  ast_str_append(&sql2, 0, "%s%30Lf", separator, whatever);
371  } else {
372  LENGTHEN_BUF2(2);
373  ast_str_append(&sql2, 0, "%s0", separator);
374  }
375  /* XXX Might want to handle dates, times, and other misc fields here XXX */
376  } else {
377  if (value) {
378  size_t required_size = strlen(value) * 2 + 1;
379 
380  /* If our argument size exceeds our buffer, grow it,
381  * as PQescapeStringConn() expects the buffer to be
382  * adequitely sized and does *NOT* do size checking.
383  */
384  if (required_size > bufsize) {
385  char *tmpbuf = ast_realloc(escapebuf, required_size);
386 
387  if (!tmpbuf) {
389  goto ast_log_cleanup;
390  }
391 
392  escapebuf = tmpbuf;
393  bufsize = required_size;
394  }
395  PQescapeStringConn(conn, escapebuf, value, strlen(value), NULL);
396  } else {
397  escapebuf[0] = '\0';
398  }
399  LENGTHEN_BUF2(strlen(escapebuf) + 3);
400  ast_str_append(&sql2, 0, "%s'%s'", separator, escapebuf);
401  }
402  }
403  separator = ", ";
404  }
405 
406  LENGTHEN_BUF1(ast_str_strlen(sql2) + 2);
408  ast_str_append(&sql, 0, ")%s)", ast_str_buffer(sql2));
409 
410  ast_debug(3, "Inserting a CDR record: [%s]\n", ast_str_buffer(sql));
411 
412  /* Test to be sure we're still connected... */
413  /* If we're connected, and connection is working, good. */
414  /* Otherwise, attempt reconnect. If it fails... sorry... */
415  if (PQstatus(conn) == CONNECTION_OK) {
416  connected = 1;
417  } else {
418  ast_log(LOG_ERROR, "Connection was lost... attempting to reconnect.\n");
419  PQreset(conn);
420  if (PQstatus(conn) == CONNECTION_OK) {
421  ast_log(LOG_ERROR, "Connection reestablished.\n");
422  connected = 1;
423  connect_time = time(NULL);
424  records = 0;
425  } else {
426  pgerror = PQerrorMessage(conn);
427  ast_log(LOG_ERROR, "Unable to reconnect to database server %s. Calls will not be logged!\n", pghostname);
428  ast_log(LOG_ERROR, "Reason: %s\n", pgerror);
429  PQfinish(conn);
430  conn = NULL;
431  connected = 0;
432  goto ast_log_cleanup;
433  }
434  }
435  result = PQexec(conn, ast_str_buffer(sql));
436  if (PQresultStatus(result) != PGRES_COMMAND_OK) {
437  pgerror = PQresultErrorMessage(result);
438  ast_log(LOG_ERROR, "Failed to insert call detail record into database!\n");
439  ast_log(LOG_ERROR, "Reason: %s\n", pgerror);
440  ast_log(LOG_ERROR, "Connection may have been lost... attempting to reconnect.\n");
441  PQreset(conn);
442  if (PQstatus(conn) == CONNECTION_OK) {
443  ast_log(LOG_ERROR, "Connection reestablished.\n");
444  connected = 1;
445  connect_time = time(NULL);
446  records = 0;
447  PQclear(result);
448  result = PQexec(conn, ast_str_buffer(sql));
449  if (PQresultStatus(result) != PGRES_COMMAND_OK) {
450  pgerror = PQresultErrorMessage(result);
451  ast_log(LOG_ERROR, "HARD ERROR! Attempted reconnection failed. DROPPING CALL RECORD!\n");
452  ast_log(LOG_ERROR, "Reason: %s\n", pgerror);
453  } else {
454  /* Second try worked out ok */
455  totalrecords++;
456  records++;
457  res = 0;
458  }
459  }
460  } else {
461  totalrecords++;
462  records++;
463  res = 0;
464  }
465  PQclear(result);
466 
467  /* Next time, just allocate buffers that are that big to start with. */
468  if (ast_str_strlen(sql) > maxsize) {
469  maxsize = ast_str_strlen(sql);
470  }
471  if (ast_str_strlen(sql2) > maxsize2) {
472  maxsize2 = ast_str_strlen(sql2);
473  }
474 
475 ast_log_cleanup:
476  ast_free(escapebuf);
477  ast_free(sql);
478  ast_free(sql2);
479  }
480 
482  return res;
483 }
unsigned int hasdefault
Definition: cdr_pgsql.c:98
static char * pgpassword
Definition: cdr_pgsql.c:70
static char * table
Definition: cdr_pgsql.c:73
static PGconn * conn
Definition: cdr_pgsql.c:91
#define ast_realloc(p, len)
A wrapper for realloc()
Definition: astmm.h:228
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static ast_mutex_t pgsql_lock
Definition: cdr_pgsql.c:89
#define LOG_WARNING
Definition: logger.h:274
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
Definition: localtime.c:1739
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition: time.h:108
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1091
#define ast_mutex_lock(a)
Definition: lock.h:187
#define NULL
Definition: resample.c:96
int value
Definition: syslog.c:37
static int totalrecords
Definition: cdr_pgsql.c:81
void ast_cdr_format_var(struct ast_cdr *cdr, const char *name, char **ret, char *workspace, int workspacelen, int raw)
Format a CDR variable from an already posted CDR.
Definition: cdr.c:3050
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1065
static char * pgdbname
Definition: cdr_pgsql.c:68
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:193
struct timeval answer
Definition: cdr.h:296
#define LOG_ERROR
Definition: logger.h:285
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
static char * tz
Definition: cdr_pgsql.c:75
#define LENGTHEN_BUF1(size)
Definition: cdr_pgsql.c:119
static time_t connect_time
Definition: cdr_pgsql.c:80
struct timeval start
Definition: cdr.h:294
static int maxsize
Definition: cdr_pgsql.c:79
#define ast_free(a)
Definition: astmm.h:182
int ast_strftime(char *buf, size_t len, const char *format, const struct ast_tm *tm)
Special version of strftime(3) that handles fractions of a second. Takes the same arguments as strfti...
Definition: localtime.c:2524
static char * pghostname
Definition: cdr_pgsql.c:67
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition: strings.h:688
struct timeval end
Definition: cdr.h:298
unsigned int notnull
Definition: cdr_pgsql.c:97
static PGresult * result
Definition: cel_pgsql.c:88
static char * pgdbuser
Definition: cdr_pgsql.c:69
static int connected
Definition: cdr_pgsql.c:77
int64_t ast_tvdiff_us(struct timeval end, struct timeval start)
Computes the difference (in microseconds) between two struct timeval instances.
Definition: time.h:78
static char * encoding
Definition: cdr_pgsql.c:74
static void pgsql_reconnect(void)
Definition: cdr_pgsql.c:174
#define DATE_FORMAT
Definition: cdr_pgsql.c:60
static int records
Definition: cdr_pgsql.c:82
static int maxsize2
Definition: cdr_pgsql.c:79
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620
#define ast_mutex_unlock(a)
Definition: lock.h:188
#define LENGTHEN_BUF2(size)
Definition: cdr_pgsql.c:121

◆ pgsql_reconnect()

static void pgsql_reconnect ( void  )
static

Definition at line 174 of file cdr_pgsql.c.

References ast_free, ast_log, ast_str_append(), ast_str_buffer(), ast_str_create, ast_str_strlen(), ast_strlen_zero, conn, LOG_ERROR, NULL, pgappname, pgdbname, pgdbport, pgdbuser, pghostname, and pgpassword.

Referenced by config_module(), and pgsql_log().

175 {
176  struct ast_str *conn_info = ast_str_create(128);
177  if (!conn_info) {
178  ast_log(LOG_ERROR, "Failed to allocate memory for connection string.\n");
179  return;
180  }
181 
182  if (conn) {
183  PQfinish(conn);
184  conn = NULL;
185  }
186 
187  if (!ast_strlen_zero(pghostname)) {
188  ast_str_append(&conn_info, 0, "host=%s ", pghostname);
189  }
190  if (!ast_strlen_zero(pgdbport)) {
191  ast_str_append(&conn_info, 0, "port=%s ", pgdbport);
192  }
193  if (!ast_strlen_zero(pgdbname)) {
194  ast_str_append(&conn_info, 0, "dbname=%s ", pgdbname);
195  }
196  if (!ast_strlen_zero(pgdbuser)) {
197  ast_str_append(&conn_info, 0, "user=%s ", pgdbuser);
198  }
199  if (!ast_strlen_zero(pgappname)) {
200  ast_str_append(&conn_info, 0, "application_name=%s ", pgappname);
201  }
202  if (!ast_strlen_zero(pgpassword)) {
203  ast_str_append(&conn_info, 0, "password=%s", pgpassword);
204  }
205  if (ast_str_strlen(conn_info) == 0) {
206  ast_log(LOG_ERROR, "Connection string is blank.\n");
207  return;
208  }
209 
210  conn = PQconnectdb(ast_str_buffer(conn_info));
211  ast_free(conn_info);
212 }
static char * pgpassword
Definition: cdr_pgsql.c:70
static PGconn * conn
Definition: cdr_pgsql.c:91
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1091
static char * pgappname
Definition: cdr_pgsql.c:71
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
static char * pgdbname
Definition: cdr_pgsql.c:68
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
Definition: logger.h:285
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
#define ast_free(a)
Definition: astmm.h:182
static char * pgdbport
Definition: cdr_pgsql.c:72
static char * pghostname
Definition: cdr_pgsql.c:67
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition: strings.h:688
static char * pgdbuser
Definition: cdr_pgsql.c:69
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620

◆ reload()

static int reload ( void  )
static

Definition at line 798 of file cdr_pgsql.c.

References AST_MODFLAG_LOAD_ORDER, AST_MODPRI_CDR_DRIVER, AST_MODULE_INFO(), AST_MODULE_SUPPORT_EXTENDED, ASTERISK_GPL_KEY, config_module(), load_module(), and unload_module().

799 {
800  return config_module(1);
801 }
static int config_module(int reload)
Definition: cdr_pgsql.c:524

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 497 of file cdr_pgsql.c.

References ARRAY_LEN, ast_cdr_unregister(), ast_cli_unregister_multiple(), ast_free, conn, empty_columns(), encoding, columns::name, NULL, pgappname, pgdbname, pgdbport, pgdbuser, pghostname, pgpassword, table, and tz.

Referenced by config_module(), and reload().

498 {
499  if (ast_cdr_unregister(name)) {
500  return -1;
501  }
502 
504 
505  if (conn) {
506  PQfinish(conn);
507  conn = NULL;
508  }
515  ast_free(table);
517  ast_free(tz);
518 
519  empty_columns();
520 
521  return 0;
522 }
static char * pgpassword
Definition: cdr_pgsql.c:70
static char * table
Definition: cdr_pgsql.c:73
static PGconn * conn
Definition: cdr_pgsql.c:91
int ast_cdr_unregister(const char *name)
Unregister a CDR handling engine.
Definition: cdr.c:2988
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
static struct ast_cli_entry cdr_pgsql_status_cli[]
Definition: cdr_pgsql.c:85
static char * pgappname
Definition: cdr_pgsql.c:71
#define NULL
Definition: resample.c:96
static char * pgdbname
Definition: cdr_pgsql.c:68
static char * tz
Definition: cdr_pgsql.c:75
#define ast_free(a)
Definition: astmm.h:182
static char * pgdbport
Definition: cdr_pgsql.c:72
static char * pghostname
Definition: cdr_pgsql.c:67
static const char name[]
Definition: cdr_pgsql.c:64
static char * pgdbuser
Definition: cdr_pgsql.c:69
static char * encoding
Definition: cdr_pgsql.c:74
static void empty_columns(void)
Definition: cdr_pgsql.c:486

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .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 = "30ef0c93b36035ec78c9cfd712d36d9b" , .support_level = AST_MODULE_SUPPORT_EXTENDED, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CDR_DRIVER, .requires = "cdr", }
static

Definition at line 810 of file cdr_pgsql.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 810 of file cdr_pgsql.c.

◆ cdr_pgsql_status_cli

struct ast_cli_entry cdr_pgsql_status_cli[]
static
Initial value:
= {
{ .handler = handle_cdr_pgsql_status , .summary = "Show connection status of the PostgreSQL CDR driver (cdr_pgsql)" ,},
}
static char * handle_cdr_pgsql_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Handle the CLI command cdr show pgsql status.
Definition: cdr_pgsql.c:125

Definition at line 85 of file cdr_pgsql.c.

◆ config

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

Definition at line 65 of file cdr_pgsql.c.

Referenced by config_module().

◆ conn

PGconn* conn = NULL
static

Definition at line 91 of file cdr_pgsql.c.

Referenced by config_module(), pgsql_log(), pgsql_reconnect(), and unload_module().

◆ connect_time

time_t connect_time = 0
static

Definition at line 80 of file cdr_pgsql.c.

Referenced by config_module(), handle_cdr_pgsql_status(), and pgsql_log().

◆ connected

int connected = 0
static

Definition at line 77 of file cdr_pgsql.c.

Referenced by config_module(), handle_cdr_pgsql_status(), and pgsql_log().

◆ encoding

char* encoding
static

Definition at line 74 of file cdr_pgsql.c.

Referenced by check_header(), config_module(), pgsql_log(), and unload_module().

◆ maxsize

int maxsize = 512
static

Definition at line 79 of file cdr_pgsql.c.

Referenced by pgsql_log().

◆ maxsize2

int maxsize2 = 512
static

Definition at line 79 of file cdr_pgsql.c.

Referenced by pgsql_log().

◆ name

const char name[] = "pgsql"
static

Definition at line 64 of file cdr_pgsql.c.

◆ pgappname

char* pgappname
static

Definition at line 71 of file cdr_pgsql.c.

Referenced by config_module(), pgsql_reconnect(), and unload_module().

◆ pgdbname

char* pgdbname
static

◆ pgdbport

char* pgdbport
static

Definition at line 72 of file cdr_pgsql.c.

Referenced by config_module(), handle_cdr_pgsql_status(), pgsql_reconnect(), and unload_module().

◆ pgdbuser

char* pgdbuser
static

◆ pghostname

char* pghostname
static

◆ pgpassword

char* pgpassword
static

Definition at line 70 of file cdr_pgsql.c.

Referenced by config_module(), pgsql_log(), pgsql_reconnect(), and unload_module().

◆ pgsql_lock

ast_mutex_t pgsql_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
static

Definition at line 89 of file cdr_pgsql.c.

Referenced by config_module(), and pgsql_log().

◆ psql_columns

struct psql_columns psql_columns = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }
static

◆ records

int records
static

Definition at line 82 of file cdr_pgsql.c.

Referenced by config_module(), handle_cdr_pgsql_status(), and pgsql_log().

◆ table

char* table
static

Definition at line 73 of file cdr_pgsql.c.

Referenced by config_module(), handle_cdr_pgsql_status(), pgsql_log(), and unload_module().

◆ totalrecords

int totalrecords = 0
static

Definition at line 81 of file cdr_pgsql.c.

Referenced by handle_cdr_pgsql_status(), and pgsql_log().

◆ tz

char* tz
static