#include "asterisk.h"
#include <libpq-fe.h>
#include "asterisk/file.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/config.h"
#include "asterisk/module.h"
#include "asterisk/lock.h"
#include "asterisk/utils.h"
#include "asterisk/cli.h"
Go to the source code of this file.
Data Structures | |
struct | columns |
struct | psql_tables |
struct | tables |
struct | tables::psql_columns |
Defines | |
#define | ESCAPE_STRING(buffer, stringname) |
#define | has_schema_support (version > 70300 ? 1 : 0) |
#define | MAX_DB_OPTION_SIZE 64 |
#define | RES_CONFIG_PGSQL_CONF "res_pgsql.conf" |
Enumerations | |
enum | { RQ_WARN, RQ_CREATECLOSE, RQ_CREATECHAR } |
Functions | |
static void | __reg_module (void) |
static void | __unreg_module (void) |
static struct ast_config * | config_pgsql (const char *database, const char *table, const char *file, struct ast_config *cfg, struct ast_flags flags, const char *suggested_incl, const char *who_asked) |
static int | destroy_pgsql (const char *database, const char *table, const char *keyfield, const char *lookup, va_list ap) |
static void | destroy_table (struct tables *table) |
static struct tables * | find_table (const char *orig_tablename) |
static char * | handle_cli_realtime_pgsql_cache (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cli_realtime_pgsql_status (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static int | load_module (void) |
static int | parse_config (int reload) |
static int | pgsql_reconnect (const char *database) |
static struct ast_config * | realtime_multi_pgsql (const char *database, const char *table, va_list ap) |
static struct ast_variable * | realtime_pgsql (const char *database, const char *table, va_list ap) |
static int | reload (void) |
static int | require_pgsql (const char *database, const char *tablename, va_list ap) |
static int | store_pgsql (const char *database, const char *table, va_list ap) |
static int | unload_module (void) |
static int | unload_pgsql (const char *database, const char *tablename) |
static int | update_pgsql (const char *database, const char *tablename, const char *keyfield, const char *lookup, va_list ap) |
Variables | |
static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS , .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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload } |
static struct ast_module_info * | ast_module_info = &__mod_info |
static struct ast_cli_entry | cli_realtime [] |
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_RECURSIVE_MUTEX_INITIALIZER_NP ) |
PGconn * | pgsqlConn = NULL |
enum { ... } | requirements |
static int | version |
Manuel Guesdon <mguesdon@oxymium.net> - PostgreSQL RealTime Driver Author/Adaptor
Definition in file res_config_pgsql.c.
#define ESCAPE_STRING | ( | buffer, | |||
stringname | ) |
Definition at line 706 of file res_config_pgsql.c.
Referenced by destroy_pgsql(), and store_pgsql().
#define has_schema_support (version > 70300 ? 1 : 0) |
#define MAX_DB_OPTION_SIZE 64 |
Definition at line 52 of file res_config_pgsql.c.
#define RES_CONFIG_PGSQL_CONF "res_pgsql.conf" |
anonymous enum |
Definition at line 85 of file res_config_pgsql.c.
00085 { RQ_WARN, RQ_CREATECLOSE, RQ_CREATECHAR } requirements;
static void __reg_module | ( | void | ) | [static] |
Definition at line 1482 of file res_config_pgsql.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 1482 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, | |||
struct ast_flags | flags, | |||
const char * | suggested_incl, | |||
const char * | who_asked | |||
) | [static] |
Definition at line 917 of file res_config_pgsql.c.
References ast_build_string(), ast_category_append(), ast_category_new(), ast_config_internal_load(), ast_debug, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_variable_append(), ast_variable_new(), last, LOG_WARNING, pgsql_lock, pgsql_reconnect(), and RES_CONFIG_PGSQL_CONF.
00920 { 00921 PGresult *result = NULL; 00922 long num_rows; 00923 struct ast_variable *new_v; 00924 struct ast_category *cur_cat = NULL; 00925 char sqlbuf[1024] = ""; 00926 char *sql = sqlbuf; 00927 size_t sqlleft = sizeof(sqlbuf); 00928 char last[80] = ""; 00929 int last_cat_metric = 0; 00930 00931 last[0] = '\0'; 00932 00933 if (!file || !strcmp(file, RES_CONFIG_PGSQL_CONF)) { 00934 ast_log(LOG_WARNING, "PostgreSQL RealTime: Cannot configure myself.\n"); 00935 return NULL; 00936 } 00937 00938 ast_build_string(&sql, &sqlleft, "SELECT category, var_name, var_val, cat_metric FROM %s ", table); 00939 ast_build_string(&sql, &sqlleft, "WHERE filename='%s' and commented=0", file); 00940 ast_build_string(&sql, &sqlleft, "ORDER BY cat_metric DESC, var_metric ASC, category, var_name "); 00941 00942 ast_debug(1, "PostgreSQL RealTime: Static SQL: %s\n", sqlbuf); 00943 00944 /* We now have our complete statement; Lets connect to the server and execute it. */ 00945 ast_mutex_lock(&pgsql_lock); 00946 if (!pgsql_reconnect(database)) { 00947 ast_mutex_unlock(&pgsql_lock); 00948 return NULL; 00949 } 00950 00951 if (!(result = PQexec(pgsqlConn, sqlbuf))) { 00952 ast_log(LOG_WARNING, 00953 "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n"); 00954 ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql); 00955 ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s\n", PQerrorMessage(pgsqlConn)); 00956 ast_mutex_unlock(&pgsql_lock); 00957 return NULL; 00958 } else { 00959 ExecStatusType result_status = PQresultStatus(result); 00960 if (result_status != PGRES_COMMAND_OK 00961 && result_status != PGRES_TUPLES_OK 00962 && result_status != PGRES_NONFATAL_ERROR) { 00963 ast_log(LOG_WARNING, 00964 "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n"); 00965 ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql); 00966 ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s (%s)\n", 00967 PQresultErrorMessage(result), PQresStatus(result_status)); 00968 ast_mutex_unlock(&pgsql_lock); 00969 return NULL; 00970 } 00971 } 00972 00973 if ((num_rows = PQntuples(result)) > 0) { 00974 int rowIndex = 0; 00975 00976 ast_debug(1, "PostgreSQL RealTime: Found %ld rows.\n", num_rows); 00977 00978 for (rowIndex = 0; rowIndex < num_rows; rowIndex++) { 00979 char *field_category = PQgetvalue(result, rowIndex, 0); 00980 char *field_var_name = PQgetvalue(result, rowIndex, 1); 00981 char *field_var_val = PQgetvalue(result, rowIndex, 2); 00982 char *field_cat_metric = PQgetvalue(result, rowIndex, 3); 00983 if (!strcmp(field_var_name, "#include")) { 00984 if (!ast_config_internal_load(field_var_val, cfg, flags, "", who_asked)) { 00985 PQclear(result); 00986 ast_mutex_unlock(&pgsql_lock); 00987 return NULL; 00988 } 00989 continue; 00990 } 00991 00992 if (strcmp(last, field_category) || last_cat_metric != atoi(field_cat_metric)) { 00993 cur_cat = ast_category_new(field_category, "", 99999); 00994 if (!cur_cat) 00995 break; 00996 strcpy(last, field_category); 00997 last_cat_metric = atoi(field_cat_metric); 00998 ast_category_append(cfg, cur_cat); 00999 } 01000 new_v = ast_variable_new(field_var_name, field_var_val, ""); 01001 ast_variable_append(cur_cat, new_v); 01002 } 01003 } else { 01004 ast_log(LOG_WARNING, 01005 "PostgreSQL RealTime: Could not find config '%s' in database.\n", file); 01006 } 01007 01008 PQclear(result); 01009 ast_mutex_unlock(&pgsql_lock); 01010 01011 return cfg; 01012 }
static int destroy_pgsql | ( | const char * | database, | |
const char * | table, | |||
const char * | keyfield, | |||
const char * | lookup, | |||
va_list | ap | |||
) | [static] |
Definition at line 816 of file res_config_pgsql.c.
References ast_debug, ast_free, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_str_append(), ast_str_create(), ast_str_set(), ast_strlen_zero(), ESCAPE_STRING, LOG_WARNING, pgsql_lock, pgsql_reconnect(), and ast_str::str.
00817 { 00818 PGresult *result = NULL; 00819 int numrows = 0; 00820 int pgresult; 00821 struct ast_str *sql = ast_str_create(256); 00822 struct ast_str *buf1 = ast_str_create(60), *buf2 = ast_str_create(60); 00823 const char *newparam, *newval; 00824 00825 if (!table) { 00826 ast_log(LOG_WARNING, "PostgreSQL RealTime: No table specified.\n"); 00827 return -1; 00828 } 00829 00830 /* Get the first parameter and first value in our list of passed paramater/value pairs */ 00831 /*newparam = va_arg(ap, const char *); 00832 newval = va_arg(ap, const char *); 00833 if (!newparam || !newval) {*/ 00834 if (ast_strlen_zero(keyfield) || ast_strlen_zero(lookup)) { 00835 ast_log(LOG_WARNING, 00836 "PostgreSQL RealTime: Realtime destroy requires at least 1 parameter and 1 value to search on.\n"); 00837 if (pgsqlConn) { 00838 PQfinish(pgsqlConn); 00839 pgsqlConn = NULL; 00840 }; 00841 return -1; 00842 } 00843 00844 /* Must connect to the server before anything else, as the escape function requires the connection handle.. */ 00845 ast_mutex_lock(&pgsql_lock); 00846 if (!pgsql_reconnect(database)) { 00847 ast_mutex_unlock(&pgsql_lock); 00848 return -1; 00849 } 00850 00851 00852 /* Create the first part of the query using the first parameter/value pairs we just extracted 00853 If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */ 00854 00855 ESCAPE_STRING(buf1, keyfield); 00856 ESCAPE_STRING(buf2, lookup); 00857 ast_str_set(&sql, 0, "DELETE FROM %s WHERE %s = '%s'", table, buf1->str, buf2->str); 00858 while ((newparam = va_arg(ap, const char *))) { 00859 newval = va_arg(ap, const char *); 00860 ESCAPE_STRING(buf1, newparam); 00861 ESCAPE_STRING(buf2, newval); 00862 ast_str_append(&sql, 0, " AND %s = '%s'", buf1->str, buf2->str); 00863 } 00864 va_end(ap); 00865 00866 ast_debug(1, "PostgreSQL RealTime: Delete SQL: %s\n", sql->str); 00867 00868 if (!(result = PQexec(pgsqlConn, sql->str))) { 00869 ast_log(LOG_WARNING, 00870 "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n"); 00871 ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql->str); 00872 ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s\n", PQerrorMessage(pgsqlConn)); 00873 ast_mutex_unlock(&pgsql_lock); 00874 ast_free(buf1); 00875 ast_free(buf2); 00876 ast_free(sql); 00877 return -1; 00878 } else { 00879 ExecStatusType result_status = PQresultStatus(result); 00880 if (result_status != PGRES_COMMAND_OK 00881 && result_status != PGRES_TUPLES_OK 00882 && result_status != PGRES_NONFATAL_ERROR) { 00883 ast_log(LOG_WARNING, 00884 "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n"); 00885 ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql->str); 00886 ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s (%s)\n", 00887 PQresultErrorMessage(result), PQresStatus(result_status)); 00888 ast_mutex_unlock(&pgsql_lock); 00889 ast_free(buf1); 00890 ast_free(buf2); 00891 ast_free(sql); 00892 return -1; 00893 } 00894 } 00895 00896 numrows = atoi(PQcmdTuples(result)); 00897 ast_mutex_unlock(&pgsql_lock); 00898 ast_free(buf1); 00899 ast_free(buf2); 00900 ast_free(sql); 00901 00902 ast_debug(1, "PostgreSQL RealTime: Deleted %d rows on table: %s\n", numrows, table); 00903 00904 /* From http://dev.pgsql.com/doc/pgsql/en/pgsql-affected-rows.html 00905 * An integer greater than zero indicates the number of rows affected 00906 * Zero indicates that no records were updated 00907 * -1 indicates that the query returned an error (although, if the query failed, it should have been caught above.) 00908 */ 00909 00910 if (numrows >= 0) 00911 return (int) numrows; 00912 00913 return -1; 00914 }
static void destroy_table | ( | struct tables * | table | ) | [static] |
Definition at line 92 of file res_config_pgsql.c.
References ast_free, AST_LIST_REMOVE_HEAD, ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), columns::list, and table.
Referenced by find_table(), unload_module(), and unload_pgsql().
00093 { 00094 struct columns *column; 00095 ast_mutex_lock(&table->lock); 00096 while ((column = AST_LIST_REMOVE_HEAD(&table->columns, list))) { 00097 ast_free(column); 00098 } 00099 ast_mutex_unlock(&table->lock); 00100 ast_mutex_destroy(&table->lock); 00101 ast_free(table); 00102 }
static struct tables* find_table | ( | const char * | orig_tablename | ) | [static] |
Definition at line 104 of file res_config_pgsql.c.
References ast_calloc, ast_debug, AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_mutex_init(), ast_mutex_lock(), ast_str_create(), ast_str_set(), ast_strdupa, ast_strlen_zero(), ast_verb, destroy_table(), has_schema_support, columns::list, LOG_ERROR, ast_str::str, and table.
Referenced by cdr_handler(), handle_cli_realtime_pgsql_cache(), realtime_require_handler(), require_pgsql(), and update_pgsql().
00105 { 00106 struct columns *column; 00107 struct tables *table; 00108 struct ast_str *sql = ast_str_create(330); 00109 char *pgerror; 00110 PGresult *result; 00111 char *fname, *ftype, *flen, *fnotnull, *fdef; 00112 int i, rows; 00113 00114 AST_LIST_LOCK(&psql_tables); 00115 AST_LIST_TRAVERSE(&psql_tables, table, list) { 00116 if (!strcasecmp(table->name, orig_tablename)) { 00117 ast_debug(1, "Found table in cache; now locking\n"); 00118 ast_mutex_lock(&table->lock); 00119 ast_debug(1, "Lock cached table; now returning\n"); 00120 AST_LIST_UNLOCK(&psql_tables); 00121 return table; 00122 } 00123 } 00124 00125 ast_debug(1, "Table '%s' not found in cache, querying now\n", orig_tablename); 00126 00127 /* Not found, scan the table */ 00128 if (has_schema_support) { 00129 char *schemaname, *tablename; 00130 if (strchr(orig_tablename, '.')) { 00131 schemaname = ast_strdupa(orig_tablename); 00132 tablename = strchr(schemaname, '.'); 00133 *tablename++ = '\0'; 00134 } else { 00135 schemaname = ""; 00136 tablename = ast_strdupa(orig_tablename); 00137 } 00138 00139 /* Escape special characters in schemaname */ 00140 if (strchr(schemaname, '\\') || strchr(schemaname, '\'')) { 00141 char *tmp = schemaname, *ptr; 00142 00143 ptr = schemaname = alloca(strlen(tmp) * 2 + 1); 00144 for (; *tmp; tmp++) { 00145 if (strchr("\\'", *tmp)) { 00146 *ptr++ = *tmp; 00147 } 00148 *ptr++ = *tmp; 00149 } 00150 *ptr = '\0'; 00151 } 00152 /* Escape special characters in tablename */ 00153 if (strchr(tablename, '\\') || strchr(tablename, '\'')) { 00154 char *tmp = tablename, *ptr; 00155 00156 ptr = tablename = alloca(strlen(tmp) * 2 + 1); 00157 for (; *tmp; tmp++) { 00158 if (strchr("\\'", *tmp)) { 00159 *ptr++ = *tmp; 00160 } 00161 *ptr++ = *tmp; 00162 } 00163 *ptr = '\0'; 00164 } 00165 00166 ast_str_set(&sql, 0, "SELECT a.attname, t.typname, a.attlen, a.attnotnull, d.adsrc, a.atttypmod FROM (((pg_catalog.pg_class c INNER JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace AND c.relname = '%s' AND n.nspname = %s%s%s) INNER JOIN pg_catalog.pg_attribute a ON (NOT a.attisdropped) AND a.attnum > 0 AND a.attrelid = c.oid) INNER JOIN pg_catalog.pg_type t ON t.oid = a.atttypid) LEFT OUTER JOIN pg_attrdef d ON a.atthasdef AND d.adrelid = a.attrelid AND d.adnum = a.attnum ORDER BY n.nspname, c.relname, attnum", 00167 tablename, 00168 ast_strlen_zero(schemaname) ? "" : "'", ast_strlen_zero(schemaname) ? "current_schema()" : schemaname, ast_strlen_zero(schemaname) ? "" : "'"); 00169 } else { 00170 /* Escape special characters in tablename */ 00171 if (strchr(orig_tablename, '\\') || strchr(orig_tablename, '\'')) { 00172 const char *tmp = orig_tablename; 00173 char *ptr; 00174 00175 orig_tablename = ptr = alloca(strlen(tmp) * 2 + 1); 00176 for (; *tmp; tmp++) { 00177 if (strchr("\\'", *tmp)) { 00178 *ptr++ = *tmp; 00179 } 00180 *ptr++ = *tmp; 00181 } 00182 *ptr = '\0'; 00183 } 00184 00185 ast_str_set(&sql, 0, "SELECT a.attname, t.typname, a.attlen, a.attnotnull, d.adsrc, a.atttypmod FROM pg_class c, pg_type t, pg_attribute a LEFT OUTER JOIN pg_attrdef d ON a.atthasdef AND d.adrelid = a.attrelid AND d.adnum = a.attnum WHERE c.oid = a.attrelid AND a.atttypid = t.oid AND (a.attnum > 0) AND c.relname = '%s' ORDER BY c.relname, attnum", orig_tablename); 00186 } 00187 00188 result = PQexec(pgsqlConn, sql->str); 00189 ast_debug(1, "Query of table structure complete. Now retrieving results.\n"); 00190 if (PQresultStatus(result) != PGRES_TUPLES_OK) { 00191 pgerror = PQresultErrorMessage(result); 00192 ast_log(LOG_ERROR, "Failed to query database columns: %s\n", pgerror); 00193 PQclear(result); 00194 AST_LIST_UNLOCK(&psql_tables); 00195 return NULL; 00196 } 00197 00198 if (!(table = ast_calloc(1, sizeof(*table) + strlen(orig_tablename) + 1))) { 00199 ast_log(LOG_ERROR, "Unable to allocate memory for new table structure\n"); 00200 AST_LIST_UNLOCK(&psql_tables); 00201 return NULL; 00202 } 00203 strcpy(table->name, orig_tablename); /* SAFE */ 00204 ast_mutex_init(&table->lock); 00205 AST_LIST_HEAD_INIT_NOLOCK(&table->columns); 00206 00207 rows = PQntuples(result); 00208 for (i = 0; i < rows; i++) { 00209 fname = PQgetvalue(result, i, 0); 00210 ftype = PQgetvalue(result, i, 1); 00211 flen = PQgetvalue(result, i, 2); 00212 fnotnull = PQgetvalue(result, i, 3); 00213 fdef = PQgetvalue(result, i, 4); 00214 ast_verb(4, "Found column '%s' of type '%s'\n", fname, ftype); 00215 00216 if (!(column = ast_calloc(1, sizeof(*column) + strlen(fname) + strlen(ftype) + 2))) { 00217 ast_log(LOG_ERROR, "Unable to allocate column element for %s, %s\n", orig_tablename, fname); 00218 destroy_table(table); 00219 AST_LIST_UNLOCK(&psql_tables); 00220 return NULL; 00221 } 00222 00223 if (strcmp(flen, "-1") == 0) { 00224 /* Some types, like chars, have the length stored in a different field */ 00225 flen = PQgetvalue(result, i, 5); 00226 sscanf(flen, "%30d", &column->len); 00227 column->len -= 4; 00228 } else { 00229 sscanf(flen, "%30d", &column->len); 00230 } 00231 column->name = (char *)column + sizeof(*column); 00232 column->type = (char *)column + sizeof(*column) + strlen(fname) + 1; 00233 strcpy(column->name, fname); 00234 strcpy(column->type, ftype); 00235 if (*fnotnull == 't') { 00236 column->notnull = 1; 00237 } else { 00238 column->notnull = 0; 00239 } 00240 if (!ast_strlen_zero(fdef)) { 00241 column->hasdefault = 1; 00242 } else { 00243 column->hasdefault = 0; 00244 } 00245 AST_LIST_INSERT_TAIL(&table->columns, column, list); 00246 } 00247 PQclear(result); 00248 00249 AST_LIST_INSERT_TAIL(&psql_tables, table, list); 00250 ast_mutex_lock(&table->lock); 00251 AST_LIST_UNLOCK(&psql_tables); 00252 return table; 00253 }
static char * handle_cli_realtime_pgsql_cache | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1370 of file res_config_pgsql.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_unlock(), ast_strdup, CLI_GENERATE, CLI_INIT, tables::columns, ast_cli_entry::command, ast_cli_args::fd, find_table(), columns::len, columns::list, tables::lock, ast_cli_args::n, columns::name, tables::name, columns::notnull, columns::type, ast_cli_entry::usage, and ast_cli_args::word.
01371 { 01372 struct tables *cur; 01373 int l, which; 01374 char *ret = NULL; 01375 01376 switch (cmd) { 01377 case CLI_INIT: 01378 e->command = "realtime pgsql cache"; 01379 e->usage = 01380 "Usage: realtime pgsql cache [<table>]\n" 01381 " Shows table cache for the PostgreSQL RealTime driver\n"; 01382 return NULL; 01383 case CLI_GENERATE: 01384 if (a->argc != 3) { 01385 return NULL; 01386 } 01387 l = strlen(a->word); 01388 which = 0; 01389 AST_LIST_LOCK(&psql_tables); 01390 AST_LIST_TRAVERSE(&psql_tables, cur, list) { 01391 if (!strncasecmp(a->word, cur->name, l) && ++which > a->n) { 01392 ret = ast_strdup(cur->name); 01393 break; 01394 } 01395 } 01396 AST_LIST_UNLOCK(&psql_tables); 01397 return ret; 01398 } 01399 01400 if (a->argc == 3) { 01401 /* List of tables */ 01402 AST_LIST_LOCK(&psql_tables); 01403 AST_LIST_TRAVERSE(&psql_tables, cur, list) { 01404 ast_cli(a->fd, "%s\n", cur->name); 01405 } 01406 AST_LIST_UNLOCK(&psql_tables); 01407 } else if (a->argc == 4) { 01408 /* List of columns */ 01409 if ((cur = find_table(a->argv[3]))) { 01410 struct columns *col; 01411 ast_cli(a->fd, "Columns for Table Cache '%s':\n", a->argv[3]); 01412 ast_cli(a->fd, "%-20.20s %-20.20s %-3.3s %-8.8s\n", "Name", "Type", "Len", "Nullable"); 01413 AST_LIST_TRAVERSE(&cur->columns, col, list) { 01414 ast_cli(a->fd, "%-20.20s %-20.20s %3d %-8.8s\n", col->name, col->type, col->len, col->notnull ? "NOT NULL" : ""); 01415 } 01416 ast_mutex_unlock(&cur->lock); 01417 } else { 01418 ast_cli(a->fd, "No such table '%s'\n", a->argv[3]); 01419 } 01420 } 01421 return 0; 01422 }
static char * handle_cli_realtime_pgsql_status | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1424 of file res_config_pgsql.c.
References ast_cli_args::argc, ast_cli(), ast_strlen_zero(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, connect_time, dbhost, dbname, dbport, dbsock, dbuser, ast_cli_args::fd, status, and ast_cli_entry::usage.
01425 { 01426 char status[256], credentials[100] = ""; 01427 int ctimesec = time(NULL) - connect_time; 01428 01429 switch (cmd) { 01430 case CLI_INIT: 01431 e->command = "realtime pgsql status"; 01432 e->usage = 01433 "Usage: realtime pgsql status\n" 01434 " Shows connection information for the PostgreSQL RealTime driver\n"; 01435 return NULL; 01436 case CLI_GENERATE: 01437 return NULL; 01438 } 01439 01440 if (a->argc != 3) 01441 return CLI_SHOWUSAGE; 01442 01443 if (pgsqlConn && PQstatus(pgsqlConn) == CONNECTION_OK) { 01444 if (!ast_strlen_zero(dbhost)) 01445 snprintf(status, sizeof(status), "Connected to %s@%s, port %d", dbname, dbhost, dbport); 01446 else if (!ast_strlen_zero(dbsock)) 01447 snprintf(status, sizeof(status), "Connected to %s on socket file %s", dbname, dbsock); 01448 else 01449 snprintf(status, sizeof(status), "Connected to %s@%s", dbname, dbhost); 01450 01451 if (!ast_strlen_zero(dbuser)) 01452 snprintf(credentials, sizeof(credentials), " with username %s", dbuser); 01453 01454 if (ctimesec > 31536000) 01455 ast_cli(a->fd, "%s%s for %d years, %d days, %d hours, %d minutes, %d seconds.\n", 01456 status, credentials, ctimesec / 31536000, (ctimesec % 31536000) / 86400, 01457 (ctimesec % 86400) / 3600, (ctimesec % 3600) / 60, ctimesec % 60); 01458 else if (ctimesec > 86400) 01459 ast_cli(a->fd, "%s%s for %d days, %d hours, %d minutes, %d seconds.\n", status, 01460 credentials, ctimesec / 86400, (ctimesec % 86400) / 3600, (ctimesec % 3600) / 60, 01461 ctimesec % 60); 01462 else if (ctimesec > 3600) 01463 ast_cli(a->fd, "%s%s for %d hours, %d minutes, %d seconds.\n", status, credentials, 01464 ctimesec / 3600, (ctimesec % 3600) / 60, ctimesec % 60); 01465 else if (ctimesec > 60) 01466 ast_cli(a->fd, "%s%s for %d minutes, %d seconds.\n", status, credentials, ctimesec / 60, 01467 ctimesec % 60); 01468 else 01469 ast_cli(a->fd, "%s%s for %d seconds.\n", status, credentials, ctimesec); 01470 01471 return CLI_SUCCESS; 01472 } else { 01473 return CLI_FAILURE; 01474 } 01475 }
static int load_module | ( | void | ) | [static] |
Definition at line 1169 of file res_config_pgsql.c.
References ast_cli_register_multiple(), ast_config_engine_register(), AST_MODULE_LOAD_DECLINE, ast_verb, cli_realtime, parse_config(), and pgsql_engine.
01170 { 01171 if(!parse_config(0)) 01172 return AST_MODULE_LOAD_DECLINE; 01173 01174 ast_config_engine_register(&pgsql_engine); 01175 ast_verb(1, "PostgreSQL RealTime driver loaded.\n"); 01176 ast_cli_register_multiple(cli_realtime, sizeof(cli_realtime) / sizeof(struct ast_cli_entry)); 01177 01178 return 0; 01179 }
static int parse_config | ( | int | reload | ) | [static] |
Definition at line 1215 of file res_config_pgsql.c.
References ast_config_destroy(), ast_config_load, ast_copy_string(), ast_debug, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), ast_variable_retrieve(), ast_verb, config, CONFIG_FLAG_FILEUNCHANGED, config_flags, CONFIG_STATUS_FILEUNCHANGED, dbhost, dbname, dbpass, dbport, dbsock, dbuser, LOG_WARNING, option_debug, pgsql_lock, pgsql_reconnect(), requirements, RES_CONFIG_PGSQL_CONF, RQ_CREATECHAR, RQ_CREATECLOSE, RQ_WARN, and s.
01216 { 01217 struct ast_config *config; 01218 const char *s; 01219 struct ast_flags config_flags = { is_reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 01220 01221 if ((config = ast_config_load(RES_CONFIG_PGSQL_CONF, config_flags)) == CONFIG_STATUS_FILEUNCHANGED) 01222 return 0; 01223 01224 if (!config) { 01225 ast_log(LOG_WARNING, "Unable to load config %s\n", RES_CONFIG_PGSQL_CONF); 01226 return 0; 01227 } 01228 01229 ast_mutex_lock(&pgsql_lock); 01230 01231 if (pgsqlConn) { 01232 PQfinish(pgsqlConn); 01233 pgsqlConn = NULL; 01234 } 01235 01236 if (!(s = ast_variable_retrieve(config, "general", "dbuser"))) { 01237 ast_log(LOG_WARNING, 01238 "PostgreSQL RealTime: No database user found, using 'asterisk' as default.\n"); 01239 strcpy(dbuser, "asterisk"); 01240 } else { 01241 ast_copy_string(dbuser, s, sizeof(dbuser)); 01242 } 01243 01244 if (!(s = ast_variable_retrieve(config, "general", "dbpass"))) { 01245 ast_log(LOG_WARNING, 01246 "PostgreSQL RealTime: No database password found, using 'asterisk' as default.\n"); 01247 strcpy(dbpass, "asterisk"); 01248 } else { 01249 ast_copy_string(dbpass, s, sizeof(dbpass)); 01250 } 01251 01252 if (!(s = ast_variable_retrieve(config, "general", "dbhost"))) { 01253 ast_log(LOG_WARNING, 01254 "PostgreSQL RealTime: No database host found, using localhost via socket.\n"); 01255 dbhost[0] = '\0'; 01256 } else { 01257 ast_copy_string(dbhost, s, sizeof(dbhost)); 01258 } 01259 01260 if (!(s = ast_variable_retrieve(config, "general", "dbname"))) { 01261 ast_log(LOG_WARNING, 01262 "PostgreSQL RealTime: No database name found, using 'asterisk' as default.\n"); 01263 strcpy(dbname, "asterisk"); 01264 } else { 01265 ast_copy_string(dbname, s, sizeof(dbname)); 01266 } 01267 01268 if (!(s = ast_variable_retrieve(config, "general", "dbport"))) { 01269 ast_log(LOG_WARNING, 01270 "PostgreSQL RealTime: No database port found, using 5432 as default.\n"); 01271 dbport = 5432; 01272 } else { 01273 dbport = atoi(s); 01274 } 01275 01276 if (!ast_strlen_zero(dbhost)) { 01277 /* No socket needed */ 01278 } else if (!(s = ast_variable_retrieve(config, "general", "dbsock"))) { 01279 ast_log(LOG_WARNING, 01280 "PostgreSQL RealTime: No database socket found, using '/tmp/pgsql.sock' as default.\n"); 01281 strcpy(dbsock, "/tmp/pgsql.sock"); 01282 } else { 01283 ast_copy_string(dbsock, s, sizeof(dbsock)); 01284 } 01285 01286 if (!(s = ast_variable_retrieve(config, "general", "requirements"))) { 01287 ast_log(LOG_WARNING, 01288 "PostgreSQL RealTime: no requirements setting found, using 'warn' as default.\n"); 01289 requirements = RQ_WARN; 01290 } else if (!strcasecmp(s, "createclose")) { 01291 requirements = RQ_CREATECLOSE; 01292 } else if (!strcasecmp(s, "createchar")) { 01293 requirements = RQ_CREATECHAR; 01294 } 01295 01296 ast_config_destroy(config); 01297 01298 if (option_debug) { 01299 if (!ast_strlen_zero(dbhost)) { 01300 ast_debug(1, "PostgreSQL RealTime Host: %s\n", dbhost); 01301 ast_debug(1, "PostgreSQL RealTime Port: %i\n", dbport); 01302 } else { 01303 ast_debug(1, "PostgreSQL RealTime Socket: %s\n", dbsock); 01304 } 01305 ast_debug(1, "PostgreSQL RealTime User: %s\n", dbuser); 01306 ast_debug(1, "PostgreSQL RealTime Password: %s\n", dbpass); 01307 ast_debug(1, "PostgreSQL RealTime DBName: %s\n", dbname); 01308 } 01309 01310 if (!pgsql_reconnect(NULL)) { 01311 ast_log(LOG_WARNING, 01312 "PostgreSQL RealTime: Couldn't establish connection. Check debug.\n"); 01313 ast_debug(1, "PostgreSQL RealTime: Cannot Connect: %s\n", PQerrorMessage(pgsqlConn)); 01314 } 01315 01316 ast_verb(2, "PostgreSQL RealTime reloaded.\n"); 01317 01318 /* Done reloading. Release lock so others can now use driver. */ 01319 ast_mutex_unlock(&pgsql_lock); 01320 01321 return 1; 01322 }
static int pgsql_reconnect | ( | const char * | database | ) | [static] |
Definition at line 1324 of file res_config_pgsql.c.
References ast_copy_string(), ast_debug, ast_free, ast_log(), ast_str_append(), ast_str_create(), ast_str_set(), ast_strlen_zero(), connect_time, dbhost, dbname, dbpass, dbport, dbsock, dbuser, LOG_ERROR, and S_OR.
Referenced by config_pgsql(), destroy_pgsql(), parse_config(), realtime_multi_pgsql(), realtime_pgsql(), require_pgsql(), store_pgsql(), and update_pgsql().
01325 { 01326 char my_database[50]; 01327 01328 ast_copy_string(my_database, S_OR(database, dbname), sizeof(my_database)); 01329 01330 /* mutex lock should have been locked before calling this function. */ 01331 01332 if (pgsqlConn && PQstatus(pgsqlConn) != CONNECTION_OK) { 01333 PQfinish(pgsqlConn); 01334 pgsqlConn = NULL; 01335 } 01336 01337 /* DB password can legitimately be 0-length */ 01338 if ((!pgsqlConn) && (!ast_strlen_zero(dbhost) || !ast_strlen_zero(dbsock)) && !ast_strlen_zero(dbuser) && !ast_strlen_zero(my_database)) { 01339 struct ast_str *connInfo = ast_str_create(32); 01340 01341 ast_str_set(&connInfo, 0, "host=%s port=%d dbname=%s user=%s", 01342 dbhost, dbport, my_database, dbuser); 01343 if (!ast_strlen_zero(dbpass)) 01344 ast_str_append(&connInfo, 0, " password=%s", dbpass); 01345 01346 ast_debug(1, "%u connInfo=%s\n", (unsigned int)connInfo->len, connInfo->str); 01347 pgsqlConn = PQconnectdb(connInfo->str); 01348 ast_debug(1, "%u connInfo=%s\n", (unsigned int)connInfo->len, connInfo->str); 01349 ast_free(connInfo); 01350 connInfo = NULL; 01351 01352 ast_debug(1, "pgsqlConn=%p\n", pgsqlConn); 01353 if (pgsqlConn && PQstatus(pgsqlConn) == CONNECTION_OK) { 01354 ast_debug(1, "PostgreSQL RealTime: Successfully connected to database.\n"); 01355 connect_time = time(NULL); 01356 version = PQserverVersion(pgsqlConn); 01357 return 1; 01358 } else { 01359 ast_log(LOG_ERROR, 01360 "PostgreSQL RealTime: Failed to connect database %s on %s: %s\n", 01361 dbname, dbhost, PQresultErrorMessage(NULL)); 01362 return 0; 01363 } 01364 } else { 01365 ast_debug(1, "PostgreSQL RealTime: One or more of the parameters in the config does not pass our validity checks.\n"); 01366 return 1; 01367 } 01368 }
static struct ast_config* realtime_multi_pgsql | ( | const char * | database, | |
const char * | table, | |||
va_list | ap | |||
) | [static] |
Definition at line 391 of file res_config_pgsql.c.
References ast_calloc, ast_category_append(), ast_category_new(), ast_category_rename(), ast_config_new(), ast_debug, ast_free, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_strdupa, ast_strip(), ast_strlen_zero(), ast_variable_append(), ast_variable_new(), LOG_ERROR, LOG_WARNING, pgsql_lock, pgsql_reconnect(), strsep(), and var.
00392 { 00393 PGresult *result = NULL; 00394 int num_rows = 0, pgerror; 00395 char sql[256], escapebuf[513]; 00396 const char *initfield = NULL; 00397 char *stringp; 00398 char *chunk; 00399 char *op; 00400 const char *newparam, *newval; 00401 struct ast_variable *var = NULL; 00402 struct ast_config *cfg = NULL; 00403 struct ast_category *cat = NULL; 00404 00405 if (!table) { 00406 ast_log(LOG_WARNING, "PostgreSQL RealTime: No table specified.\n"); 00407 return NULL; 00408 } 00409 00410 if (!(cfg = ast_config_new())) 00411 return NULL; 00412 00413 /* Get the first parameter and first value in our list of passed paramater/value pairs */ 00414 newparam = va_arg(ap, const char *); 00415 newval = va_arg(ap, const char *); 00416 if (!newparam || !newval) { 00417 ast_log(LOG_WARNING, 00418 "PostgreSQL RealTime: Realtime retrieval requires at least 1 parameter and 1 value to search on.\n"); 00419 if (pgsqlConn) { 00420 PQfinish(pgsqlConn); 00421 pgsqlConn = NULL; 00422 }; 00423 return NULL; 00424 } 00425 00426 initfield = ast_strdupa(newparam); 00427 if ((op = strchr(initfield, ' '))) { 00428 *op = '\0'; 00429 } 00430 00431 /* Create the first part of the query using the first parameter/value pairs we just extracted 00432 If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */ 00433 00434 if (!strchr(newparam, ' ')) 00435 op = " ="; 00436 else 00437 op = ""; 00438 00439 PQescapeStringConn(pgsqlConn, escapebuf, newval, (sizeof(escapebuf) - 1) / 2, &pgerror); 00440 if (pgerror) { 00441 ast_log(LOG_ERROR, "Postgres detected invalid input: '%s'\n", newval); 00442 va_end(ap); 00443 return NULL; 00444 } 00445 00446 snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s '%s'", table, newparam, op, 00447 escapebuf); 00448 while ((newparam = va_arg(ap, const char *))) { 00449 newval = va_arg(ap, const char *); 00450 if (!strchr(newparam, ' ')) 00451 op = " ="; 00452 else 00453 op = ""; 00454 00455 PQescapeStringConn(pgsqlConn, escapebuf, newval, (sizeof(escapebuf) - 1) / 2, &pgerror); 00456 if (pgerror) { 00457 ast_log(LOG_ERROR, "Postgres detected invalid input: '%s'\n", newval); 00458 va_end(ap); 00459 return NULL; 00460 } 00461 00462 snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s '%s'", newparam, 00463 op, escapebuf); 00464 } 00465 00466 if (initfield) { 00467 snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " ORDER BY %s", initfield); 00468 } 00469 00470 va_end(ap); 00471 00472 /* We now have our complete statement; Lets connect to the server and execute it. */ 00473 ast_mutex_lock(&pgsql_lock); 00474 if (!pgsql_reconnect(database)) { 00475 ast_mutex_unlock(&pgsql_lock); 00476 return NULL; 00477 } 00478 00479 if (!(result = PQexec(pgsqlConn, sql))) { 00480 ast_log(LOG_WARNING, 00481 "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n"); 00482 ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql); 00483 ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s\n", PQerrorMessage(pgsqlConn)); 00484 ast_mutex_unlock(&pgsql_lock); 00485 return NULL; 00486 } else { 00487 ExecStatusType result_status = PQresultStatus(result); 00488 if (result_status != PGRES_COMMAND_OK 00489 && result_status != PGRES_TUPLES_OK 00490 && result_status != PGRES_NONFATAL_ERROR) { 00491 ast_log(LOG_WARNING, 00492 "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n"); 00493 ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql); 00494 ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s (%s)\n", 00495 PQresultErrorMessage(result), PQresStatus(result_status)); 00496 ast_mutex_unlock(&pgsql_lock); 00497 return NULL; 00498 } 00499 } 00500 00501 ast_debug(1, "PostgreSQL RealTime: Result=%p Query: %s\n", result, sql); 00502 00503 if ((num_rows = PQntuples(result)) > 0) { 00504 int numFields = PQnfields(result); 00505 int i = 0; 00506 int rowIndex = 0; 00507 char **fieldnames = NULL; 00508 00509 ast_debug(1, "PostgreSQL RealTime: Found %d rows.\n", num_rows); 00510 00511 if (!(fieldnames = ast_calloc(1, numFields * sizeof(char *)))) { 00512 ast_mutex_unlock(&pgsql_lock); 00513 PQclear(result); 00514 return NULL; 00515 } 00516 for (i = 0; i < numFields; i++) 00517 fieldnames[i] = PQfname(result, i); 00518 00519 for (rowIndex = 0; rowIndex < num_rows; rowIndex++) { 00520 var = NULL; 00521 if (!(cat = ast_category_new("","",99999))) 00522 continue; 00523 for (i = 0; i < numFields; i++) { 00524 stringp = PQgetvalue(result, rowIndex, i); 00525 while (stringp) { 00526 chunk = strsep(&stringp, ";"); 00527 if (!ast_strlen_zero(ast_strip(chunk))) { 00528 if (initfield && !strcmp(initfield, fieldnames[i])) { 00529 ast_category_rename(cat, chunk); 00530 } 00531 var = ast_variable_new(fieldnames[i], chunk, ""); 00532 ast_variable_append(cat, var); 00533 } 00534 } 00535 } 00536 ast_category_append(cfg, cat); 00537 } 00538 ast_free(fieldnames); 00539 } else { 00540 ast_log(LOG_WARNING, 00541 "PostgreSQL RealTime: Could not find any rows in table %s.\n", table); 00542 } 00543 00544 ast_mutex_unlock(&pgsql_lock); 00545 PQclear(result); 00546 00547 return cfg; 00548 }
static struct ast_variable* realtime_pgsql | ( | const char * | database, | |
const char * | table, | |||
va_list | ap | |||
) | [static] |
Definition at line 255 of file res_config_pgsql.c.
References ast_calloc, ast_debug, ast_free, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_strip(), ast_strlen_zero(), ast_variable_new(), LOG_ERROR, LOG_WARNING, ast_variable::next, pgsql_lock, pgsql_reconnect(), strsep(), and var.
00256 { 00257 PGresult *result = NULL; 00258 int num_rows = 0, pgerror; 00259 char sql[256], escapebuf[513]; 00260 char *stringp; 00261 char *chunk; 00262 char *op; 00263 const char *newparam, *newval; 00264 struct ast_variable *var = NULL, *prev = NULL; 00265 00266 if (!table) { 00267 ast_log(LOG_WARNING, "PostgreSQL RealTime: No table specified.\n"); 00268 return NULL; 00269 } 00270 00271 /* Get the first parameter and first value in our list of passed paramater/value pairs */ 00272 newparam = va_arg(ap, const char *); 00273 newval = va_arg(ap, const char *); 00274 if (!newparam || !newval) { 00275 ast_log(LOG_WARNING, 00276 "PostgreSQL RealTime: Realtime retrieval requires at least 1 parameter and 1 value to search on.\n"); 00277 if (pgsqlConn) { 00278 PQfinish(pgsqlConn); 00279 pgsqlConn = NULL; 00280 }; 00281 return NULL; 00282 } 00283 00284 /* Create the first part of the query using the first parameter/value pairs we just extracted 00285 If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */ 00286 op = strchr(newparam, ' ') ? "" : " ="; 00287 00288 PQescapeStringConn(pgsqlConn, escapebuf, newval, (sizeof(escapebuf) - 1) / 2, &pgerror); 00289 if (pgerror) { 00290 ast_log(LOG_ERROR, "Postgres detected invalid input: '%s'\n", newval); 00291 va_end(ap); 00292 return NULL; 00293 } 00294 00295 snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s '%s'", table, newparam, op, 00296 escapebuf); 00297 while ((newparam = va_arg(ap, const char *))) { 00298 newval = va_arg(ap, const char *); 00299 if (!strchr(newparam, ' ')) 00300 op = " ="; 00301 else 00302 op = ""; 00303 00304 PQescapeStringConn(pgsqlConn, escapebuf, newval, (sizeof(escapebuf) - 1) / 2, &pgerror); 00305 if (pgerror) { 00306 ast_log(LOG_ERROR, "Postgres detected invalid input: '%s'\n", newval); 00307 va_end(ap); 00308 return NULL; 00309 } 00310 00311 snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s '%s'", newparam, 00312 op, escapebuf); 00313 } 00314 va_end(ap); 00315 00316 /* We now have our complete statement; Lets connect to the server and execute it. */ 00317 ast_mutex_lock(&pgsql_lock); 00318 if (!pgsql_reconnect(database)) { 00319 ast_mutex_unlock(&pgsql_lock); 00320 return NULL; 00321 } 00322 00323 if (!(result = PQexec(pgsqlConn, sql))) { 00324 ast_log(LOG_WARNING, 00325 "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n"); 00326 ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql); 00327 ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s\n", PQerrorMessage(pgsqlConn)); 00328 ast_mutex_unlock(&pgsql_lock); 00329 return NULL; 00330 } else { 00331 ExecStatusType result_status = PQresultStatus(result); 00332 if (result_status != PGRES_COMMAND_OK 00333 && result_status != PGRES_TUPLES_OK 00334 && result_status != PGRES_NONFATAL_ERROR) { 00335 ast_log(LOG_WARNING, 00336 "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n"); 00337 ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql); 00338 ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s (%s)\n", 00339 PQresultErrorMessage(result), PQresStatus(result_status)); 00340 ast_mutex_unlock(&pgsql_lock); 00341 return NULL; 00342 } 00343 } 00344 00345 ast_debug(1, "PostgreSQL RealTime: Result=%p Query: %s\n", result, sql); 00346 00347 if ((num_rows = PQntuples(result)) > 0) { 00348 int i = 0; 00349 int rowIndex = 0; 00350 int numFields = PQnfields(result); 00351 char **fieldnames = NULL; 00352 00353 ast_debug(1, "PostgreSQL RealTime: Found %d rows.\n", num_rows); 00354 00355 if (!(fieldnames = ast_calloc(1, numFields * sizeof(char *)))) { 00356 ast_mutex_unlock(&pgsql_lock); 00357 PQclear(result); 00358 return NULL; 00359 } 00360 for (i = 0; i < numFields; i++) 00361 fieldnames[i] = PQfname(result, i); 00362 for (rowIndex = 0; rowIndex < num_rows; rowIndex++) { 00363 for (i = 0; i < numFields; i++) { 00364 stringp = PQgetvalue(result, rowIndex, i); 00365 while (stringp) { 00366 chunk = strsep(&stringp, ";"); 00367 if (!ast_strlen_zero(ast_strip(chunk))) { 00368 if (prev) { 00369 prev->next = ast_variable_new(fieldnames[i], chunk, ""); 00370 if (prev->next) { 00371 prev = prev->next; 00372 } 00373 } else { 00374 prev = var = ast_variable_new(fieldnames[i], chunk, ""); 00375 } 00376 } 00377 } 00378 } 00379 } 00380 ast_free(fieldnames); 00381 } else { 00382 ast_debug(1, "Postgresql RealTime: Could not find any rows in table %s.\n", table); 00383 } 00384 00385 ast_mutex_unlock(&pgsql_lock); 00386 PQclear(result); 00387 00388 return var; 00389 }
static int reload | ( | void | ) | [static] |
Definition at line 1208 of file res_config_pgsql.c.
References parse_config().
01209 { 01210 parse_config(1); 01211 01212 return 0; 01213 }
static int require_pgsql | ( | const char * | database, | |
const char * | tablename, | |||
va_list | ap | |||
) | [static] |
Definition at line 1014 of file res_config_pgsql.c.
References ast_debug, ast_free, AST_LIST_TRAVERSE, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_rq_is_int(), ast_str_create(), ast_str_set(), find_table(), columns::len, columns::list, LOG_ERROR, LOG_WARNING, columns::name, pgsql_lock, pgsql_reconnect(), requirements, RQ_CHAR, RQ_CREATECHAR, RQ_DATE, RQ_DATETIME, RQ_FLOAT, RQ_INTEGER1, RQ_INTEGER2, RQ_INTEGER3, RQ_INTEGER4, RQ_INTEGER8, RQ_UINTEGER1, RQ_UINTEGER2, RQ_UINTEGER3, RQ_UINTEGER4, RQ_UINTEGER8, RQ_WARN, columns::size, ast_str::str, table, and columns::type.
01015 { 01016 struct columns *column; 01017 struct tables *table = find_table(tablename); 01018 char *elm; 01019 int type, size, res = 0; 01020 01021 if (!table) { 01022 ast_log(LOG_WARNING, "Table %s not found in database. This table should exist if you're using realtime.\n", tablename); 01023 return -1; 01024 } 01025 01026 while ((elm = va_arg(ap, char *))) { 01027 type = va_arg(ap, require_type); 01028 size = va_arg(ap, int); 01029 AST_LIST_TRAVERSE(&table->columns, column, list) { 01030 if (strcmp(column->name, elm) == 0) { 01031 /* Char can hold anything, as long as it is large enough */ 01032 if ((strncmp(column->type, "char", 4) == 0 || strncmp(column->type, "varchar", 7) == 0 || strcmp(column->type, "bpchar") == 0)) { 01033 if ((size > column->len) && column->len != -1) { 01034 ast_log(LOG_WARNING, "Column '%s' should be at least %d long, but is only %d long.\n", column->name, size, column->len); 01035 res = -1; 01036 } 01037 } else if (strncmp(column->type, "int", 3) == 0) { 01038 int typesize = atoi(column->type + 3); 01039 /* Integers can hold only other integers */ 01040 if ((type == RQ_INTEGER8 || type == RQ_UINTEGER8 || 01041 type == RQ_INTEGER4 || type == RQ_UINTEGER4 || 01042 type == RQ_INTEGER3 || type == RQ_UINTEGER3 || 01043 type == RQ_UINTEGER2) && typesize == 2) { 01044 ast_log(LOG_WARNING, "Column '%s' may not be large enough for the required data length: %d\n", column->name, size); 01045 res = -1; 01046 } else if ((type == RQ_INTEGER8 || type == RQ_UINTEGER8 || 01047 type == RQ_UINTEGER4) && typesize == 4) { 01048 ast_log(LOG_WARNING, "Column '%s' may not be large enough for the required data length: %d\n", column->name, size); 01049 res = -1; 01050 } else if (type == RQ_CHAR || type == RQ_DATETIME || type == RQ_FLOAT || type == RQ_DATE) { 01051 ast_log(LOG_WARNING, "Column '%s' is of the incorrect type: (need %s(%d) but saw %s)\n", 01052 column->name, 01053 type == RQ_CHAR ? "char" : 01054 type == RQ_DATETIME ? "datetime" : 01055 type == RQ_DATE ? "date" : 01056 type == RQ_FLOAT ? "float" : 01057 "a rather stiff drink ", 01058 size, column->type); 01059 res = -1; 01060 } 01061 } else if (strncmp(column->type, "float", 5) == 0 && !ast_rq_is_int(type) && type != RQ_FLOAT) { 01062 ast_log(LOG_WARNING, "Column %s cannot be a %s\n", column->name, column->type); 01063 res = -1; 01064 } else { /* There are other types that no module implements yet */ 01065 ast_log(LOG_WARNING, "Possibly unsupported column type '%s' on column '%s'\n", column->type, column->name); 01066 res = -1; 01067 } 01068 break; 01069 } 01070 } 01071 01072 if (!column) { 01073 if (requirements == RQ_WARN) { 01074 ast_log(LOG_WARNING, "Table %s requires a column '%s' of size '%d', but no such column exists.\n", tablename, elm, size); 01075 } else { 01076 struct ast_str *sql = ast_str_create(100); 01077 char fieldtype[15]; 01078 PGresult *result; 01079 01080 if (requirements == RQ_CREATECHAR || type == RQ_CHAR) { 01081 /* Size is minimum length; make it at least 50% greater, 01082 * just to be sure, because PostgreSQL doesn't support 01083 * resizing columns. */ 01084 snprintf(fieldtype, sizeof(fieldtype), "CHAR(%d)", 01085 size < 15 ? size * 2 : 01086 (size * 3 / 2 > 255) ? 255 : size * 3 / 2); 01087 } else if (type == RQ_INTEGER1 || type == RQ_UINTEGER1 || type == RQ_INTEGER2) { 01088 snprintf(fieldtype, sizeof(fieldtype), "INT2"); 01089 } else if (type == RQ_UINTEGER2 || type == RQ_INTEGER3 || type == RQ_UINTEGER3 || type == RQ_INTEGER4) { 01090 snprintf(fieldtype, sizeof(fieldtype), "INT4"); 01091 } else if (type == RQ_UINTEGER4 || type == RQ_INTEGER8) { 01092 snprintf(fieldtype, sizeof(fieldtype), "INT8"); 01093 } else if (type == RQ_UINTEGER8) { 01094 /* No such type on PostgreSQL */ 01095 snprintf(fieldtype, sizeof(fieldtype), "CHAR(20)"); 01096 } else if (type == RQ_FLOAT) { 01097 snprintf(fieldtype, sizeof(fieldtype), "FLOAT8"); 01098 } else if (type == RQ_DATE) { 01099 snprintf(fieldtype, sizeof(fieldtype), "DATE"); 01100 } else if (type == RQ_DATETIME) { 01101 snprintf(fieldtype, sizeof(fieldtype), "TIMESTAMP"); 01102 } else { 01103 ast_log(LOG_ERROR, "Unrecognized request type %d\n", type); 01104 ast_free(sql); 01105 continue; 01106 } 01107 ast_str_set(&sql, 0, "ALTER TABLE %s ADD COLUMN %s %s", tablename, elm, fieldtype); 01108 ast_debug(1, "About to lock pgsql_lock (running alter on table '%s' to add column '%s')\n", tablename, elm); 01109 01110 ast_mutex_lock(&pgsql_lock); 01111 if (!pgsql_reconnect(database)) { 01112 ast_mutex_unlock(&pgsql_lock); 01113 ast_log(LOG_ERROR, "Unable to add column: %s\n", sql->str); 01114 ast_free(sql); 01115 continue; 01116 } 01117 01118 ast_debug(1, "About to run ALTER query on table '%s' to add column '%s'\n", tablename, elm); 01119 result = PQexec(pgsqlConn, sql->str); 01120 ast_debug(1, "Finished running ALTER query on table '%s'\n", tablename); 01121 if (PQresultStatus(result) != PGRES_COMMAND_OK) { 01122 ast_log(LOG_ERROR, "Unable to add column: %s\n", sql->str); 01123 } 01124 PQclear(result); 01125 ast_mutex_unlock(&pgsql_lock); 01126 01127 ast_free(sql); 01128 } 01129 } 01130 } 01131 ast_mutex_unlock(&table->lock); 01132 return res; 01133 }
static int store_pgsql | ( | const char * | database, | |
const char * | table, | |||
va_list | ap | |||
) | [static] |
Definition at line 715 of file res_config_pgsql.c.
References ast_debug, ast_free, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_str_append(), ast_str_create(), ast_str_set(), buf, ESCAPE_STRING, LOG_WARNING, pgsql_lock, pgsql_reconnect(), and ast_str::str.
00716 { 00717 PGresult *result = NULL; 00718 Oid insertid; 00719 struct ast_str *buf = ast_str_create(256); 00720 struct ast_str *sql1 = ast_str_create(256); 00721 struct ast_str *sql2 = ast_str_create(256); 00722 int pgresult; 00723 const char *newparam, *newval; 00724 00725 if (!table) { 00726 ast_log(LOG_WARNING, "PostgreSQL RealTime: No table specified.\n"); 00727 return -1; 00728 } 00729 00730 /* Get the first parameter and first value in our list of passed paramater/value pairs */ 00731 newparam = va_arg(ap, const char *); 00732 newval = va_arg(ap, const char *); 00733 if (!newparam || !newval) { 00734 ast_log(LOG_WARNING, 00735 "PostgreSQL RealTime: Realtime storage requires at least 1 parameter and 1 value to store.\n"); 00736 if (pgsqlConn) { 00737 PQfinish(pgsqlConn); 00738 pgsqlConn = NULL; 00739 } 00740 return -1; 00741 } 00742 00743 /* Must connect to the server before anything else, as the escape function requires the connection handle.. */ 00744 ast_mutex_lock(&pgsql_lock); 00745 if (!pgsql_reconnect(database)) { 00746 ast_mutex_unlock(&pgsql_lock); 00747 return -1; 00748 } 00749 00750 /* Create the first part of the query using the first parameter/value pairs we just extracted 00751 If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */ 00752 ESCAPE_STRING(buf, newparam); 00753 ast_str_set(&sql1, 0, "INSERT INTO %s (%s", table, buf->str); 00754 ESCAPE_STRING(buf, newval); 00755 ast_str_set(&sql2, 0, ") VALUES ('%s'", buf->str); 00756 while ((newparam = va_arg(ap, const char *))) { 00757 newval = va_arg(ap, const char *); 00758 ESCAPE_STRING(buf, newparam); 00759 ast_str_append(&sql1, 0, ", %s", buf->str); 00760 ESCAPE_STRING(buf, newval); 00761 ast_str_append(&sql2, 0, ", '%s'", buf->str); 00762 } 00763 va_end(ap); 00764 ast_str_append(&sql1, 0, "%s)", sql2->str); 00765 00766 ast_debug(1, "PostgreSQL RealTime: Insert SQL: %s\n", sql1->str); 00767 00768 if (!(result = PQexec(pgsqlConn, sql1->str))) { 00769 ast_log(LOG_WARNING, 00770 "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n"); 00771 ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql1->str); 00772 ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s\n", PQerrorMessage(pgsqlConn)); 00773 ast_mutex_unlock(&pgsql_lock); 00774 ast_free(sql1); 00775 ast_free(sql2); 00776 ast_free(buf); 00777 return -1; 00778 } else { 00779 ExecStatusType result_status = PQresultStatus(result); 00780 if (result_status != PGRES_COMMAND_OK 00781 && result_status != PGRES_TUPLES_OK 00782 && result_status != PGRES_NONFATAL_ERROR) { 00783 ast_log(LOG_WARNING, 00784 "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n"); 00785 ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql1->str); 00786 ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s (%s)\n", 00787 PQresultErrorMessage(result), PQresStatus(result_status)); 00788 ast_mutex_unlock(&pgsql_lock); 00789 ast_free(sql1); 00790 ast_free(sql2); 00791 ast_free(buf); 00792 return -1; 00793 } 00794 } 00795 00796 insertid = PQoidValue(result); 00797 ast_mutex_unlock(&pgsql_lock); 00798 ast_free(sql1); 00799 ast_free(sql2); 00800 ast_free(buf); 00801 00802 ast_debug(1, "PostgreSQL RealTime: row inserted on table: %s, id: %u\n", table, insertid); 00803 00804 /* From http://dev.pgsql.com/doc/pgsql/en/pgsql-affected-rows.html 00805 * An integer greater than zero indicates the number of rows affected 00806 * Zero indicates that no records were updated 00807 * -1 indicates that the query returned an error (although, if the query failed, it should have been caught above.) 00808 */ 00809 00810 if (insertid >= 0) 00811 return (int) insertid; 00812 00813 return -1; 00814 }
static int unload_module | ( | void | ) | [static] |
Definition at line 1181 of file res_config_pgsql.c.
References ast_cli_unregister_multiple(), ast_config_engine_deregister(), AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), ast_verb, cli_realtime, destroy_table(), columns::list, pgsql_engine, pgsql_lock, and table.
01182 { 01183 struct tables *table; 01184 /* Acquire control before doing anything to the module itself. */ 01185 ast_mutex_lock(&pgsql_lock); 01186 01187 if (pgsqlConn) { 01188 PQfinish(pgsqlConn); 01189 pgsqlConn = NULL; 01190 } 01191 ast_cli_unregister_multiple(cli_realtime, sizeof(cli_realtime) / sizeof(struct ast_cli_entry)); 01192 ast_config_engine_deregister(&pgsql_engine); 01193 ast_verb(1, "PostgreSQL RealTime unloaded.\n"); 01194 01195 /* Destroy cached table info */ 01196 AST_LIST_LOCK(&psql_tables); 01197 while ((table = AST_LIST_REMOVE_HEAD(&psql_tables, list))) { 01198 destroy_table(table); 01199 } 01200 AST_LIST_UNLOCK(&psql_tables); 01201 01202 /* Unlock so something else can destroy the lock. */ 01203 ast_mutex_unlock(&pgsql_lock); 01204 01205 return 0; 01206 }
static int unload_pgsql | ( | const char * | database, | |
const char * | tablename | |||
) | [static] |
Definition at line 1135 of file res_config_pgsql.c.
References ast_debug, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, destroy_table(), columns::list, and tables::name.
01136 { 01137 struct tables *cur; 01138 ast_debug(2, "About to lock table cache list\n"); 01139 AST_LIST_LOCK(&psql_tables); 01140 ast_debug(2, "About to traverse table cache list\n"); 01141 AST_LIST_TRAVERSE_SAFE_BEGIN(&psql_tables, cur, list) { 01142 if (strcmp(cur->name, tablename) == 0) { 01143 ast_debug(2, "About to remove matching cache entry\n"); 01144 AST_LIST_REMOVE_CURRENT(list); 01145 ast_debug(2, "About to destroy matching cache entry\n"); 01146 destroy_table(cur); 01147 ast_debug(1, "Cache entry '%s@%s' destroyed\n", tablename, database); 01148 break; 01149 } 01150 } 01151 AST_LIST_TRAVERSE_SAFE_END 01152 AST_LIST_UNLOCK(&psql_tables); 01153 ast_debug(2, "About to return\n"); 01154 return cur ? 0 : -1; 01155 }
static int update_pgsql | ( | const char * | database, | |
const char * | tablename, | |||
const char * | keyfield, | |||
const char * | lookup, | |||
va_list | ap | |||
) | [static] |
Definition at line 550 of file res_config_pgsql.c.
References ast_debug, ast_free, AST_LIST_TRAVERSE, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_str_append(), ast_str_create(), ast_str_set(), find_table(), columns::list, LOG_ERROR, LOG_WARNING, columns::name, pgsql_lock, pgsql_reconnect(), ast_str::str, and table.
00552 { 00553 PGresult *result = NULL; 00554 int numrows = 0, pgerror; 00555 char escapebuf[513]; 00556 const char *newparam, *newval; 00557 struct ast_str *sql = ast_str_create(100); 00558 struct tables *table; 00559 struct columns *column = NULL; 00560 00561 if (!tablename) { 00562 ast_log(LOG_WARNING, "PostgreSQL RealTime: No table specified.\n"); 00563 ast_free(sql); 00564 return -1; 00565 } 00566 00567 if (!(table = find_table(tablename))) { 00568 ast_log(LOG_ERROR, "Table '%s' does not exist!!\n", tablename); 00569 ast_free(sql); 00570 return -1; 00571 } 00572 00573 /* Get the first parameter and first value in our list of passed paramater/value pairs */ 00574 newparam = va_arg(ap, const char *); 00575 newval = va_arg(ap, const char *); 00576 if (!newparam || !newval) { 00577 ast_log(LOG_WARNING, 00578 "PostgreSQL RealTime: Realtime retrieval requires at least 1 parameter and 1 value to search on.\n"); 00579 if (pgsqlConn) { 00580 PQfinish(pgsqlConn); 00581 pgsqlConn = NULL; 00582 }; 00583 ast_mutex_unlock(&table->lock); 00584 ast_free(sql); 00585 return -1; 00586 } 00587 00588 /* Check that the column exists in the table */ 00589 AST_LIST_TRAVERSE(&table->columns, column, list) { 00590 if (strcmp(column->name, newparam) == 0) { 00591 break; 00592 } 00593 } 00594 00595 if (!column) { 00596 ast_log(LOG_ERROR, "PostgreSQL RealTime: Updating on column '%s', but that column does not exist within the table '%s'!\n", newparam, tablename); 00597 ast_mutex_unlock(&table->lock); 00598 ast_free(sql); 00599 return -1; 00600 } 00601 00602 /* Create the first part of the query using the first parameter/value pairs we just extracted 00603 If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */ 00604 00605 PQescapeStringConn(pgsqlConn, escapebuf, newval, (sizeof(escapebuf) - 1) / 2, &pgerror); 00606 if (pgerror) { 00607 ast_log(LOG_ERROR, "Postgres detected invalid input: '%s'\n", newval); 00608 va_end(ap); 00609 ast_mutex_unlock(&table->lock); 00610 ast_free(sql); 00611 return -1; 00612 } 00613 ast_str_set(&sql, 0, "UPDATE %s SET %s = '%s'", tablename, newparam, escapebuf); 00614 00615 while ((newparam = va_arg(ap, const char *))) { 00616 newval = va_arg(ap, const char *); 00617 00618 /* If the column is not within the table, then skip it */ 00619 AST_LIST_TRAVERSE(&table->columns, column, list) { 00620 if (strcmp(column->name, newparam) == 0) { 00621 break; 00622 } 00623 } 00624 00625 if (!column) { 00626 ast_log(LOG_WARNING, "Attempted to update column '%s' in table '%s', but column does not exist!\n", newparam, tablename); 00627 continue; 00628 } 00629 00630 PQescapeStringConn(pgsqlConn, escapebuf, newval, (sizeof(escapebuf) - 1) / 2, &pgerror); 00631 if (pgerror) { 00632 ast_log(LOG_ERROR, "Postgres detected invalid input: '%s'\n", newval); 00633 va_end(ap); 00634 ast_mutex_unlock(&table->lock); 00635 ast_free(sql); 00636 return -1; 00637 } 00638 00639 ast_str_append(&sql, 0, ", %s = '%s'", newparam, escapebuf); 00640 } 00641 va_end(ap); 00642 ast_mutex_unlock(&table->lock); 00643 00644 PQescapeStringConn(pgsqlConn, escapebuf, lookup, (sizeof(escapebuf) - 1) / 2, &pgerror); 00645 if (pgerror) { 00646 ast_log(LOG_ERROR, "Postgres detected invalid input: '%s'\n", lookup); 00647 va_end(ap); 00648 ast_free(sql); 00649 return -1; 00650 } 00651 00652 ast_str_append(&sql, 0, " WHERE %s = '%s'", keyfield, escapebuf); 00653 00654 ast_debug(1, "PostgreSQL RealTime: Update SQL: %s\n", sql->str); 00655 00656 /* We now have our complete statement; Lets connect to the server and execute it. */ 00657 ast_mutex_lock(&pgsql_lock); 00658 if (!pgsql_reconnect(database)) { 00659 ast_mutex_unlock(&pgsql_lock); 00660 ast_free(sql); 00661 return -1; 00662 } 00663 00664 if (!(result = PQexec(pgsqlConn, sql->str))) { 00665 ast_log(LOG_WARNING, 00666 "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n"); 00667 ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql->str); 00668 ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s\n", PQerrorMessage(pgsqlConn)); 00669 ast_mutex_unlock(&pgsql_lock); 00670 ast_free(sql); 00671 return -1; 00672 } else { 00673 ExecStatusType result_status = PQresultStatus(result); 00674 if (result_status != PGRES_COMMAND_OK 00675 && result_status != PGRES_TUPLES_OK 00676 && result_status != PGRES_NONFATAL_ERROR) { 00677 ast_log(LOG_WARNING, 00678 "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n"); 00679 ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql->str); 00680 ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s (%s)\n", 00681 PQresultErrorMessage(result), PQresStatus(result_status)); 00682 ast_mutex_unlock(&pgsql_lock); 00683 ast_free(sql); 00684 return -1; 00685 } 00686 } 00687 00688 numrows = atoi(PQcmdTuples(result)); 00689 ast_mutex_unlock(&pgsql_lock); 00690 ast_free(sql); 00691 00692 ast_debug(1, "PostgreSQL RealTime: Updated %d rows on table: %s\n", numrows, tablename); 00693 00694 /* From http://dev.pgsql.com/doc/pgsql/en/pgsql-affected-rows.html 00695 * An integer greater than zero indicates the number of rows affected 00696 * Zero indicates that no records were updated 00697 * -1 indicates that the query returned an error (although, if the query failed, it should have been caught above.) 00698 */ 00699 00700 if (numrows >= 0) 00701 return (int) numrows; 00702 00703 return -1; 00704 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS , .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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload } [static] |
Definition at line 1482 of file res_config_pgsql.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 1482 of file res_config_pgsql.c.
struct ast_cli_entry cli_realtime[] [static] |
Initial value:
{ { .handler = handle_cli_realtime_pgsql_status , .summary = "Shows connection information for the PostgreSQL RealTime driver" ,__VA_ARGS__ }, { .handler = handle_cli_realtime_pgsql_cache , .summary = "Shows cached tables within the PostgreSQL realtime driver" ,__VA_ARGS__ }, }
Definition at line 87 of file res_config_pgsql.c.
Referenced by load_module(), and unload_module().
time_t connect_time = 0 [static] |
Definition at line 78 of file res_config_pgsql.c.
char dbhost[MAX_DB_OPTION_SIZE] = "" [static] |
Definition at line 72 of file res_config_pgsql.c.
Referenced by handle_cli_realtime_pgsql_status(), parse_config(), and pgsql_reconnect().
char dbname[MAX_DB_OPTION_SIZE] = "" [static] |
Definition at line 75 of file res_config_pgsql.c.
Referenced by handle_cli_realtime_pgsql_status(), parse_config(), and pgsql_reconnect().
char dbpass[MAX_DB_OPTION_SIZE] = "" [static] |
Definition at line 74 of file res_config_pgsql.c.
Referenced by parse_config(), and pgsql_reconnect().
int dbport = 5432 [static] |
Definition at line 77 of file res_config_pgsql.c.
Referenced by handle_cli_realtime_pgsql_status(), parse_config(), and pgsql_reconnect().
char dbsock[MAX_DB_OPTION_SIZE] = "" [static] |
Definition at line 76 of file res_config_pgsql.c.
Referenced by handle_cli_realtime_pgsql_status(), parse_config(), and pgsql_reconnect().
char dbuser[MAX_DB_OPTION_SIZE] = "" [static] |
Definition at line 73 of file res_config_pgsql.c.
Referenced by handle_cli_realtime_pgsql_status(), parse_config(), and pgsql_reconnect().
struct ast_config_engine pgsql_engine [static] |
Definition at line 1157 of file res_config_pgsql.c.
Referenced by load_module(), and unload_module().
ast_mutex_t pgsql_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
Definition at line 44 of file res_config_pgsql.c.
PGconn* pgsqlConn = NULL |
Definition at line 48 of file res_config_pgsql.c.
enum { ... } requirements |
Referenced by parse_config(), and require_pgsql().
int version [static] |
Definition at line 49 of file res_config_pgsql.c.