From 383b0739669d284900efe6f3f01b9648548770b0 Mon Sep 17 00:00:00 2001 From: Olle Johansson Date: Thu, 29 Sep 2011 12:03:23 +0000 Subject: Add CLI command "cdr show pgsql status" based on "cdr mysql status" Review: https://reviewboard.asterisk.org/r/923/ Thanks all for the code reviews and feedback. git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@338415 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- cdr/cdr_pgsql.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) (limited to 'cdr') diff --git a/cdr/cdr_pgsql.c b/cdr/cdr_pgsql.c index e857baa87..b26e7dac4 100644 --- a/cdr/cdr_pgsql.c +++ b/cdr/cdr_pgsql.c @@ -47,6 +47,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/config.h" #include "asterisk/channel.h" #include "asterisk/cdr.h" +#include "asterisk/cli.h" #include "asterisk/module.h" #define DATE_FORMAT "'%Y-%m-%d %T'" @@ -56,6 +57,14 @@ static const char config[] = "cdr_pgsql.conf"; static char *pghostname = NULL, *pgdbname = NULL, *pgdbuser = NULL, *pgpassword = NULL, *pgdbport = NULL, *table = NULL, *encoding = NULL, *tz = NULL; static int connected = 0; static int maxsize = 512, maxsize2 = 512; +static time_t connect_time = 0; +static int totalrecords = 0; +static int records; + +static char *handle_cdr_pgsql_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a); +static struct ast_cli_entry cdr_pgsql_status_cli[] = { + AST_CLI_DEFINE(handle_cdr_pgsql_status, "Show connection status of the PostgreSQL CDR driver (cdr_pgsql)"), +}; AST_MUTEX_DEFINE_STATIC(pgsql_lock); @@ -99,6 +108,61 @@ static AST_RWLIST_HEAD_STATIC(psql_columns, columns); } \ } while (0) +/*! \brief Handle the CLI command cdr show pgsql status */ +static char *handle_cdr_pgsql_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) +{ + switch (cmd) { + case CLI_INIT: + e->command = "cdr show pgsql status"; + e->usage = + "Usage: cdr show pgsql status\n" + " Shows current connection status for cdr_pgsql\n"; + return NULL; + case CLI_GENERATE: + return NULL; + } + + if (a->argc != 3) + return CLI_SHOWUSAGE; + + if (connected) { + char status[256], status2[100] = ""; + int ctime = time(NULL) - connect_time; + + if (pgdbport) { + snprintf(status, 255, "Connected to %s@%s, port %s", pgdbname, pghostname, pgdbport); + } else { + snprintf(status, 255, "Connected to %s@%s", pgdbname, pghostname); + } + + if (pgdbuser && *pgdbuser) { + snprintf(status2, 99, " with username %s", pgdbuser); + } + if (table && *table) { + snprintf(status2, 99, " using table %s", table); + } + if (ctime > 31536000) { + ast_cli(a->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); + } else if (ctime > 86400) { + ast_cli(a->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); + } else if (ctime > 3600) { + ast_cli(a->fd, "%s%s for %d hours, %d minutes, %d seconds.\n", status, status2, ctime / 3600, (ctime % 3600) / 60, ctime % 60); + } else if (ctime > 60) { + ast_cli(a->fd, "%s%s for %d minutes, %d seconds.\n", status, status2, ctime / 60, ctime % 60); + } else { + ast_cli(a->fd, "%s%s for %d seconds.\n", status, status2, ctime); + } + if (records == totalrecords) { + ast_cli(a->fd, " Wrote %d records since last restart.\n", totalrecords); + } else { + ast_cli(a->fd, " Wrote %d records since last restart and %d records since last reconnect.\n", totalrecords, records); + } + } else { + ast_cli(a->fd, "Not currently connected to a PgSQL server.\n"); + } + return CLI_SUCCESS; +} + static int pgsql_log(struct ast_cdr *cdr) { struct ast_tm tm; @@ -111,6 +175,8 @@ static int pgsql_log(struct ast_cdr *cdr) conn = PQsetdbLogin(pghostname, pgdbport, NULL, NULL, pgdbname, pgdbuser, pgpassword); if (PQstatus(conn) != CONNECTION_BAD) { connected = 1; + connect_time = time(NULL); + records = 0; if (PQsetClientEncoding(conn, encoding)) { #ifdef HAVE_PGSQL_pg_encoding_to_char ast_log(LOG_WARNING, "Failed to set encoding to '%s'. Encoding set to default '%s'\n", encoding, pg_encoding_to_char(PQclientEncoding(conn))); @@ -289,6 +355,8 @@ static int pgsql_log(struct ast_cdr *cdr) if (PQstatus(conn) == CONNECTION_OK) { ast_log(LOG_ERROR, "Connection reestablished.\n"); connected = 1; + connect_time = time(NULL); + records = 0; } else { pgerror = PQerrorMessage(conn); ast_log(LOG_ERROR, "Unable to reconnect to database server %s. Calls will not be logged!\n", pghostname); @@ -312,12 +380,21 @@ static int pgsql_log(struct ast_cdr *cdr) if (PQstatus(conn) == CONNECTION_OK) { ast_log(LOG_ERROR, "Connection reestablished.\n"); connected = 1; + connect_time = time(NULL); + records = 0; PQclear(result); result = PQexec(conn, ast_str_buffer(sql)); if (PQresultStatus(result) != PGRES_COMMAND_OK) { pgerror = PQresultErrorMessage(result); ast_log(LOG_ERROR, "HARD ERROR! Attempted reconnection failed. DROPPING CALL RECORD!\n"); ast_log(LOG_ERROR, "Reason: %s\n", pgerror); + } else { + /* Second try worked out ok */ + totalrecords++; + records++; + ast_mutex_unlock(&pgsql_lock); + PQclear(result); + return 0; } } ast_mutex_unlock(&pgsql_lock); @@ -325,6 +402,9 @@ static int pgsql_log(struct ast_cdr *cdr) ast_free(sql); ast_free(sql2); return -1; + } else { + totalrecords++; + records++; } PQclear(result); ast_free(sql); @@ -339,6 +419,7 @@ static int unload_module(void) struct columns *current; ast_cdr_unregister(name); + ast_cli_unregister_multiple(cdr_pgsql_status_cli, ARRAY_LEN(cdr_pgsql_status_cli)); PQfinish(conn); @@ -524,6 +605,8 @@ static int config_module(int reload) int i, rows, version; ast_debug(1, "Successfully connected to PostgreSQL database.\n"); connected = 1; + connect_time = time(NULL); + records = 0; if (PQsetClientEncoding(conn, encoding)) { #ifdef HAVE_PGSQL_pg_encoding_to_char ast_log(LOG_WARNING, "Failed to set encoding to '%s'. Encoding set to default '%s'\n", encoding, pg_encoding_to_char(PQclientEncoding(conn))); @@ -641,6 +724,7 @@ static int config_module(int reload) static int load_module(void) { + ast_cli_register_multiple(cdr_pgsql_status_cli, sizeof(cdr_pgsql_status_cli) / sizeof(struct ast_cli_entry)); return config_module(0) ? AST_MODULE_LOAD_DECLINE : 0; } -- cgit v1.2.3