Add CLI command "cdr show pgsql status" based on "cdr mysql status"
authorOlle Johansson <oej@edvina.net>
Thu, 29 Sep 2011 12:03:23 +0000 (12:03 +0000)
committerOlle Johansson <oej@edvina.net>
Thu, 29 Sep 2011 12:03:23 +0000 (12:03 +0000)
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

CHANGES
cdr/cdr_pgsql.c

diff --git a/CHANGES b/CHANGES
index e338252..76a9016 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -36,6 +36,11 @@ Queue changes
  * Added queue options autopausebusy and autopauseunavail for automatically
    pausing a queue member when their device reports busy or congestion.
 
+CDR postgresql driver changes
+-----------------------------
+ * Added command "cdr show pgsql status" to check connection status
+
+
 ------------------------------------------------------------------------------
 --- Functionality changes from Asterisk 1.8 to Asterisk 10 -------------------
 ------------------------------------------------------------------------------
index e857baa..b26e7da 100644 (file)
@@ -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;
 }