Thu Mar 25 12:10:06 2010

Asterisk developer's documentation


res_config_pgsql.c File Reference

Postgresql plugin for Asterisk RealTime Architecture. More...

#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"

Go to the source code of this file.

Defines

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

Functions

static void __reg_module (void)
static void __unreg_module (void)
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_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "PostgreSQL RealTime Configuration Driver" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, .reload = reload }
static const struct ast_module_infoast_module_info = &__mod_info
static struct ast_cli_entry cli_realtime []
static 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
static ast_mutex_t pgsql_lock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
PGconn * pgsqlConn = NULL


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.


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

static void __reg_module ( void   )  [static]

Definition at line 842 of file res_config_pgsql.c.

static void __unreg_module ( void   )  [static]

Definition at line 842 of file res_config_pgsql.c.

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 491 of file res_config_pgsql.c.

References ast_build_string(), 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, pgsql_lock, pgsql_reconnect(), pgsqlConn, and RES_CONFIG_PGSQL_CONF.

00494 {
00495    PGresult *result = NULL;
00496    long num_rows;
00497    struct ast_variable *new_v;
00498    struct ast_category *cur_cat = NULL;
00499    char sqlbuf[1024] = "";
00500    char *sql = sqlbuf;
00501    size_t sqlleft = sizeof(sqlbuf);
00502    char last[80] = "";
00503    int last_cat_metric = 0;
00504 
00505    last[0] = '\0';
00506 
00507    if (!file || !strcmp(file, RES_CONFIG_PGSQL_CONF)) {
00508       ast_log(LOG_WARNING, "Postgresql RealTime: Cannot configure myself.\n");
00509       return NULL;
00510    }
00511 
00512    ast_build_string(&sql, &sqlleft, "SELECT category, var_name, var_val, cat_metric FROM %s ", table);
00513    ast_build_string(&sql, &sqlleft, "WHERE filename='%s' and commented=0", file);
00514    ast_build_string(&sql, &sqlleft, "ORDER BY cat_metric DESC, var_metric ASC, category, var_name ");
00515 
00516    ast_log(LOG_DEBUG, "Postgresql RealTime: Static SQL: %s\n", sqlbuf);
00517 
00518    /* We now have our complete statement; Lets connect to the server and execute it. */
00519    ast_mutex_lock(&pgsql_lock);
00520    if (!pgsql_reconnect(database)) {
00521       ast_mutex_unlock(&pgsql_lock);
00522       return NULL;
00523    }
00524 
00525    if (!(result = PQexec(pgsqlConn, sqlbuf))) {
00526       ast_log(LOG_WARNING,
00527             "Postgresql RealTime: Failed to query database. Check debug for more info.\n");
00528       ast_log(LOG_DEBUG, "Postgresql RealTime: Query: %s\n", sql);
00529       ast_log(LOG_DEBUG, "Postgresql RealTime: Query Failed because: %s\n",
00530             PQerrorMessage(pgsqlConn));
00531       ast_mutex_unlock(&pgsql_lock);
00532       return NULL;
00533    } else {
00534       ExecStatusType result_status = PQresultStatus(result);
00535       if (result_status != PGRES_COMMAND_OK
00536          && result_status != PGRES_TUPLES_OK
00537          && result_status != PGRES_NONFATAL_ERROR) {
00538          ast_log(LOG_WARNING,
00539                "Postgresql RealTime: Failed to query database. Check debug for more info.\n");
00540          ast_log(LOG_DEBUG, "Postgresql RealTime: Query: %s\n", sql);
00541          ast_log(LOG_DEBUG, "Postgresql RealTime: Query Failed because: %s (%s)\n",
00542                PQresultErrorMessage(result), PQresStatus(result_status));
00543          ast_mutex_unlock(&pgsql_lock);
00544          return NULL;
00545       }
00546    }
00547 
00548    if ((num_rows = PQntuples(result)) > 0) {
00549       int rowIndex = 0;
00550 
00551       ast_log(LOG_DEBUG, "Postgresql RealTime: Found %ld rows.\n", num_rows);
00552 
00553       for (rowIndex = 0; rowIndex < num_rows; rowIndex++) {
00554          char *field_category = PQgetvalue(result, rowIndex, 0);
00555          char *field_var_name = PQgetvalue(result, rowIndex, 1);
00556          char *field_var_val = PQgetvalue(result, rowIndex, 2);
00557          char *field_cat_metric = PQgetvalue(result, rowIndex, 3);
00558          if (!strcmp(field_var_name, "#include")) {
00559             if (!ast_config_internal_load(field_var_val, cfg, 0)) {
00560                PQclear(result);
00561                ast_mutex_unlock(&pgsql_lock);
00562                return NULL;
00563             }
00564             continue;
00565          }
00566 
00567          if (strcmp(last, field_category) || last_cat_metric != atoi(field_cat_metric)) {
00568             cur_cat = ast_category_new(field_category);
00569             if (!cur_cat)
00570                break;
00571             strcpy(last, field_category);
00572             last_cat_metric = atoi(field_cat_metric);
00573             ast_category_append(cfg, cur_cat);
00574          }
00575          new_v = ast_variable_new(field_var_name, field_var_val);
00576          ast_variable_append(cur_cat, new_v);
00577       }
00578    } else {
00579       ast_log(LOG_WARNING,
00580             "Postgresql RealTime: Could not find config '%s' in database.\n", file);
00581    }
00582 
00583    PQclear(result);
00584    ast_mutex_unlock(&pgsql_lock);
00585 
00586    return cfg;
00587 }

static int load_module ( void   )  [static]

Definition at line 597 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_verbose, parse_config(), pgsql_engine, pgsql_lock, pgsql_reconnect(), and pgsqlConn.

00598 {
00599    if(!parse_config())
00600       return AST_MODULE_LOAD_DECLINE;
00601 
00602    ast_mutex_lock(&pgsql_lock);
00603 
00604    if (!pgsql_reconnect(NULL)) {
00605       ast_log(LOG_WARNING,
00606             "Postgresql RealTime: Couldn't establish connection. Check debug.\n");
00607       ast_log(LOG_DEBUG, "Postgresql RealTime: Cannot Connect: %s\n",
00608             PQerrorMessage(pgsqlConn));
00609    }
00610 
00611    ast_config_engine_register(&pgsql_engine);
00612    if (option_verbose) {
00613       ast_verbose("Postgresql RealTime driver loaded.\n");
00614    }
00615    ast_cli_register_multiple(cli_realtime, sizeof(cli_realtime) / sizeof(struct ast_cli_entry));
00616 
00617    ast_mutex_unlock(&pgsql_lock);
00618 
00619    return 0;
00620 }

static int parse_config ( void   )  [static]

Definition at line 671 of file res_config_pgsql.c.

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

00672 {
00673    struct ast_config *config;
00674    const char *s;
00675 
00676    config = ast_config_load(RES_CONFIG_PGSQL_CONF);
00677 
00678    if (!config) {
00679       ast_log(LOG_WARNING, "Unable to load config %s\n",RES_CONFIG_PGSQL_CONF);
00680       return 0;
00681    }
00682    if (!(s = ast_variable_retrieve(config, "general", "dbuser"))) {
00683       ast_log(LOG_WARNING,
00684             "Postgresql RealTime: No database user found, using 'asterisk' as default.\n");
00685       strcpy(dbuser, "asterisk");
00686    } else {
00687       ast_copy_string(dbuser, s, sizeof(dbuser));
00688    }
00689 
00690    if (!(s = ast_variable_retrieve(config, "general", "dbpass"))) {
00691       ast_log(LOG_WARNING,
00692             "Postgresql RealTime: No database password found, using 'asterisk' as default.\n");
00693       strcpy(dbpass, "asterisk");
00694    } else {
00695       ast_copy_string(dbpass, s, sizeof(dbpass));
00696    }
00697 
00698    if (!(s = ast_variable_retrieve(config, "general", "dbhost"))) {
00699       ast_log(LOG_WARNING,
00700             "Postgresql RealTime: No database host found, using localhost via socket.\n");
00701       dbhost[0] = '\0';
00702    } else {
00703       ast_copy_string(dbhost, s, sizeof(dbhost));
00704    }
00705 
00706    if (!(s = ast_variable_retrieve(config, "general", "dbname"))) {
00707       ast_log(LOG_WARNING,
00708             "Postgresql RealTime: No database name found, using 'asterisk' as default.\n");
00709       strcpy(dbname, "asterisk");
00710    } else {
00711       ast_copy_string(dbname, s, sizeof(dbname));
00712    }
00713 
00714    if (!(s = ast_variable_retrieve(config, "general", "dbport"))) {
00715       ast_log(LOG_WARNING,
00716             "Postgresql RealTime: No database port found, using 5432 as default.\n");
00717       dbport = 5432;
00718    } else {
00719       dbport = atoi(s);
00720    }
00721 
00722    if (!ast_strlen_zero(dbhost)) {
00723       /* No socket needed */
00724    } else if (!(s = ast_variable_retrieve(config, "general", "dbsock"))) {
00725       ast_log(LOG_WARNING,
00726             "Postgresql RealTime: No database socket found, using '/tmp/pgsql.sock' as default.\n");
00727       strcpy(dbsock, "/tmp/pgsql.sock");
00728    } else {
00729       ast_copy_string(dbsock, s, sizeof(dbsock));
00730    }
00731    ast_config_destroy(config);
00732 
00733    if (!ast_strlen_zero(dbhost)) {
00734       ast_log(LOG_DEBUG, "Postgresql RealTime Host: %s\n", dbhost);
00735       ast_log(LOG_DEBUG, "Postgresql RealTime Port: %i\n", dbport);
00736    } else {
00737       ast_log(LOG_DEBUG, "Postgresql RealTime Socket: %s\n", dbsock);
00738    }
00739    ast_log(LOG_DEBUG, "Postgresql RealTime User: %s\n", dbuser);
00740    ast_log(LOG_DEBUG, "Postgresql RealTime Password: %s\n", dbpass);
00741    ast_log(LOG_DEBUG, "Postgresql RealTime DBName: %s\n", dbname);
00742 
00743    return 1;
00744 }

static int pgsql_reconnect ( const char *  database  )  [static]

Definition at line 746 of file res_config_pgsql.c.

References ast_copy_string(), ast_free, ast_log(), ast_malloc, ast_strlen_zero(), connect_time, dbhost, dbname, dbpass, dbport, dbsock, dbuser, LOG_DEBUG, LOG_ERROR, pgsqlConn, and S_OR.

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

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

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

Definition at line 216 of file res_config_pgsql.c.

References ast_calloc, ast_category_append(), ast_category_new(), ast_category_rename(), ast_config_new(), ast_free, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_strdupa, ast_strip(), ast_strlen_zero(), ast_variable_append(), ast_variable_new(), LOG_DEBUG, LOG_ERROR, LOG_WARNING, pgsql_lock, pgsql_reconnect(), pgsqlConn, and var.

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

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_free, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_strip(), ast_strlen_zero(), ast_variable_new(), LOG_DEBUG, LOG_ERROR, LOG_WARNING, ast_variable::next, pgsql_lock, pgsql_reconnect(), and var.

00080 {
00081    PGresult *result = NULL;
00082    int num_rows = 0, pgerror;
00083    char sql[256], escapebuf[513];
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    PQescapeStringConn(pgsqlConn, escapebuf, newval, (sizeof(escapebuf) - 1) / 2, &pgerror);
00113    if (pgerror) {
00114       ast_log(LOG_ERROR, "Postgres detected invalid input: '%s'\n", newval);
00115       va_end(ap);
00116       return NULL;
00117    }
00118 
00119    snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s '%s'", table, newparam, op,
00120           escapebuf);
00121    while ((newparam = va_arg(ap, const char *))) {
00122       newval = va_arg(ap, const char *);
00123       if (!strchr(newparam, ' '))
00124          op = " =";
00125       else
00126          op = "";
00127 
00128       PQescapeStringConn(pgsqlConn, escapebuf, newval, (sizeof(escapebuf) - 1) / 2, &pgerror);
00129       if (pgerror) {
00130          ast_log(LOG_ERROR, "Postgres detected invalid input: '%s'\n", newval);
00131          va_end(ap);
00132          return NULL;
00133       }
00134 
00135       snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s '%s'", newparam,
00136              op, escapebuf);
00137    }
00138    va_end(ap);
00139 
00140    /* We now have our complete statement; Lets connect to the server and execute it. */
00141    ast_mutex_lock(&pgsql_lock);
00142    if (!pgsql_reconnect(database)) {
00143       ast_mutex_unlock(&pgsql_lock);
00144       return NULL;
00145    }
00146 
00147    if (!(result = PQexec(pgsqlConn, sql))) {
00148       ast_log(LOG_WARNING,
00149             "Postgresql RealTime: Failed to query database. Check debug for more info.\n");
00150       ast_log(LOG_DEBUG, "Postgresql RealTime: Query: %s\n", sql);
00151       ast_log(LOG_DEBUG, "Postgresql RealTime: Query Failed because: %s\n",
00152             PQerrorMessage(pgsqlConn));
00153       ast_mutex_unlock(&pgsql_lock);
00154       return NULL;
00155    } else {
00156       ExecStatusType result_status = PQresultStatus(result);
00157       if (result_status != PGRES_COMMAND_OK
00158          && result_status != PGRES_TUPLES_OK
00159          && result_status != PGRES_NONFATAL_ERROR) {
00160          ast_log(LOG_WARNING,
00161                "Postgresql RealTime: Failed to query database. Check debug for more info.\n");
00162          ast_log(LOG_DEBUG, "Postgresql RealTime: Query: %s\n", sql);
00163          ast_log(LOG_DEBUG, "Postgresql RealTime: Query Failed because: %s (%s)\n",
00164                PQresultErrorMessage(result), PQresStatus(result_status));
00165          ast_mutex_unlock(&pgsql_lock);
00166          return NULL;
00167       }
00168    }
00169 
00170    ast_log(LOG_DEBUG, "1Postgresql RealTime: Result=%p Query: %s\n", result, sql);
00171 
00172    if ((num_rows = PQntuples(result)) > 0) {
00173       int i = 0;
00174       int rowIndex = 0;
00175       int numFields = PQnfields(result);
00176       char **fieldnames = NULL;
00177 
00178       ast_log(LOG_DEBUG, "Postgresql RealTime: Found %d rows.\n", num_rows);
00179 
00180       if (!(fieldnames = ast_calloc(1, numFields * sizeof(char *)))) {
00181          ast_mutex_unlock(&pgsql_lock);
00182          PQclear(result);
00183          return NULL;
00184       }
00185       for (i = 0; i < numFields; i++)
00186          fieldnames[i] = PQfname(result, i);
00187       for (rowIndex = 0; rowIndex < num_rows; rowIndex++) {
00188          for (i = 0; i < numFields; i++) {
00189             stringp = PQgetvalue(result, rowIndex, i);
00190             while (stringp) {
00191                chunk = strsep(&stringp, ";");
00192                if (chunk && !ast_strlen_zero(ast_strip(chunk))) {
00193                   if (prev) {
00194                      prev->next = ast_variable_new(fieldnames[i], chunk);
00195                      if (prev->next) {
00196                         prev = prev->next;
00197                      }
00198                   } else {
00199                      prev = var = ast_variable_new(fieldnames[i], chunk);
00200                   }
00201                }
00202             }
00203          }
00204       }
00205       ast_free(fieldnames);
00206    } else {
00207       ast_log(LOG_DEBUG, "Postgresql RealTime: Could not find any rows in table %s.\n", table);
00208    }
00209 
00210    ast_mutex_unlock(&pgsql_lock);
00211    PQclear(result);
00212 
00213    return var;
00214 }

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

Definition at line 795 of file res_config_pgsql.c.

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

00796 {
00797    char status[256], status2[100] = "";
00798    int ctime = time(NULL) - connect_time;
00799 
00800    if (pgsqlConn && PQstatus(pgsqlConn) == CONNECTION_OK) {
00801       if (!ast_strlen_zero(dbhost)) {
00802          snprintf(status, 255, "Connected to %s@%s, port %d", dbname, dbhost, dbport);
00803       } else if (!ast_strlen_zero(dbsock)) {
00804          snprintf(status, 255, "Connected to %s on socket file %s", dbname, dbsock);
00805       } else {
00806          snprintf(status, 255, "Connected to %s@%s", dbname, dbhost);
00807       }
00808 
00809       if (!ast_strlen_zero(dbuser)) {
00810          snprintf(status2, 99, " with username %s", dbuser);
00811       }
00812 
00813       if (ctime > 31536000) {
00814          ast_cli(fd, "%s%s for %d years, %d days, %d hours, %d minutes, %d seconds.\n",
00815                status, status2, ctime / 31536000, (ctime % 31536000) / 86400,
00816                (ctime % 86400) / 3600, (ctime % 3600) / 60, ctime % 60);
00817       } else if (ctime > 86400) {
00818          ast_cli(fd, "%s%s for %d days, %d hours, %d minutes, %d seconds.\n", status,
00819                status2, ctime / 86400, (ctime % 86400) / 3600, (ctime % 3600) / 60,
00820                ctime % 60);
00821       } else if (ctime > 3600) {
00822          ast_cli(fd, "%s%s for %d hours, %d minutes, %d seconds.\n", status, status2,
00823                ctime / 3600, (ctime % 3600) / 60, ctime % 60);
00824       } else if (ctime > 60) {
00825          ast_cli(fd, "%s%s for %d minutes, %d seconds.\n", status, status2, ctime / 60,
00826                ctime % 60);
00827       } else {
00828          ast_cli(fd, "%s%s for %d seconds.\n", status, status2, ctime);
00829       }
00830 
00831       return RESULT_SUCCESS;
00832    } else {
00833       return RESULT_FAILURE;
00834    }
00835 }

static int reload ( void   )  [static]

Definition at line 645 of file res_config_pgsql.c.

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

00646 {
00647    /* Aquire control before doing anything to the module itself. */
00648    ast_mutex_lock(&pgsql_lock);
00649 
00650    if (pgsqlConn) {
00651       PQfinish(pgsqlConn);
00652       pgsqlConn = NULL;
00653    };
00654    parse_config();
00655 
00656    if (!pgsql_reconnect(NULL)) {
00657       ast_log(LOG_WARNING,
00658             "Postgresql RealTime: Couldn't establish connection. Check debug.\n");
00659       ast_log(LOG_DEBUG, "Postgresql RealTime: Cannot Connect: %s\n",
00660             PQerrorMessage(pgsqlConn));
00661    }
00662 
00663    ast_verbose(VERBOSE_PREFIX_2 "Postgresql RealTime reloaded.\n");
00664 
00665    /* Done reloading. Release lock so others can now use driver. */
00666    ast_mutex_unlock(&pgsql_lock);
00667 
00668    return 0;
00669 }

static int unload_module ( void   )  [static]

Definition at line 622 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, pgsql_lock, and pgsqlConn.

00623 {
00624    /* Aquire control before doing anything to the module itself. */
00625    ast_mutex_lock(&pgsql_lock);
00626 
00627    if (pgsqlConn) {
00628       PQfinish(pgsqlConn);
00629       pgsqlConn = NULL;
00630    };
00631    ast_cli_unregister_multiple(cli_realtime, sizeof(cli_realtime) / sizeof(struct ast_cli_entry));
00632    ast_config_engine_deregister(&pgsql_engine);
00633    if (option_verbose) {
00634       ast_verbose("Postgresql RealTime unloaded.\n");
00635    }
00636 
00637    ast_module_user_hangup_all();
00638 
00639    /* Unlock so something else can destroy the lock. */
00640    ast_mutex_unlock(&pgsql_lock);
00641 
00642    return 0;
00643 }

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

Definition at line 379 of file res_config_pgsql.c.

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

00381 {
00382    PGresult *result = NULL;
00383    int numrows = 0, pgerror;
00384    char sql[256], escapebuf[513];
00385    const char *newparam, *newval;
00386 
00387    if (!table) {
00388       ast_log(LOG_WARNING, "Postgresql RealTime: No table specified.\n");
00389       return -1;
00390    }
00391 
00392    /* Get the first parameter and first value in our list of passed paramater/value pairs */
00393    newparam = va_arg(ap, const char *);
00394    newval = va_arg(ap, const char *);
00395    if (!newparam || !newval) {
00396       ast_log(LOG_WARNING,
00397             "Postgresql RealTime: Realtime retrieval requires at least 1 parameter and 1 value to search on.\n");
00398       if (pgsqlConn) {
00399          PQfinish(pgsqlConn);
00400          pgsqlConn = NULL;
00401       };
00402       return -1;
00403    }
00404 
00405    /* Create the first part of the query using the first parameter/value pairs we just extracted
00406       If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */
00407 
00408    PQescapeStringConn(pgsqlConn, escapebuf, newval, (sizeof(escapebuf) - 1) / 2, &pgerror);
00409    if (pgerror) {
00410       ast_log(LOG_ERROR, "Postgres detected invalid input: '%s'\n", newval);
00411       va_end(ap);
00412       return -1;
00413    }
00414    snprintf(sql, sizeof(sql), "UPDATE %s SET %s = '%s'", table, newparam, escapebuf);
00415 
00416    while ((newparam = va_arg(ap, const char *))) {
00417       newval = va_arg(ap, const char *);
00418 
00419       PQescapeStringConn(pgsqlConn, escapebuf, newval, (sizeof(escapebuf) - 1) / 2, &pgerror);
00420       if (pgerror) {
00421          ast_log(LOG_ERROR, "Postgres detected invalid input: '%s'\n", newval);
00422          va_end(ap);
00423          return -1;
00424       }
00425 
00426       snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), ", %s = '%s'", newparam,
00427              escapebuf);
00428    }
00429    va_end(ap);
00430 
00431    PQescapeStringConn(pgsqlConn, escapebuf, lookup, (sizeof(escapebuf) - 1) / 2, &pgerror);
00432    if (pgerror) {
00433       ast_log(LOG_ERROR, "Postgres detected invalid input: '%s'\n", lookup);
00434       va_end(ap);
00435       return -1;
00436    }
00437 
00438    snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " WHERE %s = '%s'", keyfield,
00439           escapebuf);
00440 
00441    ast_log(LOG_DEBUG, "Postgresql RealTime: Update SQL: %s\n", sql);
00442 
00443    /* We now have our complete statement; Lets connect to the server and execute it. */
00444    ast_mutex_lock(&pgsql_lock);
00445    if (!pgsql_reconnect(database)) {
00446       ast_mutex_unlock(&pgsql_lock);
00447       return -1;
00448    }
00449 
00450    if (!(result = PQexec(pgsqlConn, sql))) {
00451       ast_log(LOG_WARNING,
00452             "Postgresql RealTime: Failed to query database. Check debug for more info.\n");
00453       ast_log(LOG_DEBUG, "Postgresql RealTime: Query: %s\n", sql);
00454       ast_log(LOG_DEBUG, "Postgresql RealTime: Query Failed because: %s\n",
00455             PQerrorMessage(pgsqlConn));
00456       ast_mutex_unlock(&pgsql_lock);
00457       return -1;
00458    } else {
00459       ExecStatusType result_status = PQresultStatus(result);
00460       if (result_status != PGRES_COMMAND_OK
00461          && result_status != PGRES_TUPLES_OK
00462          && result_status != PGRES_NONFATAL_ERROR) {
00463          ast_log(LOG_WARNING,
00464                "Postgresql RealTime: Failed to query database. Check debug for more info.\n");
00465          ast_log(LOG_DEBUG, "Postgresql RealTime: Query: %s\n", sql);
00466          ast_log(LOG_DEBUG, "Postgresql RealTime: Query Failed because: %s (%s)\n",
00467                PQresultErrorMessage(result), PQresStatus(result_status));
00468          ast_mutex_unlock(&pgsql_lock);
00469          return -1;
00470       }
00471    }
00472 
00473    numrows = atoi(PQcmdTuples(result));
00474    ast_mutex_unlock(&pgsql_lock);
00475 
00476    ast_log(LOG_DEBUG, "Postgresql RealTime: Updated %d rows on table: %s\n", numrows,
00477          table);
00478 
00479    /* From http://dev.pgsql.com/doc/pgsql/en/pgsql-affected-rows.html
00480     * An integer greater than zero indicates the number of rows affected
00481     * Zero indicates that no records were updated
00482     * -1 indicates that the query returned an error (although, if the query failed, it should have been caught above.)
00483     */
00484 
00485    if (numrows >= 0)
00486       return (int) numrows;
00487 
00488    return -1;
00489 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "PostgreSQL RealTime Configuration Driver" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, .reload = reload } [static]

Definition at line 842 of file res_config_pgsql.c.

const struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 842 of file res_config_pgsql.c.

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.

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.

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.

struct ast_config_engine pgsql_engine [static]

Definition at line 589 of file res_config_pgsql.c.

Referenced by load_module(), and unload_module().

ast_mutex_t pgsql_lock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static]

Definition at line 49 of file res_config_pgsql.c.

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().


Generated on Thu Mar 25 12:10:06 2010 for Asterisk - the Open Source PBX by  doxygen 1.4.7