2 * Asterisk -- A telephony toolkit for Linux.
4 * Copyright (C) 1999-2005, Digium, Inc.
6 * Manuel Guesdon <mguesdon@oxymium.net> - Postgresql RealTime Driver Author/Adaptor
7 * Mark Spencer <markster@digium.com> - Asterisk Author
8 * Matthew Boehm <mboehm@cytelcom.com> - MySQL RealTime Driver Author
10 * res_config_pgsql.c <Postgresql plugin for RealTime configuration engine>
12 * v1.0 - (07-11-05) - Initial version based on res_config_mysql v2.0
17 * \brief Postgresql plugin for Asterisk RealTime Architecture
19 * \author Mark Spencer <markster@digium.com>
20 * \author Manuel Guesdon <mguesdon@oxymium.net> - Postgresql RealTime Driver Author/Adaptor
22 * \arg http://www.postgresql.org
27 #include <libpq-fe.h> /* PostgreSQL */
31 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
33 #include "asterisk/file.h"
34 #include "asterisk/logger.h"
35 #include "asterisk/channel.h"
36 #include "asterisk/pbx.h"
37 #include "asterisk/config.h"
38 #include "asterisk/module.h"
39 #include "asterisk/lock.h"
40 #include "asterisk/options.h"
41 #include "asterisk/utils.h"
42 #include "asterisk/cli.h"
44 static char *res_config_pgsql_desc = "Postgresql RealTime Configuration Driver";
46 AST_MUTEX_DEFINE_STATIC(pgsql_lock);
47 #define RES_CONFIG_PGSQL_CONF "res_pgsql.conf"
48 PGconn* pgsqlConn = NULL;
49 static char dbhost[50]="";
50 static char dbuser[50]="";
51 static char dbpass[50]="";
52 static char dbname[50]="";
53 static char dbsock[50]="";
54 static int dbport=5432;
55 static time_t connect_time=0;
57 static int parse_config(void);
58 static int pgsql_reconnect(const char *database);
59 static int realtime_pgsql_status(int fd, int argc, char **argv);
63 static char cli_realtime_pgsql_status_usage[] =
64 "Usage: realtime pgsql status\n"
65 " Shows connection information for the Postgresql RealTime driver\n";
67 static struct ast_cli_entry cli_realtime_pgsql_status = {
68 { "realtime", "pgsql", "status", NULL }, realtime_pgsql_status,
69 "Shows connection information for the Postgresql RealTime driver", cli_realtime_pgsql_status_usage, NULL };
71 static struct ast_variable *realtime_pgsql(const char *database, const char *table, va_list ap)
73 PGresult *result = NULL;
79 const char *newparam, *newval;
80 struct ast_variable *var=NULL, *prev=NULL;
83 ast_log(LOG_WARNING, "Postgresql RealTime: No table specified.\n");
87 /* Get the first parameter and first value in our list of passed paramater/value pairs */
88 newparam = va_arg(ap, const char *);
89 newval = va_arg(ap, const char *);
90 if(!newparam || !newval) {
91 ast_log(LOG_WARNING, "Postgresql RealTime: Realtime retrieval requires at least 1 parameter and 1 value to search on.\n");
100 /* Create the first part of the query using the first parameter/value pairs we just extracted
101 If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */
103 if(!strchr(newparam, ' ')) op = " ="; else op = "";
105 snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s '%s'", table, newparam, op, newval);
106 while((newparam = va_arg(ap, const char *))) {
107 newval = va_arg(ap, const char *);
108 if(!strchr(newparam, ' ')) op = " ="; else op = "";
109 snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s '%s'", newparam, op, newval);
113 /* We now have our complete statement; Lets connect to the server and execute it. */
114 ast_mutex_lock(&pgsql_lock);
115 if(!pgsql_reconnect(database)) {
116 ast_mutex_unlock(&pgsql_lock);
120 if(!(result=PQexec(pgsqlConn, sql))) {
121 ast_log(LOG_WARNING, "Postgresql RealTime: Failed to query database. Check debug for more info.\n");
122 ast_log(LOG_DEBUG, "Postgresql RealTime: Query: %s\n", sql);
123 ast_log(LOG_DEBUG, "Postgresql RealTime: Query Failed because: %s\n", PQerrorMessage(pgsqlConn));
124 ast_mutex_unlock(&pgsql_lock);
128 ExecStatusType result_status=PQresultStatus(result);
129 if (result_status!=PGRES_COMMAND_OK
130 && result_status!=PGRES_TUPLES_OK
131 && result_status!=PGRES_NONFATAL_ERROR)
133 ast_log(LOG_WARNING, "Postgresql RealTime: Failed to query database. Check debug for more info.\n");
134 ast_log(LOG_DEBUG, "Postgresql RealTime: Query: %s\n", sql);
135 ast_log(LOG_DEBUG, "Postgresql RealTime: Query Failed because: %s (%s)\n",
136 PQresultErrorMessage(result),PQresStatus(result_status));
137 ast_mutex_unlock(&pgsql_lock);
142 ast_log(LOG_DEBUG, "1Postgresql RealTime: Result=%p Query: %s\n", result, sql);
144 if((num_rows=PQntuples(result))>0) {
147 int numFields = PQnfields(result);
148 char** fieldnames=NULL;
150 ast_log(LOG_DEBUG, "Postgresql RealTime: Found %d rows.\n", num_rows);
152 fieldnames=malloc(numFields*sizeof(char*));
154 /* If I can't alloc memory at this point, why bother doing anything else? */
155 ast_log(LOG_WARNING, "Out of memory!\n");
156 ast_mutex_unlock(&pgsql_lock);
160 for(i = 0; i < numFields; i++)
161 fieldnames[i]=PQfname(result,i);
162 for(rowIndex=0;rowIndex<num_rows;rowIndex++)
164 for(i = 0; i < numFields; i++) {
165 stringp = PQgetvalue(result,rowIndex,i);
167 chunk = strsep(&stringp, ";");
168 if(chunk && !ast_strlen_zero(ast_strip(chunk))) {
170 prev->next = ast_variable_new(fieldnames[i], chunk);
175 prev = var = ast_variable_new(fieldnames[i], chunk);
183 ast_log(LOG_WARNING, "Postgresql RealTime: Could not find any rows in table %s.\n", table);
186 ast_mutex_unlock(&pgsql_lock);
192 static struct ast_config *realtime_multi_pgsql(const char *database, const char *table, va_list ap)
194 PGresult *result = NULL;
197 const char *initfield = NULL;
201 const char *newparam, *newval;
202 struct ast_realloca ra;
203 struct ast_variable *var=NULL;
204 struct ast_config *cfg = NULL;
205 struct ast_category *cat = NULL;
208 ast_log(LOG_WARNING, "Postgresql RealTime: No table specified.\n");
212 memset(&ra, 0, sizeof(ra));
214 cfg = ast_config_new();
216 /* If I can't alloc memory at this point, why bother doing anything else? */
217 ast_log(LOG_WARNING, "Out of memory!\n");
221 /* Get the first parameter and first value in our list of passed paramater/value pairs */
222 newparam = va_arg(ap, const char *);
223 newval = va_arg(ap, const char *);
224 if(!newparam || !newval) {
225 ast_log(LOG_WARNING, "Postgresql RealTime: Realtime retrieval requires at least 1 parameter and 1 value to search on.\n");
234 initfield = ast_strdupa(newparam);
235 if(initfield && (op = strchr(initfield, ' '))) {
239 /* Create the first part of the query using the first parameter/value pairs we just extracted
240 If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */
242 if(!strchr(newparam, ' ')) op = " ="; else op = "";
244 snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s '%s'", table, newparam, op, newval);
245 while((newparam = va_arg(ap, const char *))) {
246 newval = va_arg(ap, const char *);
247 if(!strchr(newparam, ' ')) op = " ="; else op = "";
248 snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s '%s'", newparam, op, newval);
252 snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " ORDER BY %s", initfield);
257 /* We now have our complete statement; Lets connect to the server and execute it. */
258 ast_mutex_lock(&pgsql_lock);
259 if(!pgsql_reconnect(database)) {
260 ast_mutex_unlock(&pgsql_lock);
264 if(!(result=PQexec(pgsqlConn, sql))) {
265 ast_log(LOG_WARNING, "Postgresql RealTime: Failed to query database. Check debug for more info.\n");
266 ast_log(LOG_DEBUG, "Postgresql RealTime: Query: %s\n", sql);
267 ast_log(LOG_DEBUG, "Postgresql RealTime: Query Failed because: %s\n", PQerrorMessage(pgsqlConn));
268 ast_mutex_unlock(&pgsql_lock);
272 ExecStatusType result_status=PQresultStatus(result);
273 if (result_status!=PGRES_COMMAND_OK
274 && result_status!=PGRES_TUPLES_OK
275 && result_status!=PGRES_NONFATAL_ERROR)
277 ast_log(LOG_WARNING, "Postgresql RealTime: Failed to query database. Check debug for more info.\n");
278 ast_log(LOG_DEBUG, "Postgresql RealTime: Query: %s\n", sql);
279 ast_log(LOG_DEBUG, "Postgresql RealTime: Query Failed because: %s (%s)\n",
280 PQresultErrorMessage(result),PQresStatus(result_status));
281 ast_mutex_unlock(&pgsql_lock);
286 ast_log(LOG_DEBUG, "2Postgresql RealTime: Result=%p Query: %s\n", result, sql);
288 if((num_rows=PQntuples(result))>0) {
289 int numFields = PQnfields(result);
292 char** fieldnames=NULL;
294 ast_log(LOG_DEBUG, "Postgresql RealTime: Found %d rows.\n", num_rows);
296 fieldnames=malloc(numFields*sizeof(char*));
298 /* If I can't alloc memory at this point, why bother doing anything else? */
299 ast_log(LOG_WARNING, "Out of memory!\n");
300 ast_mutex_unlock(&pgsql_lock);
304 for(i = 0; i < numFields; i++)
305 fieldnames[i]=PQfname(result,i);
307 for(rowIndex=0;rowIndex<num_rows;rowIndex++)
310 cat = ast_category_new("");
312 ast_log(LOG_WARNING, "Out of memory!\n");
315 for(i = 0; i < numFields; i++) {
316 stringp = PQgetvalue(result,rowIndex,i);
318 chunk = strsep(&stringp, ";");
319 if(chunk && !ast_strlen_zero(ast_strip(chunk))) {
320 if(initfield && !strcmp(initfield, fieldnames[i])) {
321 ast_category_rename(cat, chunk);
323 var = ast_variable_new(fieldnames[i], chunk);
324 ast_variable_append(cat, var);
328 ast_category_append(cfg, cat);
332 ast_log(LOG_WARNING, "Postgresql RealTime: Could not find any rows in table %s.\n", table);
335 ast_mutex_unlock(&pgsql_lock);
341 static int update_pgsql(const char *database, const char *table, const char *keyfield, const char *lookup, va_list ap)
343 PGresult* result = NULL;
346 const char *newparam, *newval;
349 ast_log(LOG_WARNING, "Postgresql RealTime: No table specified.\n");
353 /* Get the first parameter and first value in our list of passed paramater/value pairs */
354 newparam = va_arg(ap, const char *);
355 newval = va_arg(ap, const char *);
356 if(!newparam || !newval) {
357 ast_log(LOG_WARNING, "Postgresql RealTime: Realtime retrieval requires at least 1 parameter and 1 value to search on.\n");
366 /* Create the first part of the query using the first parameter/value pairs we just extracted
367 If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */
369 snprintf(sql, sizeof(sql), "UPDATE %s SET %s = '%s'", table, newparam, newval);
370 while((newparam = va_arg(ap, const char *))) {
371 newval = va_arg(ap, const char *);
372 snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), ", %s = '%s'", newparam, newval);
375 snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " WHERE %s = '%s'", keyfield, lookup);
377 ast_log(LOG_DEBUG,"Postgresql RealTime: Update SQL: %s\n", sql);
379 /* We now have our complete statement; Lets connect to the server and execute it. */
380 ast_mutex_lock(&pgsql_lock);
381 if(!pgsql_reconnect(database)) {
382 ast_mutex_unlock(&pgsql_lock);
386 if(!(result=PQexec(pgsqlConn, sql))) {
387 ast_log(LOG_WARNING, "Postgresql RealTime: Failed to query database. Check debug for more info.\n");
388 ast_log(LOG_DEBUG, "Postgresql RealTime: Query: %s\n", sql);
389 ast_log(LOG_DEBUG, "Postgresql RealTime: Query Failed because: %s\n", PQerrorMessage(pgsqlConn));
390 ast_mutex_unlock(&pgsql_lock);
394 ExecStatusType result_status=PQresultStatus(result);
395 if (result_status!=PGRES_COMMAND_OK
396 && result_status!=PGRES_TUPLES_OK
397 && result_status!=PGRES_NONFATAL_ERROR)
399 ast_log(LOG_WARNING, "Postgresql RealTime: Failed to query database. Check debug for more info.\n");
400 ast_log(LOG_DEBUG, "Postgresql RealTime: Query: %s\n", sql);
401 ast_log(LOG_DEBUG, "Postgresql RealTime: Query Failed because: %s (%s)\n",
402 PQresultErrorMessage(result),PQresStatus(result_status));
403 ast_mutex_unlock(&pgsql_lock);
408 numrows = atoi(PQcmdTuples(result));
409 ast_mutex_unlock(&pgsql_lock);
411 ast_log(LOG_DEBUG,"Postgresql RealTime: Updated %d rows on table: %s\n", numrows, table);
413 /* From http://dev.pgsql.com/doc/pgsql/en/pgsql-affected-rows.html
414 * An integer greater than zero indicates the number of rows affected
415 * Zero indicates that no records were updated
416 * -1 indicates that the query returned an error (although, if the query failed, it should have been caught above.)
425 static struct ast_config *config_pgsql(const char *database, const char *table, const char *file, struct ast_config *cfg)
427 PGresult *result = NULL;
429 struct ast_variable *new_v;
430 struct ast_category *cur_cat = NULL;
433 int last_cat_metric = 0;
437 if(!file || !strcmp(file, RES_CONFIG_PGSQL_CONF)) {
438 ast_log(LOG_WARNING, "Postgresql RealTime: Cannot configure myself.\n");
442 snprintf(sql, sizeof(sql), "SELECT category, var_name, var_val, cat_metric FROM %s WHERE filename='%s' and commented=0 ORDER BY filename, cat_metric desc, var_metric asc, category, var_name, var_val, id", table, file);
444 ast_log(LOG_DEBUG, "Postgresql RealTime: Static SQL: %s\n", sql);
446 /* We now have our complete statement; Lets connect to the server and execute it. */
447 ast_mutex_lock(&pgsql_lock);
448 if(!pgsql_reconnect(database)) {
449 ast_mutex_unlock(&pgsql_lock);
453 if(!(result=PQexec(pgsqlConn, sql))) {
454 ast_log(LOG_WARNING, "Postgresql RealTime: Failed to query database. Check debug for more info.\n");
455 ast_log(LOG_DEBUG, "Postgresql RealTime: Query: %s\n", sql);
456 ast_log(LOG_DEBUG, "Postgresql RealTime: Query Failed because: %s\n", PQerrorMessage(pgsqlConn));
457 ast_mutex_unlock(&pgsql_lock);
461 ExecStatusType result_status=PQresultStatus(result);
462 if (result_status!=PGRES_COMMAND_OK
463 && result_status!=PGRES_TUPLES_OK
464 && result_status!=PGRES_NONFATAL_ERROR)
466 ast_log(LOG_WARNING, "Postgresql RealTime: Failed to query database. Check debug for more info.\n");
467 ast_log(LOG_DEBUG, "Postgresql RealTime: Query: %s\n", sql);
468 ast_log(LOG_DEBUG, "Postgresql RealTime: Query Failed because: %s (%s)\n",
469 PQresultErrorMessage(result),PQresStatus(result_status));
470 ast_mutex_unlock(&pgsql_lock);
475 if((num_rows=PQntuples(result))>0) {
476 int numFields = PQnfields(result);
479 char** fieldnames=NULL;
481 ast_log(LOG_DEBUG, "Postgresql RealTime: Found %ld rows.\n", num_rows);
483 fieldnames=malloc(numFields*sizeof(char*));
485 /* If I can't alloc memory at this point, why bother doing anything else? */
486 ast_log(LOG_WARNING, "Out of memory!\n");
487 ast_mutex_unlock(&pgsql_lock);
491 for(i = 0; i < numFields; i++)
492 fieldnames[i]=PQfname(result,i);
494 for(rowIndex=0;rowIndex<num_rows;rowIndex++)
496 char* field_category=PQgetvalue(result,rowIndex,0);
497 char* field_var_name=PQgetvalue(result,rowIndex,1);
498 char* field_var_val=PQgetvalue(result,rowIndex,2);
499 char* field_cat_metric=PQgetvalue(result,rowIndex,3);
500 if(!strcmp(field_var_name, "#include")) {
501 if (!ast_config_internal_load(field_var_val, cfg)) {
503 ast_mutex_unlock(&pgsql_lock);
509 if(strcmp(last, field_category) || last_cat_metric != atoi(field_cat_metric)) {
510 cur_cat = ast_category_new(field_category);
512 ast_log(LOG_WARNING, "Out of memory!\n");
515 strcpy(last, field_category);
516 last_cat_metric = atoi(field_cat_metric);
517 ast_category_append(cfg, cur_cat);
519 new_v = ast_variable_new(field_var_name, field_var_val);
520 ast_variable_append(cur_cat, new_v);
523 ast_log(LOG_WARNING, "Postgresql RealTime: Could not find config '%s' in database.\n", file);
527 ast_mutex_unlock(&pgsql_lock);
532 static struct ast_config_engine pgsql_engine = {
534 .load_func = config_pgsql,
535 .realtime_func = realtime_pgsql,
536 .realtime_multi_func = realtime_multi_pgsql,
537 .update_func = update_pgsql
540 int load_module (void)
544 ast_mutex_lock(&pgsql_lock);
546 if(!pgsql_reconnect(NULL)) {
547 ast_log(LOG_WARNING, "Postgresql RealTime: Couldn't establish connection. Check debug.\n");
548 ast_log(LOG_DEBUG, "Postgresql RealTime: Cannot Connect: %s\n", PQerrorMessage(pgsqlConn));
551 ast_config_engine_register(&pgsql_engine);
553 ast_verbose("Postgresql RealTime driver loaded.\n");
555 ast_cli_register(&cli_realtime_pgsql_status);
557 ast_mutex_unlock(&pgsql_lock);
562 int unload_module (void)
564 /* Aquire control before doing anything to the module itself. */
565 ast_mutex_lock(&pgsql_lock);
572 ast_cli_unregister(&cli_realtime_pgsql_status);
573 ast_config_engine_deregister(&pgsql_engine);
575 ast_verbose("Postgresql RealTime unloaded.\n");
578 STANDARD_HANGUP_LOCALUSERS;
580 /* Unlock so something else can destroy the lock. */
581 ast_mutex_unlock(&pgsql_lock);
588 /* Aquire control before doing anything to the module itself. */
589 ast_mutex_lock(&pgsql_lock);
598 if(!pgsql_reconnect(NULL)) {
599 ast_log(LOG_WARNING, "Postgresql RealTime: Couldn't establish connection. Check debug.\n");
600 ast_log(LOG_DEBUG, "Postgresql RealTime: Cannot Connect: %s\n", PQerrorMessage(pgsqlConn));
603 ast_verbose(VERBOSE_PREFIX_2 "Postgresql RealTime reloaded.\n");
605 /* Done reloading. Release lock so others can now use driver. */
606 ast_mutex_unlock(&pgsql_lock);
611 int parse_config (void)
613 struct ast_config *config;
616 config = ast_config_load(RES_CONFIG_PGSQL_CONF);
619 if(!(s=ast_variable_retrieve(config, "general", "dbuser"))) {
620 ast_log(LOG_WARNING, "Postgresql RealTime: No database user found, using 'asterisk' as default.\n");
621 strncpy(dbuser, "asterisk", sizeof(dbuser) - 1);
623 strncpy(dbuser, s, sizeof(dbuser) - 1);
626 if(!(s=ast_variable_retrieve(config, "general", "dbpass"))) {
627 ast_log(LOG_WARNING, "Postgresql RealTime: No database password found, using 'asterisk' as default.\n");
628 strncpy(dbpass, "asterisk", sizeof(dbpass) - 1);
630 strncpy(dbpass, s, sizeof(dbpass) - 1);
633 if(!(s=ast_variable_retrieve(config, "general", "dbhost"))) {
634 ast_log(LOG_WARNING, "Postgresql RealTime: No database host found, using localhost via socket.\n");
637 strncpy(dbhost, s, sizeof(dbhost) - 1);
640 if(!(s=ast_variable_retrieve(config, "general", "dbname"))) {
641 ast_log(LOG_WARNING, "Postgresql RealTime: No database name found, using 'asterisk' as default.\n");
642 strncpy(dbname, "asterisk", sizeof(dbname) - 1);
644 strncpy(dbname, s, sizeof(dbname) - 1);
647 if(!(s=ast_variable_retrieve(config, "general", "dbport"))) {
648 ast_log(LOG_WARNING, "Postgresql RealTime: No database port found, using 5432 as default.\n");
654 if(dbhost && !(s=ast_variable_retrieve(config, "general", "dbsock"))) {
655 ast_log(LOG_WARNING, "Postgresql RealTime: No database socket found, using '/tmp/pgsql.sock' as default.\n");
656 strncpy(dbsock, "/tmp/pgsql.sock", sizeof(dbsock) - 1);
658 strncpy(dbsock, s, sizeof(dbsock) - 1);
661 ast_config_destroy(config);
664 ast_log(LOG_DEBUG, "Postgresql RealTime Host: %s\n", dbhost);
665 ast_log(LOG_DEBUG, "Postgresql RealTime Port: %i\n", dbport);
667 ast_log(LOG_DEBUG, "Postgresql RealTime Socket: %s\n", dbsock);
669 ast_log(LOG_DEBUG, "Postgresql RealTime User: %s\n", dbuser);
670 ast_log(LOG_DEBUG, "Postgresql RealTime Password: %s\n", dbpass);
671 ast_log(LOG_DEBUG, "Postgresql RealTime DBName: %s\n", dbname);
676 char *description (void)
678 return res_config_pgsql_desc;
683 /* Try and get a lock. If unsuccessful, than that means another thread is using the pgsql object. */
684 if(ast_mutex_trylock(&pgsql_lock)) {
685 ast_log(LOG_DEBUG, "Postgresql RealTime: Module usage count is 1.\n");
688 ast_mutex_unlock(&pgsql_lock);
694 return ASTERISK_GPL_KEY;
697 static int pgsql_reconnect(const char *database)
699 char my_database[50];
701 if(!database || ast_strlen_zero(database))
702 ast_copy_string(my_database, dbname, sizeof(my_database));
704 ast_copy_string(my_database, database, sizeof(my_database));
706 /* mutex lock should have been locked before calling this function. */
708 if (pgsqlConn && PQstatus(pgsqlConn) != CONNECTION_OK) {
713 if((!pgsqlConn) && (dbhost || dbsock) && dbuser && dbpass && my_database) {
715 unsigned int size=100
719 +strlen(my_database);
720 connInfo=malloc(size);
723 ast_log(LOG_WARNING, "Postgresql RealTime: Insufficient memory to allocate Pgsql resource.\n");
728 sprintf(connInfo,"host=%s port=%d dbname=%s user=%s password=%s",
729 dbhost,dbport,my_database,dbuser,dbpass);
730 ast_log(LOG_DEBUG, "%u connInfo=%s\n", size,connInfo);
731 pgsqlConn=PQconnectdb(connInfo);
732 ast_log(LOG_DEBUG, "%u connInfo=%s\n", size,connInfo);
735 ast_log(LOG_DEBUG, "pgsqlConn=%p\n", pgsqlConn);
738 ast_log(LOG_DEBUG, "Postgresql RealTime: Successfully connected to database.\n");
739 connect_time = time(NULL);
742 ast_log(LOG_ERROR, "Postgresql RealTime: Failed to connect database server %s on %s. Check debug for more info.\n", dbname, dbhost);
743 ast_log(LOG_DEBUG, "Postgresql RealTime: Cannot Connect: %s\n", PQresultErrorMessage(NULL));
749 ast_log(LOG_DEBUG, "Postgresql RealTime: Everything is fine.\n");
754 static int realtime_pgsql_status(int fd, int argc, char **argv)
756 char status[256], status2[100] = "";
757 int ctime = time(NULL) - connect_time;
759 if(pgsqlConn && PQstatus(pgsqlConn) == CONNECTION_OK) {
761 snprintf(status, 255, "Connected to %s@%s, port %d", dbname, dbhost, dbport);
763 snprintf(status, 255, "Connected to %s on socket file %s", dbname, dbsock);
765 snprintf(status, 255, "Connected to %s@%s", dbname, dbhost);
768 if(dbuser && *dbuser) {
769 snprintf(status2, 99, " with username %s", dbuser);
772 if (ctime > 31536000) {
773 ast_cli(fd, "%s%s for %d years, %d days, %d hours, %d minutes, %d seconds.\n", status, status2, ctime / 31536000, (ctime % 31536000) / 86400, (ctime % 86400) / 3600, (ctime % 3600) / 60, ctime % 60);
774 } else if (ctime > 86400) {
775 ast_cli(fd, "%s%s for %d days, %d hours, %d minutes, %d seconds.\n", status, status2, ctime / 86400, (ctime % 86400) / 3600, (ctime % 3600) / 60, ctime % 60);
776 } else if (ctime > 3600) {
777 ast_cli(fd, "%s%s for %d hours, %d minutes, %d seconds.\n", status, status2, ctime / 3600, (ctime % 3600) / 60, ctime % 60);
778 } else if (ctime > 60) {
779 ast_cli(fd, "%s%s for %d minutes, %d seconds.\n", status, status2, ctime / 60, ctime % 60);
781 ast_cli(fd, "%s%s for %d seconds.\n", status, status2, ctime);
784 return RESULT_SUCCESS;
786 return RESULT_FAILURE;