Codename Pineapple

Home page | Mailing list | Docs

Last updated: Sat Feb 3 05:01:44 2007

Asterisk developer's documentation :: Codename Pineapple


res_config_pgsql.c File Reference


Detailed Description

Postgresql plugin for Asterisk RealTime Architecture.

Author:
Mark Spencer <markster@digium.com>

Manuel Guesdon <mguesdon@oxymium.net> - Postgresql RealTime Driver Author/Adaptor

Definition in file res_config_pgsql.c.

#include "asterisk.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <libpq-fe.h>
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/config.h"
#include "asterisk/module.h"
#include "asterisk/lock.h"
#include "asterisk/options.h"
#include "asterisk/utils.h"
#include "asterisk/cli.h"

Include dependency graph for res_config_pgsql.c:

Go to the source code of this file.

Defines

#define MAX_DB_OPTION_SIZE   64
#define RES_CONFIG_PGSQL_CONF   "res_pgsql.conf"

Functions

 AST_MODULE_INFO (ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS,"PostgreSQL RealTime Configuration Driver",.load=load_module,.unload=unload_module,.reload=reload)
 AST_MUTEX_DEFINE_STATIC (pgsql_lock)
static struct ast_configconfig_pgsql (const char *database, const char *table, const char *file, struct ast_config *cfg, int withcomments)
static int load_module (void)
static int parse_config (void)
static int pgsql_reconnect (const char *database)
static struct ast_configrealtime_multi_pgsql (const char *database, const char *table, va_list ap)
static struct ast_variablerealtime_pgsql (const char *database, const char *table, va_list ap)
static int realtime_pgsql_status (int fd, int argc, char **argv)
static int reload (void)
static int unload_module (void)
static int update_pgsql (const char *database, const char *table, const char *keyfield, const char *lookup, va_list ap)

Variables

static struct ast_cli_entry cli_realtime []
static const char cli_realtime_pgsql_status_usage []
static time_t connect_time = 0
static char dbhost [MAX_DB_OPTION_SIZE] = ""
static char dbname [MAX_DB_OPTION_SIZE] = ""
static char dbpass [MAX_DB_OPTION_SIZE] = ""
static int dbport = 5432
static char dbsock [MAX_DB_OPTION_SIZE] = ""
static char dbuser [MAX_DB_OPTION_SIZE] = ""
static struct ast_config_engine pgsql_engine
PGconn * pgsqlConn = NULL


Define Documentation

#define MAX_DB_OPTION_SIZE   64
 

Definition at line 55 of file res_config_pgsql.c.

#define RES_CONFIG_PGSQL_CONF   "res_pgsql.conf"
 

Definition at line 51 of file res_config_pgsql.c.

Referenced by config_pgsql(), and parse_config().


Function Documentation

AST_MODULE_INFO ASTERISK_GPL_KEY  ,
AST_MODFLAG_GLOBAL_SYMBOLS  ,
"PostgreSQL RealTime Configuration Driver"  ,
load = load_module,
unload = unload_module,
reload = reload
 

AST_MUTEX_DEFINE_STATIC pgsql_lock   ) 
 

static struct ast_config* config_pgsql const char *  database,
const char *  table,
const char *  file,
struct ast_config cfg,
int  withcomments
[static]
 

Definition at line 457 of file res_config_pgsql.c.

References ast_calloc, ast_category_append(), ast_category_new(), ast_config_internal_load(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_variable_append(), ast_variable_new(), last, LOG_DEBUG, LOG_WARNING, option_debug, pgsql_reconnect(), pgsqlConn, and RES_CONFIG_PGSQL_CONF.

00460 {
00461    PGresult *result = NULL;
00462    long num_rows;
00463    struct ast_variable *new_v;
00464    struct ast_category *cur_cat = NULL;
00465    char sql[250] = "";
00466    char last[80] = "";
00467    int last_cat_metric = 0;
00468 
00469    last[0] = '\0';
00470 
00471    if (!file || !strcmp(file, RES_CONFIG_PGSQL_CONF)) {
00472       ast_log(LOG_WARNING, "Postgresql RealTime: Cannot configure myself.\n");
00473       return NULL;
00474    }
00475 
00476    snprintf(sql, sizeof(sql),
00477           "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",
00478           table, file);
00479 
00480    if (option_debug)
00481       ast_log(LOG_DEBUG, "Postgresql RealTime: Static SQL: %s\n", sql);
00482 
00483    /* We now have our complete statement; Lets connect to the server and execute it. */
00484    ast_mutex_lock(&pgsql_lock);
00485    if (!pgsql_reconnect(database)) {
00486       ast_mutex_unlock(&pgsql_lock);
00487       return NULL;
00488    }
00489 
00490    if (!(result = PQexec(pgsqlConn, sql))) {
00491       ast_log(LOG_WARNING,
00492             "Postgresql RealTime: Failed to query database. Check debug for more info.\n");
00493       if (option_debug) {
00494          ast_log(LOG_DEBUG, "Postgresql RealTime: Query: %s\n", sql);
00495          ast_log(LOG_DEBUG, "Postgresql RealTime: Query Failed because: %s\n",
00496                PQerrorMessage(pgsqlConn));
00497       }
00498       ast_mutex_unlock(&pgsql_lock);
00499       return NULL;
00500    } else {
00501       ExecStatusType result_status = PQresultStatus(result);
00502       if (result_status != PGRES_COMMAND_OK
00503          && result_status != PGRES_TUPLES_OK
00504          && result_status != PGRES_NONFATAL_ERROR) {
00505          ast_log(LOG_WARNING,
00506                "Postgresql RealTime: Failed to query database. Check debug for more info.\n");
00507          if (option_debug) {
00508             ast_log(LOG_DEBUG, "Postgresql RealTime: Query: %s\n", sql);
00509             ast_log(LOG_DEBUG, "Postgresql RealTime: Query Failed because: %s (%s)\n",
00510                   PQresultErrorMessage(result), PQresStatus(result_status));
00511          }
00512          ast_mutex_unlock(&pgsql_lock);
00513          return NULL;
00514       }
00515    }
00516 
00517    if ((num_rows = PQntuples(result)) > 0) {
00518       int numFields = PQnfields(result);
00519       int i = 0;
00520       int rowIndex = 0;
00521       char **fieldnames = NULL;
00522 
00523       if (option_debug)
00524          ast_log(LOG_DEBUG, "Postgresql RealTime: Found %ld rows.\n", num_rows);
00525 
00526       if (!(fieldnames = ast_calloc(1, numFields * sizeof(char *)))) {
00527          ast_mutex_unlock(&pgsql_lock);
00528          PQclear(result);
00529          return NULL;
00530       }
00531       for (i = 0; i < numFields; i++)
00532          fieldnames[i] = PQfname(result, i);
00533 
00534       for (rowIndex = 0; rowIndex < num_rows; rowIndex++) {
00535          char *field_category = PQgetvalue(result, rowIndex, 0);
00536          char *field_var_name = PQgetvalue(result, rowIndex, 1);
00537          char *field_var_val = PQgetvalue(result, rowIndex, 2);
00538          char *field_cat_metric = PQgetvalue(result, rowIndex, 3);
00539          if (!strcmp(field_var_name, "#include")) {
00540             if (!ast_config_internal_load(field_var_val, cfg, 0)) {
00541                PQclear(result);
00542                ast_mutex_unlock(&pgsql_lock);
00543                return NULL;
00544             }
00545             continue;
00546          }
00547 
00548          if (strcmp(last, field_category) || last_cat_metric != atoi(field_cat_metric)) {
00549             cur_cat = ast_category_new(field_category);
00550             if (!cur_cat)
00551                break;
00552             strcpy(last, field_category);
00553             last_cat_metric = atoi(field_cat_metric);
00554             ast_category_append(cfg, cur_cat);
00555          }
00556          new_v = ast_variable_new(field_var_name, field_var_val);
00557          ast_variable_append(cur_cat, new_v);
00558       }
00559    } else {
00560       ast_log(LOG_WARNING,
00561             "Postgresql RealTime: Could not find config '%s' in database.\n", file);
00562    }
00563 
00564    PQclear(result);
00565    ast_mutex_unlock(&pgsql_lock);
00566 
00567    return cfg;
00568 }

static int load_module void   )  [static]
 

Definition at line 578 of file res_config_pgsql.c.

References ast_cli_register_multiple(), ast_config_engine_register(), ast_log(), AST_MODULE_LOAD_DECLINE, ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), cli_realtime, LOG_DEBUG, LOG_WARNING, option_debug, option_verbose, parse_config(), pgsql_engine, pgsql_reconnect(), and pgsqlConn.

00579 {
00580    if(!parse_config())
00581       return AST_MODULE_LOAD_DECLINE;
00582 
00583    ast_mutex_lock(&pgsql_lock);
00584 
00585    if (!pgsql_reconnect(NULL)) {
00586       ast_log(LOG_WARNING,
00587             "Postgresql RealTime: Couldn't establish connection. Check debug.\n");
00588       if (option_debug)
00589          ast_log(LOG_DEBUG, "Postgresql RealTime: Cannot Connect: %s\n",
00590                PQerrorMessage(pgsqlConn));
00591    }
00592 
00593    ast_config_engine_register(&pgsql_engine);
00594    if (option_verbose) {
00595       ast_verbose("Postgresql RealTime driver loaded.\n");
00596    }
00597    ast_cli_register_multiple(cli_realtime, sizeof(cli_realtime) / sizeof(struct ast_cli_entry));
00598 
00599    ast_mutex_unlock(&pgsql_lock);
00600 
00601    return 0;
00602 }

static int parse_config void   )  [static]
 

Definition at line 654 of file res_config_pgsql.c.

References ast_config_destroy(), ast_config_load(), ast_log(), ast_variable_retrieve(), config, dbhost, dbname, dbpass, dbport, dbsock, dbuser, LOG_DEBUG, LOG_WARNING, option_debug, RES_CONFIG_PGSQL_CONF, and s.

Referenced by load_module(), and reload().

00655 {
00656    struct ast_config *config;
00657    const char *s;
00658 
00659    config = ast_config_load(RES_CONFIG_PGSQL_CONF);
00660 
00661    if (!config) {
00662       ast_log(LOG_WARNING, "Unable to load config %s\n",RES_CONFIG_PGSQL_CONF);
00663       return 0;
00664    }
00665    if (!(s = ast_variable_retrieve(config, "general", "dbuser"))) {
00666       ast_log(LOG_WARNING,
00667             "Postgresql RealTime: No database user found, using 'asterisk' as default.\n");
00668       strcpy(dbuser, "asterisk");
00669    } else {
00670       ast_copy_string(dbuser, s, sizeof(dbuser));
00671    }
00672 
00673    if (!(s = ast_variable_retrieve(config, "general", "dbpass"))) {
00674       ast_log(LOG_WARNING,
00675             "Postgresql RealTime: No database password found, using 'asterisk' as default.\n");
00676       strcpy(dbpass, "asterisk");
00677    } else {
00678       ast_copy_string(dbpass, s, sizeof(dbpass));
00679    }
00680 
00681    if (!(s = ast_variable_retrieve(config, "general", "dbhost"))) {
00682       ast_log(LOG_WARNING,
00683             "Postgresql RealTime: No database host found, using localhost via socket.\n");
00684       dbhost[0] = '\0';
00685    } else {
00686       ast_copy_string(dbhost, s, sizeof(dbhost));
00687    }
00688 
00689    if (!(s = ast_variable_retrieve(config, "general", "dbname"))) {
00690       ast_log(LOG_WARNING,
00691             "Postgresql RealTime: No database name found, using 'asterisk' as default.\n");
00692       strcpy(dbname, "asterisk");
00693    } else {
00694       ast_copy_string(dbname, s, sizeof(dbname));
00695    }
00696 
00697    if (!(s = ast_variable_retrieve(config, "general", "dbport"))) {
00698       ast_log(LOG_WARNING,
00699             "Postgresql RealTime: No database port found, using 5432 as default.\n");
00700       dbport = 5432;
00701    } else {
00702       dbport = atoi(s);
00703    }
00704 
00705    if (dbhost && !(s = ast_variable_retrieve(config, "general", "dbsock"))) {
00706       ast_log(LOG_WARNING,
00707             "Postgresql RealTime: No database socket found, using '/tmp/pgsql.sock' as default.\n");
00708       strcpy(dbsock, "/tmp/pgsql.sock");
00709    } else {
00710       ast_copy_string(dbsock, s, sizeof(dbsock));
00711    }
00712    ast_config_destroy(config);
00713 
00714    if (option_debug) {
00715       if (dbhost) {
00716          ast_log(LOG_DEBUG, "Postgresql RealTime Host: %s\n", dbhost);
00717          ast_log(LOG_DEBUG, "Postgresql RealTime Port: %i\n", dbport);
00718       } else {
00719          ast_log(LOG_DEBUG, "Postgresql RealTime Socket: %s\n", dbsock);
00720       }
00721       ast_log(LOG_DEBUG, "Postgresql RealTime User: %s\n", dbuser);
00722       ast_log(LOG_DEBUG, "Postgresql RealTime Password: %s\n", dbpass);
00723       ast_log(LOG_DEBUG, "Postgresql RealTime DBName: %s\n", dbname);
00724    }
00725 
00726    return 1;
00727 }

static int pgsql_reconnect const char *  database  )  [static]
 

Definition at line 729 of file res_config_pgsql.c.

References ast_log(), ast_malloc, connect_time, dbhost, dbname, dbpass, dbport, dbsock, dbuser, free, LOG_DEBUG, LOG_ERROR, option_debug, pgsqlConn, and S_OR.

Referenced by config_pgsql(), load_module(), realtime_multi_pgsql(), realtime_pgsql(), reload(), and update_pgsql().

00730 {
00731    char my_database[50];
00732 
00733    ast_copy_string(my_database, S_OR(database, dbname), sizeof(my_database));
00734 
00735    /* mutex lock should have been locked before calling this function. */
00736 
00737    if (pgsqlConn && PQstatus(pgsqlConn) != CONNECTION_OK) {
00738       PQfinish(pgsqlConn);
00739       pgsqlConn = NULL;
00740    }
00741 
00742    if ((!pgsqlConn) && (dbhost || dbsock) && dbuser && dbpass && my_database) {
00743       char *connInfo = NULL;
00744       unsigned int size = 100 + strlen(dbhost)
00745          + strlen(dbuser)
00746          + strlen(dbpass)
00747          + strlen(my_database);
00748       
00749       if (!(connInfo = ast_malloc(size)))
00750          return 0;
00751       
00752       sprintf(connInfo, "host=%s port=%d dbname=%s user=%s password=%s",
00753                dbhost, dbport, my_database, dbuser, dbpass);
00754       if (option_debug)
00755          ast_log(LOG_DEBUG, "%u connInfo=%s\n", size, connInfo);
00756       pgsqlConn = PQconnectdb(connInfo);
00757       if (option_debug)
00758          ast_log(LOG_DEBUG, "%u connInfo=%s\n", size, connInfo);
00759       free(connInfo);
00760       connInfo = NULL;
00761       if (option_debug)
00762          ast_log(LOG_DEBUG, "pgsqlConn=%p\n", pgsqlConn);
00763       if (pgsqlConn && PQstatus(pgsqlConn) == CONNECTION_OK) {
00764          if (option_debug)
00765             ast_log(LOG_DEBUG, "Postgresql RealTime: Successfully connected to database.\n");
00766          connect_time = time(NULL);
00767          return 1;
00768       } else {
00769          ast_log(LOG_ERROR,
00770                "Postgresql RealTime: Failed to connect database server %s on %s. Check debug for more info.\n",
00771                dbname, dbhost);
00772          if (option_debug)
00773             ast_log(LOG_DEBUG, "Postgresql RealTime: Cannot Connect: %s\n",
00774                   PQresultErrorMessage(NULL));
00775          return 0;
00776       }
00777    } else {
00778       if (option_debug)
00779          ast_log(LOG_DEBUG, "Postgresql RealTime: Everything is fine.\n");
00780       return 1;
00781    }
00782 }

static struct ast_config* realtime_multi_pgsql const char *  database,
const char *  table,
va_list  ap
[static]
 

Definition at line 208 of file res_config_pgsql.c.

References ast_calloc, ast_category_new(), ast_category_rename(), ast_config_new(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_strdupa, ast_strlen_zero(), ast_variable_append(), ast_variable_new(), LOG_DEBUG, LOG_WARNING, option_debug, pgsql_reconnect(), pgsqlConn, strsep(), and var.

00209 {
00210    PGresult *result = NULL;
00211    int num_rows = 0;
00212    char sql[256];
00213    const char *initfield = NULL;
00214    char *stringp;
00215    char *chunk;
00216    char *op;
00217    const char *newparam, *newval;
00218    struct ast_realloca ra;
00219    struct ast_variable *var = NULL;
00220    struct ast_config *cfg = NULL;
00221    struct ast_category *cat = NULL;
00222 
00223    if (!table) {
00224       ast_log(LOG_WARNING, "Postgresql RealTime: No table specified.\n");
00225       return NULL;
00226    }
00227 
00228    memset(&ra, 0, sizeof(ra));
00229 
00230    if (!(cfg = ast_config_new()))
00231       return NULL;
00232 
00233    /* Get the first parameter and first value in our list of passed paramater/value pairs */
00234    newparam = va_arg(ap, const char *);
00235    newval = va_arg(ap, const char *);
00236    if (!newparam || !newval) {
00237       ast_log(LOG_WARNING,
00238             "Postgresql RealTime: Realtime retrieval requires at least 1 parameter and 1 value to search on.\n");
00239       if (pgsqlConn) {
00240          PQfinish(pgsqlConn);
00241          pgsqlConn = NULL;
00242       };
00243       return NULL;
00244    }
00245 
00246    initfield = ast_strdupa(newparam);
00247    if ((op = strchr(initfield, ' '))) {
00248       *op = '\0';
00249    }
00250 
00251    /* Create the first part of the query using the first parameter/value pairs we just extracted
00252       If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */
00253 
00254    if (!strchr(newparam, ' '))
00255       op = " =";
00256    else
00257       op = "";
00258 
00259    snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s '%s'", table, newparam, op,
00260           newval);
00261    while ((newparam = va_arg(ap, const char *))) {
00262       newval = va_arg(ap, const char *);
00263       if (!strchr(newparam, ' '))
00264          op = " =";
00265       else
00266          op = "";
00267       snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s '%s'", newparam,
00268              op, newval);
00269    }
00270 
00271    if (initfield) {
00272       snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " ORDER BY %s", initfield);
00273    }
00274 
00275    va_end(ap);
00276 
00277    /* We now have our complete statement; Lets connect to the server and execute it. */
00278    ast_mutex_lock(&pgsql_lock);
00279    if (!pgsql_reconnect(database)) {
00280       ast_mutex_unlock(&pgsql_lock);
00281       return NULL;
00282    }
00283 
00284    if (!(result = PQexec(pgsqlConn, sql))) {
00285       ast_log(LOG_WARNING,
00286             "Postgresql RealTime: Failed to query database. Check debug for more info.\n");
00287       if (option_debug) {
00288          ast_log(LOG_DEBUG, "Postgresql RealTime: Query: %s\n", sql);
00289          ast_log(LOG_DEBUG, "Postgresql RealTime: Query Failed because: %s\n",
00290                PQerrorMessage(pgsqlConn));
00291       }
00292       ast_mutex_unlock(&pgsql_lock);
00293       return NULL;
00294    } else {
00295       ExecStatusType result_status = PQresultStatus(result);
00296       if (result_status != PGRES_COMMAND_OK
00297          && result_status != PGRES_TUPLES_OK
00298          && result_status != PGRES_NONFATAL_ERROR) {
00299          ast_log(LOG_WARNING,
00300                "Postgresql RealTime: Failed to query database. Check debug for more info.\n");
00301          if (option_debug) {
00302             ast_log(LOG_DEBUG, "Postgresql RealTime: Query: %s\n", sql);
00303             ast_log(LOG_DEBUG, "Postgresql RealTime: Query Failed because: %s (%s)\n",
00304                   PQresultErrorMessage(result), PQresStatus(result_status));
00305          }
00306          ast_mutex_unlock(&pgsql_lock);
00307          return NULL;
00308       }
00309    }
00310 
00311    if (option_debug)
00312       ast_log(LOG_DEBUG, "2Postgresql RealTime: Result=%p Query: %s\n", result, sql);
00313 
00314    if ((num_rows = PQntuples(result)) > 0) {
00315       int numFields = PQnfields(result);
00316       int i = 0;
00317       int rowIndex = 0;
00318       char **fieldnames = NULL;
00319 
00320       if (option_debug)
00321          ast_log(LOG_DEBUG, "Postgresql RealTime: Found %d rows.\n", num_rows);
00322 
00323       if (!(fieldnames = ast_calloc(1, numFields * sizeof(char *)))) {
00324          ast_mutex_unlock(&pgsql_lock);
00325          PQclear(result);
00326          return NULL;
00327       }
00328       for (i = 0; i < numFields; i++)
00329          fieldnames[i] = PQfname(result, i);
00330 
00331       for (rowIndex = 0; rowIndex < num_rows; rowIndex++) {
00332          var = NULL;
00333          if (!(cat = ast_category_new("")))
00334             continue;
00335          for (i = 0; i < numFields; i++) {
00336             stringp = PQgetvalue(result, rowIndex, i);
00337             while (stringp) {
00338                chunk = strsep(&stringp, ";");
00339                if (chunk && !ast_strlen_zero(ast_strip(chunk))) {
00340                   if (initfield && !strcmp(initfield, fieldnames[i])) {
00341                      ast_category_rename(cat, chunk);
00342                   }
00343                   var = ast_variable_new(fieldnames[i], chunk);
00344                   ast_variable_append(cat, var);
00345                }
00346             }
00347          }
00348          ast_category_append(cfg, cat);
00349       }
00350       free(fieldnames);
00351    } else {
00352       ast_log(LOG_WARNING,
00353             "Postgresql RealTime: Could not find any rows in table %s.\n", table);
00354    }
00355 
00356    ast_mutex_unlock(&pgsql_lock);
00357    PQclear(result);
00358 
00359    return cfg;
00360 }

static struct ast_variable* realtime_pgsql const char *  database,
const char *  table,
va_list  ap
[static]
 

Definition at line 79 of file res_config_pgsql.c.

References ast_calloc, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), ast_variable_new(), LOG_DEBUG, LOG_WARNING, ast_variable::next, option_debug, pgsql_reconnect(), strsep(), and var.

00080 {
00081    PGresult *result = NULL;
00082    int num_rows = 0;
00083    char sql[256];
00084    char *stringp;
00085    char *chunk;
00086    char *op;
00087    const char *newparam, *newval;
00088    struct ast_variable *var = NULL, *prev = NULL;
00089 
00090    if (!table) {
00091       ast_log(LOG_WARNING, "Postgresql RealTime: No table specified.\n");
00092       return NULL;
00093    }
00094 
00095    /* Get the first parameter and first value in our list of passed paramater/value pairs */
00096    newparam = va_arg(ap, const char *);
00097    newval = va_arg(ap, const char *);
00098    if (!newparam || !newval) {
00099       ast_log(LOG_WARNING,
00100             "Postgresql RealTime: Realtime retrieval requires at least 1 parameter and 1 value to search on.\n");
00101       if (pgsqlConn) {
00102          PQfinish(pgsqlConn);
00103          pgsqlConn = NULL;
00104       };
00105       return NULL;
00106    }
00107 
00108    /* Create the first part of the query using the first parameter/value pairs we just extracted
00109       If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */
00110    op = strchr(newparam, ' ') ? "" : " =";
00111 
00112    snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s '%s'", table, newparam, op,
00113           newval);
00114    while ((newparam = va_arg(ap, const char *))) {
00115       newval = va_arg(ap, const char *);
00116       if (!strchr(newparam, ' '))
00117          op = " =";
00118       else
00119          op = "";
00120       snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s '%s'", newparam,
00121              op, newval);
00122    }
00123    va_end(ap);
00124 
00125    /* We now have our complete statement; Lets connect to the server and execute it. */
00126    ast_mutex_lock(&pgsql_lock);
00127    if (!pgsql_reconnect(database)) {
00128       ast_mutex_unlock(&pgsql_lock);
00129       return NULL;
00130    }
00131 
00132    if (!(result = PQexec(pgsqlConn, sql))) {
00133       ast_log(LOG_WARNING,
00134             "Postgresql RealTime: Failed to query database. Check debug for more info.\n");
00135       if (option_debug) {
00136          ast_log(LOG_DEBUG, "Postgresql RealTime: Query: %s\n", sql);
00137          ast_log(LOG_DEBUG, "Postgresql RealTime: Query Failed because: %s\n",
00138                PQerrorMessage(pgsqlConn));
00139       }
00140       ast_mutex_unlock(&pgsql_lock);
00141       return NULL;
00142    } else {
00143       ExecStatusType result_status = PQresultStatus(result);
00144       if (result_status != PGRES_COMMAND_OK
00145          && result_status != PGRES_TUPLES_OK
00146          && result_status != PGRES_NONFATAL_ERROR) {
00147          ast_log(LOG_WARNING,
00148                "Postgresql RealTime: Failed to query database. Check debug for more info.\n");
00149          if (option_debug) {
00150             ast_log(LOG_DEBUG, "Postgresql RealTime: Query: %s\n", sql);
00151             ast_log(LOG_DEBUG, "Postgresql RealTime: Query Failed because: %s (%s)\n",
00152                   PQresultErrorMessage(result), PQresStatus(result_status));
00153          }
00154          ast_mutex_unlock(&pgsql_lock);
00155          return NULL;
00156       }
00157    }
00158 
00159    if (option_debug)
00160       ast_log(LOG_DEBUG, "1Postgresql RealTime: Result=%p Query: %s\n", result, sql);
00161 
00162    if ((num_rows = PQntuples(result)) > 0) {
00163       int i = 0;
00164       int rowIndex = 0;
00165       int numFields = PQnfields(result);
00166       char **fieldnames = NULL;
00167 
00168       if (option_debug)
00169          ast_log(LOG_DEBUG, "Postgresql RealTime: Found %d rows.\n", num_rows);
00170 
00171       if (!(fieldnames = ast_calloc(1, numFields * sizeof(char *)))) {
00172          ast_mutex_unlock(&pgsql_lock);
00173          PQclear(result);
00174          return NULL;
00175       }
00176       for (i = 0; i < numFields; i++)
00177          fieldnames[i] = PQfname(result, i);
00178       for (rowIndex = 0; rowIndex < num_rows; rowIndex++) {
00179          for (i = 0; i < numFields; i++) {
00180             stringp = PQgetvalue(result, rowIndex, i);
00181             while (stringp) {
00182                chunk = strsep(&stringp, ";");
00183                if (chunk && !ast_strlen_zero(ast_strip(chunk))) {
00184                   if (prev) {
00185                      prev->next = ast_variable_new(fieldnames[i], chunk);
00186                      if (prev->next) {
00187                         prev = prev->next;
00188                      }
00189                   } else {
00190                      prev = var = ast_variable_new(fieldnames[i], chunk);
00191                   }
00192                }
00193             }
00194          }
00195       }
00196       free(fieldnames);
00197    } else {
00198       ast_log(LOG_WARNING,
00199             "Postgresql RealTime: Could not find any rows in table %s.\n", table);
00200    }
00201 
00202    ast_mutex_unlock(&pgsql_lock);
00203    PQclear(result);
00204 
00205    return var;
00206 }

static int realtime_pgsql_status int  fd,
int  argc,
char **  argv
[static]
 

Definition at line 784 of file res_config_pgsql.c.

References ast_cli(), connect_time, dbhost, dbname, dbport, dbsock, dbuser, pgsqlConn, RESULT_FAILURE, and RESULT_SUCCESS.

00785 {
00786    char status[256], status2[100] = "";
00787    int ctime = time(NULL) - connect_time;
00788 
00789    if (pgsqlConn && PQstatus(pgsqlConn) == CONNECTION_OK) {
00790       if (dbhost) {
00791          snprintf(status, 255, "Connected to %s@%s, port %d", dbname, dbhost, dbport);
00792       } else if (dbsock) {
00793          snprintf(status, 255, "Connected to %s on socket file %s", dbname, dbsock);
00794       } else {
00795          snprintf(status, 255, "Connected to %s@%s", dbname, dbhost);
00796       }
00797 
00798       if (dbuser && *dbuser) {
00799          snprintf(status2, 99, " with username %s", dbuser);
00800       }
00801 
00802       if (ctime > 31536000) {
00803          ast_cli(fd, "%s%s for %d years, %d days, %d hours, %d minutes, %d seconds.\n",
00804                status, status2, ctime / 31536000, (ctime % 31536000) / 86400,
00805                (ctime % 86400) / 3600, (ctime % 3600) / 60, ctime % 60);
00806       } else if (ctime > 86400) {
00807          ast_cli(fd, "%s%s for %d days, %d hours, %d minutes, %d seconds.\n", status,
00808                status2, ctime / 86400, (ctime % 86400) / 3600, (ctime % 3600) / 60,
00809                ctime % 60);
00810       } else if (ctime > 3600) {
00811          ast_cli(fd, "%s%s for %d hours, %d minutes, %d seconds.\n", status, status2,
00812                ctime / 3600, (ctime % 3600) / 60, ctime % 60);
00813       } else if (ctime > 60) {
00814          ast_cli(fd, "%s%s for %d minutes, %d seconds.\n", status, status2, ctime / 60,
00815                ctime % 60);
00816       } else {
00817          ast_cli(fd, "%s%s for %d seconds.\n", status, status2, ctime);
00818       }
00819 
00820       return RESULT_SUCCESS;
00821    } else {
00822       return RESULT_FAILURE;
00823    }
00824 }

static int reload void   )  [static]
 

Definition at line 627 of file res_config_pgsql.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), LOG_DEBUG, LOG_WARNING, option_debug, parse_config(), pgsql_reconnect(), pgsqlConn, and VERBOSE_PREFIX_2.

00628 {
00629    /* Aquire control before doing anything to the module itself. */
00630    ast_mutex_lock(&pgsql_lock);
00631 
00632    if (pgsqlConn) {
00633       PQfinish(pgsqlConn);
00634       pgsqlConn = NULL;
00635    };
00636    parse_config();
00637 
00638    if (!pgsql_reconnect(NULL)) {
00639       ast_log(LOG_WARNING,
00640             "Postgresql RealTime: Couldn't establish connection. Check debug.\n");
00641       if (option_debug)
00642          ast_log(LOG_DEBUG, "Postgresql RealTime: Cannot Connect: %s\n",
00643                PQerrorMessage(pgsqlConn));
00644    }
00645 
00646    ast_verbose(VERBOSE_PREFIX_2 "Postgresql RealTime reloaded.\n");
00647 
00648    /* Done reloading. Release lock so others can now use driver. */
00649    ast_mutex_unlock(&pgsql_lock);
00650 
00651    return 0;
00652 }

static int unload_module void   )  [static]
 

Definition at line 604 of file res_config_pgsql.c.

References ast_cli_unregister_multiple(), ast_config_engine_deregister(), ast_module_user_hangup_all, ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), cli_realtime, option_verbose, pgsql_engine, and pgsqlConn.

00605 {
00606    /* Aquire control before doing anything to the module itself. */
00607    ast_mutex_lock(&pgsql_lock);
00608 
00609    if (pgsqlConn) {
00610       PQfinish(pgsqlConn);
00611       pgsqlConn = NULL;
00612    };
00613    ast_cli_unregister_multiple(cli_realtime, sizeof(cli_realtime) / sizeof(struct ast_cli_entry));
00614    ast_config_engine_deregister(&pgsql_engine);
00615    if (option_verbose) {
00616       ast_verbose("Postgresql RealTime unloaded.\n");
00617    }
00618 
00619    ast_module_user_hangup_all();
00620 
00621    /* Unlock so something else can destroy the lock. */
00622    ast_mutex_unlock(&pgsql_lock);
00623 
00624    return 0;
00625 }

static int update_pgsql const char *  database,
const char *  table,
const char *  keyfield,
const char *  lookup,
va_list  ap
[static]
 

Definition at line 362 of file res_config_pgsql.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), LOG_DEBUG, LOG_WARNING, option_debug, pgsql_reconnect(), and pgsqlConn.

00364 {
00365    PGresult *result = NULL;
00366    int numrows = 0;
00367    char sql[256];
00368    const char *newparam, *newval;
00369 
00370    if (!table) {
00371       ast_log(LOG_WARNING, "Postgresql RealTime: No table specified.\n");
00372       return -1;
00373    }
00374 
00375    /* Get the first parameter and first value in our list of passed paramater/value pairs */
00376    newparam = va_arg(ap, const char *);
00377    newval = va_arg(ap, const char *);
00378    if (!newparam || !newval) {
00379       ast_log(LOG_WARNING,
00380             "Postgresql RealTime: Realtime retrieval requires at least 1 parameter and 1 value to search on.\n");
00381       if (pgsqlConn) {
00382          PQfinish(pgsqlConn);
00383          pgsqlConn = NULL;
00384       };
00385       return -1;
00386    }
00387 
00388    /* Create the first part of the query using the first parameter/value pairs we just extracted
00389       If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */
00390 
00391    snprintf(sql, sizeof(sql), "UPDATE %s SET %s = '%s'", table, newparam, newval);
00392    while ((newparam = va_arg(ap, const char *))) {
00393       newval = va_arg(ap, const char *);
00394       snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), ", %s = '%s'", newparam,
00395              newval);
00396    }
00397    va_end(ap);
00398    snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " WHERE %s = '%s'", keyfield,
00399           lookup);
00400 
00401    if (option_debug)
00402       ast_log(LOG_DEBUG, "Postgresql RealTime: Update SQL: %s\n", sql);
00403 
00404    /* We now have our complete statement; Lets connect to the server and execute it. */
00405    ast_mutex_lock(&pgsql_lock);
00406    if (!pgsql_reconnect(database)) {
00407       ast_mutex_unlock(&pgsql_lock);
00408       return -1;
00409    }
00410 
00411    if (!(result = PQexec(pgsqlConn, sql))) {
00412       ast_log(LOG_WARNING,
00413             "Postgresql RealTime: Failed to query database. Check debug for more info.\n");
00414       if (option_debug) {
00415          ast_log(LOG_DEBUG, "Postgresql RealTime: Query: %s\n", sql);
00416          ast_log(LOG_DEBUG, "Postgresql RealTime: Query Failed because: %s\n",
00417                PQerrorMessage(pgsqlConn));
00418       }
00419       ast_mutex_unlock(&pgsql_lock);
00420       return -1;
00421    } else {
00422       ExecStatusType result_status = PQresultStatus(result);
00423       if (result_status != PGRES_COMMAND_OK
00424          && result_status != PGRES_TUPLES_OK
00425          && result_status != PGRES_NONFATAL_ERROR) {
00426          ast_log(LOG_WARNING,
00427                "Postgresql RealTime: Failed to query database. Check debug for more info.\n");
00428          if (option_debug) {
00429             ast_log(LOG_DEBUG, "Postgresql RealTime: Query: %s\n", sql);
00430             ast_log(LOG_DEBUG, "Postgresql RealTime: Query Failed because: %s (%s)\n",
00431                   PQresultErrorMessage(result), PQresStatus(result_status));
00432          }
00433          ast_mutex_unlock(&pgsql_lock);
00434          return -1;
00435       }
00436    }
00437 
00438    numrows = atoi(PQcmdTuples(result));
00439    ast_mutex_unlock(&pgsql_lock);
00440 
00441    if (option_debug)
00442       ast_log(LOG_DEBUG, "Postgresql RealTime: Updated %d rows on table: %s\n", numrows,
00443             table);
00444 
00445    /* From http://dev.pgsql.com/doc/pgsql/en/pgsql-affected-rows.html
00446     * An integer greater than zero indicates the number of rows affected
00447     * Zero indicates that no records were updated
00448     * -1 indicates that the query returned an error (although, if the query failed, it should have been caught above.)
00449     */
00450 
00451    if (numrows >= 0)
00452       return (int) numrows;
00453 
00454    return -1;
00455 }


Variable Documentation

struct ast_cli_entry cli_realtime[] [static]
 

Initial value:

 {
   { { "realtime", "pgsql", "status", NULL },
   realtime_pgsql_status, "Shows connection information for the Postgresql RealTime driver",
   cli_realtime_pgsql_status_usage },
}

Definition at line 73 of file res_config_pgsql.c.

Referenced by load_module(), and unload_module().

const char cli_realtime_pgsql_status_usage[] [static]
 

Initial value:

   "Usage: realtime pgsql status\n"
   "       Shows connection information for the Postgresql RealTime driver\n"

Definition at line 69 of file res_config_pgsql.c.

time_t connect_time = 0 [static]
 

Definition at line 63 of file res_config_pgsql.c.

Referenced by pgsql_reconnect(), and realtime_pgsql_status().

char dbhost[MAX_DB_OPTION_SIZE] = "" [static]
 

Definition at line 57 of file res_config_pgsql.c.

Referenced by parse_config(), pgsql_reconnect(), and realtime_pgsql_status().

char dbname[MAX_DB_OPTION_SIZE] = "" [static]
 

Definition at line 60 of file res_config_pgsql.c.

Referenced by parse_config(), pgsql_reconnect(), and realtime_pgsql_status().

char dbpass[MAX_DB_OPTION_SIZE] = "" [static]
 

Definition at line 59 of file res_config_pgsql.c.

Referenced by parse_config(), and pgsql_reconnect().

int dbport = 5432 [static]
 

Definition at line 62 of file res_config_pgsql.c.

Referenced by parse_config(), pgsql_reconnect(), and realtime_pgsql_status().

char dbsock[MAX_DB_OPTION_SIZE] = "" [static]
 

Definition at line 61 of file res_config_pgsql.c.

Referenced by parse_config(), pgsql_reconnect(), and realtime_pgsql_status().

char dbuser[MAX_DB_OPTION_SIZE] = "" [static]
 

Definition at line 58 of file res_config_pgsql.c.

Referenced by parse_config(), pgsql_reconnect(), and realtime_pgsql_status().

struct ast_config_engine pgsql_engine [static]
 

Definition at line 570 of file res_config_pgsql.c.

Referenced by load_module(), and unload_module().

PGconn* pgsqlConn = NULL
 

Definition at line 53 of file res_config_pgsql.c.

Referenced by config_pgsql(), load_module(), pgsql_reconnect(), realtime_multi_pgsql(), realtime_pgsql_status(), reload(), unload_module(), and update_pgsql().


Asterisk is a trademark for Digium, inc.. | Edvina.net | Asterisk.org | This documentation was generated with Doxygen