52 #define RES_CONFIG_PGSQL_CONF "res_pgsql.conf"
56 #define has_schema_support (version > 70300 ? 1 : 0)
58 #define MAX_DB_OPTION_SIZE 64
79 static
char dbuser[MAX_DB_OPTION_SIZE] = "";
80 static
char dbpass[MAX_DB_OPTION_SIZE] = "";
81 static
char dbname[MAX_DB_OPTION_SIZE] = "";
82 static
char dbsock[MAX_DB_OPTION_SIZE] = "";
98 #define ESCAPE_STRING(buffer, stringname) \
100 int len = strlen(stringname); \
101 struct ast_str *semi = ast_str_thread_get(&semibuf_buf, len * 3 + 1); \
102 const char *chunk = stringname; \
103 ast_str_reset(semi); \
104 for (; *chunk; chunk++) { \
105 if (strchr(";^", *chunk)) { \
106 ast_str_append(&semi, 0, "^%02hhX", *chunk); \
108 ast_str_append(&semi, 0, "%c", *chunk); \
111 if (ast_str_strlen(semi) > (ast_str_size(buffer) - 1) / 2) { \
112 ast_str_make_space(&buffer, ast_str_strlen(semi) * 2 + 1); \
114 PQescapeStringConn(pgsqlConn, ast_str_buffer(buffer), ast_str_buffer(semi), ast_str_size(buffer), &pgresult); \
135 RAII_VAR(PGresult *, result, NULL, PQclear);
136 char *fname, *ftype, *flen, *fnotnull, *fdef;
141 if (!strcasecmp(table->
name, orig_tablename)) {
142 ast_debug(1,
"Found table in cache; now locking\n");
144 ast_debug(1,
"Lock cached table; now returning\n");
150 ast_debug(1,
"Table '%s' not found in cache, querying now\n", orig_tablename);
154 char *schemaname, *tablename;
155 if (strchr(orig_tablename,
'.')) {
157 tablename = strchr(schemaname,
'.');
165 if (strchr(schemaname,
'\\') || strchr(schemaname,
'\'')) {
166 char *tmp = schemaname, *ptr;
168 ptr = schemaname =
ast_alloca(strlen(tmp) * 2 + 1);
169 for (; *tmp; tmp++) {
170 if (strchr(
"\\'", *tmp)) {
178 if (strchr(tablename,
'\\') || strchr(tablename,
'\'')) {
179 char *tmp = tablename, *ptr;
181 ptr = tablename =
ast_alloca(strlen(tmp) * 2 + 1);
182 for (; *tmp; tmp++) {
183 if (strchr(
"\\'", *tmp)) {
191 ast_str_set(&sql, 0,
"SELECT a.attname, t.typname, a.attlen, a.attnotnull, d.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",
196 if (strchr(orig_tablename,
'\\') || strchr(orig_tablename,
'\'')) {
197 const char *tmp = orig_tablename;
200 orig_tablename = ptr =
ast_alloca(strlen(tmp) * 2 + 1);
201 for (; *tmp; tmp++) {
202 if (strchr(
"\\'", *tmp)) {
210 ast_str_set(&sql, 0,
"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", orig_tablename);
221 ast_debug(1,
"Query of table structure complete. Now retrieving results.\n");
222 if (PQresultStatus(result) != PGRES_TUPLES_OK) {
223 pgerror = PQresultErrorMessage(result);
230 if (!(table =
ast_calloc(1,
sizeof(*table) + strlen(orig_tablename) + 1))) {
236 strcpy(table->
name, orig_tablename);
240 rows = PQntuples(result);
241 for (i = 0; i < rows; i++) {
242 fname = PQgetvalue(result, i, 0);
243 ftype = PQgetvalue(result, i, 1);
244 flen = PQgetvalue(result, i, 2);
245 fnotnull = PQgetvalue(result, i, 3);
246 fdef = PQgetvalue(result, i, 4);
247 ast_verb(4,
"Found column '%s' of type '%s'\n", fname, ftype);
249 if (!(column =
ast_calloc(1,
sizeof(*column) + strlen(fname) + strlen(ftype) + 2))) {
250 ast_log(
LOG_ERROR,
"Unable to allocate column element for %s, %s\n", orig_tablename, fname);
257 if (strcmp(flen,
"-1") == 0) {
259 flen = PQgetvalue(result, i, 5);
260 sscanf(flen,
"%30d", &column->
len);
263 sscanf(flen,
"%30d", &column->
len);
265 column->
name = (
char *)column +
sizeof(*column);
266 column->
type = (
char *)column +
sizeof(*column) + strlen(fname) + 1;
267 strcpy(column->
name, fname);
268 strcpy(column->
type, ftype);
269 if (*fnotnull ==
't') {
289 #define release_table(table) ast_rwlock_unlock(&(table)->lock);
297 if (strcmp(column->
name, colname) == 0) {
306 RAII_VAR(PGresult *, result, NULL, PQclear);
307 int num_rows = 0, pgresult;
313 const char *newparam, *newval;
328 newparam = va_arg(ap,
const char *);
329 newval = va_arg(ap,
const char *);
330 if (!newparam || !newval) {
332 "PostgreSQL RealTime: Realtime retrieval requires at least 1 parameter and 1 value to search on.\n");
342 op = strchr(newparam,
' ') ?
"" :
" =";
351 while ((newparam = va_arg(ap,
const char *))) {
352 newval = va_arg(ap,
const char *);
353 if (!strchr(newparam,
' '))
376 "PostgreSQL RealTime: Failed to query '%s@%s'. Check debug for more info.\n", tablename, database);
378 ast_debug(1,
"PostgreSQL RealTime: Query Failed because: %s\n", PQerrorMessage(pgsqlConn));
382 ExecStatusType result_status = PQresultStatus(result);
383 if (result_status != PGRES_COMMAND_OK
384 && result_status != PGRES_TUPLES_OK
385 && result_status != PGRES_NONFATAL_ERROR) {
387 "PostgreSQL RealTime: Failed to query '%s@%s'. Check debug for more info.\n", tablename, database);
389 ast_debug(1,
"PostgreSQL RealTime: Query Failed because: %s (%s)\n",
390 PQresultErrorMessage(result), PQresStatus(result_status));
398 if ((num_rows = PQntuples(result)) > 0) {
401 int numFields = PQnfields(result);
402 char **fieldnames = NULL;
404 ast_debug(1,
"PostgreSQL RealTime: Found %d rows.\n", num_rows);
406 if (!(fieldnames =
ast_calloc(1, numFields *
sizeof(
char *)))) {
410 for (i = 0; i < numFields; i++)
411 fieldnames[i] = PQfname(result, i);
412 for (rowIndex = 0; rowIndex < num_rows; rowIndex++) {
413 for (i = 0; i < numFields; i++) {
414 stringp = PQgetvalue(result, rowIndex, i);
416 chunk =
strsep(&stringp,
";");
432 ast_debug(1,
"Postgresql RealTime: Could not find any rows in table %s@%s.\n", tablename, database);
442 RAII_VAR(PGresult *, result, NULL, PQclear);
443 int num_rows = 0, pgresult;
446 const char *initfield = NULL;
450 const char *newparam, *newval;
470 newparam = va_arg(ap,
const char *);
471 newval = va_arg(ap,
const char *);
472 if (!newparam || !newval) {
474 "PostgreSQL RealTime: Realtime retrieval requires at least 1 parameter and 1 value to search on.\n");
484 if ((op = strchr(initfield,
' '))) {
491 if (!strchr(newparam,
' '))
504 while ((newparam = va_arg(ap,
const char *))) {
505 newval = va_arg(ap,
const char *);
506 if (!strchr(newparam,
' '))
536 "PostgreSQL RealTime: Failed to query %s@%s. Check debug for more info.\n", table, database);
538 ast_debug(1,
"PostgreSQL RealTime: Query Failed because: %s\n", PQerrorMessage(pgsqlConn));
543 ExecStatusType result_status = PQresultStatus(result);
544 if (result_status != PGRES_COMMAND_OK
545 && result_status != PGRES_TUPLES_OK
546 && result_status != PGRES_NONFATAL_ERROR) {
548 "PostgreSQL RealTime: Failed to query %s@%s. Check debug for more info.\n", table, database);
550 ast_debug(1,
"PostgreSQL RealTime: Query Failed because: %s (%s)\n",
551 PQresultErrorMessage(result), PQresStatus(result_status));
560 if ((num_rows = PQntuples(result)) > 0) {
561 int numFields = PQnfields(result);
564 char **fieldnames = NULL;
566 ast_debug(1,
"PostgreSQL RealTime: Found %d rows.\n", num_rows);
568 if (!(fieldnames =
ast_calloc(1, numFields *
sizeof(
char *)))) {
573 for (i = 0; i < numFields; i++)
574 fieldnames[i] = PQfname(result, i);
576 for (rowIndex = 0; rowIndex < num_rows; rowIndex++) {
580 for (i = 0; i < numFields; i++) {
581 stringp = PQgetvalue(result, rowIndex, i);
583 chunk =
strsep(&stringp,
";");
585 if (initfield && !strcmp(initfield, fieldnames[i])) {
597 ast_debug(1,
"PostgreSQL RealTime: Could not find any rows in table %s.\n", table);
605 static int update_pgsql(
const char *database,
const char *tablename,
const char *keyfield,
606 const char *lookup, va_list ap)
608 RAII_VAR(PGresult *, result, NULL, PQclear);
609 int numrows = 0, pgresult;
610 const char *newparam, *newval;
627 if (!(table =
find_table(database, tablename))) {
633 newparam = va_arg(ap,
const char *);
634 newval = va_arg(ap,
const char *);
635 if (!newparam || !newval) {
637 "PostgreSQL RealTime: Realtime retrieval requires at least 1 parameter and 1 value to search on.\n");
648 if (strcmp(column->
name, newparam) == 0) {
654 ast_log(
LOG_ERROR,
"PostgreSQL RealTime: Updating on column '%s', but that column does not exist within the table '%s'!\n", newparam, tablename);
670 while ((newparam = va_arg(ap,
const char *))) {
671 newval = va_arg(ap,
const char *);
674 ast_log(
LOG_NOTICE,
"Attempted to update column '%s' in table '%s', but column does not exist!\n", newparam, tablename);
708 "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n");
710 ast_debug(1,
"PostgreSQL RealTime: Query Failed because: %s\n", PQerrorMessage(pgsqlConn));
714 ExecStatusType result_status = PQresultStatus(result);
715 if (result_status != PGRES_COMMAND_OK
716 && result_status != PGRES_TUPLES_OK
717 && result_status != PGRES_NONFATAL_ERROR) {
719 "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n");
721 ast_debug(1,
"PostgreSQL RealTime: Query Failed because: %s (%s)\n",
722 PQresultErrorMessage(result), PQresStatus(result_status));
728 numrows = atoi(PQcmdTuples(result));
731 ast_debug(1,
"PostgreSQL RealTime: Updated %d rows on table: %s\n", numrows, tablename);
740 return (
int) numrows;
745 static int update2_pgsql(
const char *database,
const char *tablename, va_list ap)
747 RAII_VAR(PGresult *, result, NULL, PQclear);
748 int numrows = 0, pgresult,
first = 1;
750 const char *newparam, *newval;
766 if (!escapebuf || !sql || !where) {
771 if (!(table =
find_table(database, tablename))) {
779 while ((newparam = va_arg(ap,
const char *))) {
781 ast_log(
LOG_ERROR,
"Attempted to update based on criteria column '%s' (%s@%s), but that column does not exist!\n", newparam, tablename, database);
786 newval = va_arg(ap,
const char *);
799 "PostgreSQL RealTime: Realtime update requires at least 1 parameter and 1 value to search on.\n");
810 while ((newparam = va_arg(ap,
const char *))) {
811 newval = va_arg(ap,
const char *);
815 ast_log(
LOG_NOTICE,
"Attempted to update column '%s' in table '%s@%s', but column does not exist!\n", newparam, tablename, database);
844 "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n");
846 ast_debug(1,
"PostgreSQL RealTime: Query Failed because: %s\n", PQerrorMessage(pgsqlConn));
850 ExecStatusType result_status = PQresultStatus(result);
851 if (result_status != PGRES_COMMAND_OK
852 && result_status != PGRES_TUPLES_OK
853 && result_status != PGRES_NONFATAL_ERROR) {
855 "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n");
857 ast_debug(1,
"PostgreSQL RealTime: Query Failed because: %s (%s)\n",
858 PQresultErrorMessage(result), PQresStatus(result_status));
864 numrows = atoi(PQcmdTuples(result));
867 ast_debug(1,
"PostgreSQL RealTime: Updated %d rows on table: %s\n", numrows, tablename);
876 return (
int) numrows;
884 RAII_VAR(PGresult *, result, NULL, PQclear);
890 const char *newparam, *newval;
904 newparam = va_arg(ap,
const char *);
905 newval = va_arg(ap,
const char *);
906 if (!newparam || !newval) {
908 "PostgreSQL RealTime: Realtime storage requires at least 1 parameter and 1 value to store.\n");
929 while ((newparam = va_arg(ap,
const char *))) {
930 newval = va_arg(ap,
const char *);
942 "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n");
944 ast_debug(1,
"PostgreSQL RealTime: Query Failed because: %s\n", PQerrorMessage(pgsqlConn));
948 ExecStatusType result_status = PQresultStatus(result);
949 if (result_status != PGRES_COMMAND_OK
950 && result_status != PGRES_TUPLES_OK
951 && result_status != PGRES_NONFATAL_ERROR) {
953 "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n");
955 ast_debug(1,
"PostgreSQL RealTime: Query Failed because: %s (%s)\n",
956 PQresultErrorMessage(result), PQresStatus(result_status));
962 numrows = atoi(PQcmdTuples(result));
965 ast_debug(1,
"PostgreSQL RealTime: row inserted on table: %s.", table);
980 static int destroy_pgsql(
const char *database,
const char *
table,
const char *keyfield,
const char *lookup, va_list ap)
982 RAII_VAR(PGresult *, result, NULL, PQclear);
987 const char *newparam, *newval;
1006 "PostgreSQL RealTime: Realtime destroy requires at least 1 parameter and 1 value to search on.\n");
1008 PQfinish(pgsqlConn);
1028 while ((newparam = va_arg(ap,
const char *))) {
1029 newval = va_arg(ap,
const char *);
1039 "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n");
1041 ast_debug(1,
"PostgreSQL RealTime: Query Failed because: %s\n", PQerrorMessage(pgsqlConn));
1045 ExecStatusType result_status = PQresultStatus(result);
1046 if (result_status != PGRES_COMMAND_OK
1047 && result_status != PGRES_TUPLES_OK
1048 && result_status != PGRES_NONFATAL_ERROR) {
1050 "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n");
1052 ast_debug(1,
"PostgreSQL RealTime: Query Failed because: %s (%s)\n",
1053 PQresultErrorMessage(result), PQresStatus(result_status));
1059 numrows = atoi(PQcmdTuples(result));
1062 ast_debug(1,
"PostgreSQL RealTime: Deleted %d rows on table: %s\n", numrows, table);
1071 return (
int) numrows;
1079 struct ast_flags flags,
const char *suggested_incl,
const char *who_asked)
1081 RAII_VAR(PGresult *, result, NULL, PQclear);
1087 int last_cat_metric = 0;
1102 ast_str_set(&sql, 0,
"SELECT category, var_name, var_val, cat_metric FROM %s "
1103 "WHERE filename='%s' and commented=0"
1104 "ORDER BY cat_metric DESC, var_metric ASC, category, var_name ", table, file);
1117 "PostgreSQL RealTime: Failed to query '%s@%s'. Check debug for more info.\n", table, database);
1119 ast_debug(1,
"PostgreSQL RealTime: Query Failed because: %s\n", PQerrorMessage(pgsqlConn));
1123 ExecStatusType result_status = PQresultStatus(result);
1124 if (result_status != PGRES_COMMAND_OK
1125 && result_status != PGRES_TUPLES_OK
1126 && result_status != PGRES_NONFATAL_ERROR) {
1128 "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n");
1130 ast_debug(1,
"PostgreSQL RealTime: Query Failed because: %s (%s)\n",
1131 PQresultErrorMessage(result), PQresStatus(result_status));
1137 if ((num_rows = PQntuples(result)) > 0) {
1140 ast_debug(1,
"PostgreSQL RealTime: Found %ld rows.\n", num_rows);
1142 for (rowIndex = 0; rowIndex < num_rows; rowIndex++) {
1143 char *field_category = PQgetvalue(result, rowIndex, 0);
1144 char *field_var_name = PQgetvalue(result, rowIndex, 1);
1145 char *field_var_val = PQgetvalue(result, rowIndex, 2);
1146 char *field_cat_metric = PQgetvalue(result, rowIndex, 3);
1147 if (!strcmp(field_var_name,
"#include")) {
1155 if (strcmp(last, field_category) || last_cat_metric != atoi(field_cat_metric)) {
1160 last_cat_metric = atoi(field_cat_metric);
1168 "PostgreSQL RealTime: Could not find config '%s' in database.\n", file);
1176 static int require_pgsql(
const char *database,
const char *tablename, va_list ap)
1181 int type, size, res = 0;
1191 ast_log(
LOG_WARNING,
"Table %s not found in database. This table should exist if you're using realtime.\n", tablename);
1195 while ((elm = va_arg(ap,
char *))) {
1197 size = va_arg(ap,
int);
1199 if (strcmp(column->
name, elm) == 0) {
1201 if ((strncmp(column->
type,
"char", 4) == 0 || strncmp(column->
type,
"varchar", 7) == 0 || strcmp(column->
type,
"bpchar") == 0)) {
1202 if ((size > column->
len) && column->
len != -1) {
1203 ast_log(
LOG_WARNING,
"Column '%s' should be at least %d long, but is only %d long.\n", column->
name, size, column->
len);
1206 }
else if (strncmp(column->
type,
"int", 3) == 0) {
1207 int typesize = atoi(column->
type + 3);
1213 ast_log(
LOG_WARNING,
"Column '%s' may not be large enough for the required data length: %d\n", column->
name, size);
1217 ast_log(
LOG_WARNING,
"Column '%s' may not be large enough for the required data length: %d\n", column->
name, size);
1220 ast_log(
LOG_WARNING,
"Column '%s' is of the incorrect type: (need %s(%d) but saw %s)\n",
1226 "a rather stiff drink ",
1227 size, column->
type);
1230 }
else if (strncmp(column->
type,
"float", 5) == 0) {
1235 }
else if (strncmp(column->
type,
"timestamp", 9) == 0) {
1250 ast_log(
LOG_WARNING,
"Table %s requires a column '%s' of size '%d', but no such column exists.\n", tablename, elm, size);
1260 snprintf(fieldtype,
sizeof(fieldtype),
"CHAR(%d)",
1261 size < 15 ? size * 2 :
1262 (size * 3 / 2 > 255) ? 255 : size * 3 / 2);
1264 snprintf(fieldtype,
sizeof(fieldtype),
"INT2");
1266 snprintf(fieldtype,
sizeof(fieldtype),
"INT4");
1268 snprintf(fieldtype,
sizeof(fieldtype),
"INT8");
1271 snprintf(fieldtype,
sizeof(fieldtype),
"CHAR(20)");
1273 snprintf(fieldtype,
sizeof(fieldtype),
"FLOAT8");
1275 snprintf(fieldtype,
sizeof(fieldtype),
"DATE");
1277 snprintf(fieldtype,
sizeof(fieldtype),
"TIMESTAMP");
1283 ast_str_set(&sql, 0,
"ALTER TABLE %s ADD COLUMN %s %s", tablename, elm, fieldtype);
1284 ast_debug(1,
"About to lock pgsql_lock (running alter on table '%s' to add column '%s')\n", tablename, elm);
1294 ast_debug(1,
"About to run ALTER query on table '%s' to add column '%s'\n", tablename, elm);
1296 ast_debug(1,
"Finished running ALTER query on table '%s'\n", tablename);
1297 if (PQresultStatus(result) != PGRES_COMMAND_OK) {
1321 ast_debug(2,
"About to lock table cache list\n");
1323 ast_debug(2,
"About to traverse table cache list\n");
1325 if (strcmp(cur->
name, tablename) == 0) {
1326 ast_debug(2,
"About to remove matching cache entry\n");
1328 ast_debug(2,
"About to destroy matching cache entry\n");
1330 ast_debug(1,
"Cache entry '%s@%s' destroyed\n", tablename, database);
1337 return cur ? 0 : -1;
1359 ast_verb(1,
"PostgreSQL RealTime driver loaded.\n");
1372 PQfinish(pgsqlConn);
1377 ast_verb(1,
"PostgreSQL RealTime unloaded.\n");
1418 PQfinish(pgsqlConn);
1424 "PostgreSQL RealTime: No database user found, using 'asterisk' as default.\n");
1425 strcpy(
dbuser,
"asterisk");
1432 "PostgreSQL RealTime: No database password found, using 'asterisk' as default.\n");
1433 strcpy(
dbpass,
"asterisk");
1440 "PostgreSQL RealTime: No database host found, using localhost via socket.\n");
1448 "PostgreSQL RealTime: No database name found, using 'asterisk' as default.\n");
1449 strcpy(
dbname,
"asterisk");
1456 "PostgreSQL RealTime: No database port found, using 5432 as default.\n");
1466 "PostgreSQL RealTime: No database socket found, using '/tmp/.s.PGSQL.%d' as default.\n",
dbport);
1474 "PostgreSQL RealTime: no requirements setting found, using 'warn' as default.\n");
1476 }
else if (!strcasecmp(s,
"createclose")) {
1478 }
else if (!strcasecmp(s,
"createchar")) {
1498 "PostgreSQL RealTime: Couldn't establish connection. Check debug.\n");
1499 ast_debug(1,
"PostgreSQL RealTime: Cannot Connect: %s\n", PQerrorMessage(pgsqlConn));
1502 ast_verb(2,
"PostgreSQL RealTime reloaded.\n");
1512 char my_database[50];
1518 if (pgsqlConn && PQstatus(pgsqlConn) != CONNECTION_OK) {
1519 PQfinish(pgsqlConn);
1527 ast_str_set(&connInfo, 0,
"host=%s port=%d dbname=%s user=%s",
1538 ast_debug(1,
"pgsqlConn=%p\n", pgsqlConn);
1539 if (pgsqlConn && PQstatus(pgsqlConn) == CONNECTION_OK) {
1540 ast_debug(1,
"PostgreSQL RealTime: Successfully connected to database.\n");
1542 version = PQserverVersion(pgsqlConn);
1546 "PostgreSQL RealTime: Failed to connect database %s on %s: %s\n",
1547 my_database,
dbhost, PQresultErrorMessage(NULL));
1551 ast_debug(1,
"PostgreSQL RealTime: One or more of the parameters in the config does not pass our validity checks.\n");
1564 e->
command =
"realtime show pgsql cache";
1566 "Usage: realtime show pgsql cache [<table>]\n"
1567 " Shows table cache for the PostgreSQL RealTime driver\n";
1573 l = strlen(a->
word);
1577 if (!strncasecmp(a->
word, cur->
name, l) && ++which > a->
n) {
1593 }
else if (a->
argc == 5) {
1597 ast_cli(a->
fd,
"Columns for Table Cache '%s':\n", a->
argv[4]);
1598 ast_cli(a->
fd,
"%-20.20s %-20.20s %-3.3s %-8.8s\n",
"Name",
"Type",
"Len",
"Nullable");
1612 char status[256], credentials[100] =
"";
1617 e->
command =
"realtime show pgsql status";
1619 "Usage: realtime show pgsql status\n"
1620 " Shows connection information for the PostgreSQL RealTime driver\n";
1629 if (pgsqlConn && PQstatus(pgsqlConn) == CONNECTION_OK) {
1631 snprintf(status,
sizeof(status),
"Connected to %s@%s, port %d",
dbname,
dbhost,
dbport);
1633 snprintf(status,
sizeof(status),
"Connected to %s on socket file %s",
dbname,
dbsock);
1635 snprintf(status,
sizeof(status),
"Connected to %s@%s",
dbname,
dbhost);
1638 snprintf(credentials,
sizeof(credentials),
" with username %s",
dbuser);
1640 if (ctimesec > 31536000)
1641 ast_cli(a->
fd,
"%s%s for %d years, %d days, %d hours, %d minutes, %d seconds.\n",
1642 status, credentials, ctimesec / 31536000, (ctimesec % 31536000) / 86400,
1643 (ctimesec % 86400) / 3600, (ctimesec % 3600) / 60, ctimesec % 60);
1644 else if (ctimesec > 86400)
1645 ast_cli(a->
fd,
"%s%s for %d days, %d hours, %d minutes, %d seconds.\n", status,
1646 credentials, ctimesec / 86400, (ctimesec % 86400) / 3600, (ctimesec % 3600) / 60,
1648 else if (ctimesec > 3600)
1649 ast_cli(a->
fd,
"%s%s for %d hours, %d minutes, %d seconds.\n", status, credentials,
1650 ctimesec / 3600, (ctimesec % 3600) / 60, ctimesec % 60);
1651 else if (ctimesec > 60)
1652 ast_cli(a->
fd,
"%s%s for %d minutes, %d seconds.\n", status, credentials, ctimesec / 60,
1655 ast_cli(a->
fd,
"%s%s for %d seconds.\n", status, credentials, ctimesec);
#define has_schema_support
#define AST_THREADSTORAGE(name)
Define a thread storage variable.
static struct ast_config * config_pgsql(const char *database, const char *table, const char *file, struct ast_config *cfg, struct ast_flags flags, const char *suggested_incl, const char *who_asked)
#define ast_rwlock_rdlock(a)
#define AST_CLI_DEFINE(fn, txt,...)
#define AST_LIST_LOCK(head)
Locks a list.
static void destroy_table(struct tables *table)
Asterisk locking-related definitions:
static int update_pgsql(const char *database, const char *tablename, const char *keyfield, const char *lookup, va_list ap)
Asterisk main include file. File version handling, generic pbx functions.
const char * ast_variable_retrieve(const struct ast_config *config, const char *category, const char *variable)
Gets a variable.
static const char config[]
char * strsep(char **str, const char *delims)
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
static PGconn * pgsqlConn
static struct ast_threadstorage escapebuf_buf
#define ast_rwlock_destroy(rwlock)
size_t ast_str_size(const struct ast_str *buf)
Returns the current maximum length (without reallocation) of the current buffer.
static char * handle_cli_realtime_pgsql_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char dbname[MAX_DB_OPTION_SIZE]
#define release_table(table)
descriptor for a cli entry.
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Structure for variables, used for configurations and for channel variables.
static int unload_pgsql(const char *database, const char *tablename)
Configuration File Parser.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
static struct ast_threadstorage buf2
struct ast_str * ast_str_create(size_t init_len)
Create a malloc'ed dynamic length string.
#define ast_mutex_lock(a)
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
static ast_mutex_t pgsql_lock
void ast_cli(int fd, const char *fmt,...)
#define ast_rwlock_unlock(a)
static char dbpass[MAX_DB_OPTION_SIZE]
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
static struct tables * find_table(const char *database, const char *orig_tablename)
#define ast_verb(level,...)
void ast_config_destroy(struct ast_config *config)
Destroys a config.
#define ESCAPE_STRING(buffer, stringname)
Configuration engine structure, used to define realtime drivers.
struct ast_category * ast_category_new(const char *name, const char *in_file, int lineno)
Create a category structure.
#define CONFIG_STATUS_FILEMISSING
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
#define ast_debug(level,...)
Log a DEBUG message.
#define RES_CONFIG_PGSQL_CONF
General Asterisk PBX channel definitions.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
#define ast_config_load(filename, flags)
Load a config file.
static char * handle_cli_realtime_pgsql_cache(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static struct ast_threadstorage where_buf
static force_inline int attribute_pure ast_strlen_zero(const char *s)
struct sla_ringing_trunk * last
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
char * ast_realtime_decode_chunk(char *chunk)
Remove standard encoding from realtime values, which ensures that a semicolon embedded within a singl...
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
static int pgsql_reconnect(const char *database)
static int store_pgsql(const char *database, const char *table, va_list ap)
Core PBX routines and definitions.
static struct ast_config * realtime_multi_pgsql(const char *database, const char *table, va_list ap)
#define AST_LIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a list of specified type, statically initialized.
struct tables::odbc_columns columns
static struct ast_cli_entry cli_realtime[]
#define AST_LIST_HEAD_NOLOCK(name, type)
Defines a structure to be used to hold a list of specified type (with no lock).
#define ast_strdupa(s)
duplicate a string in memory from the stack
static int update2_pgsql(const char *database, const char *tablename, va_list ap)
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
void ast_variable_append(struct ast_category *category, struct ast_variable *variable)
#define ast_rwlock_init(rwlock)
wrapper for rwlock with tracking enabled
struct sla_ringing_trunk * first
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
int ast_config_engine_register(struct ast_config_engine *newconfig)
Register config engine.
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
static struct ast_threadstorage semibuf_buf
static struct ast_threadstorage buf1
struct ast_config * ast_config_new(void)
Create a new base configuration structure.
static struct ast_threadstorage findtable_buf
static int require_pgsql(const char *database, const char *tablename, va_list ap)
static enum @327 requirements
Structure used to handle boolean flags.
static struct ast_threadstorage sql_buf
static char dbuser[MAX_DB_OPTION_SIZE]
#define ast_rwlock_wrlock(a)
static struct ast_variable * realtime_pgsql(const char *database, const char *tablename, va_list ap)
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
Structure for rwlock and tracking information.
Standard Command Line Interface.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
int ast_rq_is_int(require_type type)
Check if require type is an integer type.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
int ast_cli_register_multiple(struct ast_cli_entry *e, int len)
Register multiple commands.
static struct columns * find_column(struct tables *t, const char *colname)
static char dbsock[MAX_DB_OPTION_SIZE]
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
static int parse_config(int reload)
struct ast_str * ast_str_thread_get(struct ast_threadstorage *ts, size_t init_len)
Retrieve a thread locally stored dynamic string.
void ast_category_append(struct ast_config *config, struct ast_category *cat)
#define CONFIG_STATUS_FILEINVALID
struct ast_config * ast_config_internal_load(const char *configfile, struct ast_config *cfg, struct ast_flags flags, const char *suggested_incl_file, const char *who_asked)
static struct ast_config_engine pgsql_engine
static time_t connect_time
void ast_category_rename(struct ast_category *cat, const char *name)
#define ASTERISK_GPL_KEY
The text the key() function should return.
static char dbhost[MAX_DB_OPTION_SIZE]
Asterisk module definitions.
require_type
Types used in ast_realtime_require_field.
static int load_module(void)
#define AST_MUTEX_DEFINE_STATIC(mutex)
struct ast_variable * ast_variable_new(const char *name, const char *value, const char *filename)
#define MAX_DB_OPTION_SIZE
static int unload_module(void)
#define ASTERISK_FILE_VERSION(file, version)
Register/unregister a source code file with the core.
#define CONFIG_STATUS_FILEUNCHANGED
int ast_config_engine_deregister(struct ast_config_engine *del)
Deregister config engine.
#define ast_mutex_unlock(a)
static int destroy_pgsql(const char *database, const char *table, const char *keyfield, const char *lookup, va_list ap)