[asterisk-commits] tilghman: branch tilghman/adaptive_realtime r116556 - /team/tilghman/adaptive...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Wed May 14 23:42:59 CDT 2008
Author: tilghman
Date: Wed May 14 23:42:59 2008
New Revision: 116556
URL: http://svn.digium.com/view/asterisk?view=rev&rev=116556
Log:
Implement first half of what's required for the postgres backend
Modified:
team/tilghman/adaptive_realtime/res/res_config_odbc.c
team/tilghman/adaptive_realtime/res/res_config_pgsql.c
Modified: team/tilghman/adaptive_realtime/res/res_config_odbc.c
URL: http://svn.digium.com/view/asterisk/team/tilghman/adaptive_realtime/res/res_config_odbc.c?view=diff&rev=116556&r1=116555&r2=116556
==============================================================================
--- team/tilghman/adaptive_realtime/res/res_config_odbc.c (original)
+++ team/tilghman/adaptive_realtime/res/res_config_odbc.c Wed May 14 23:42:59 2008
@@ -892,8 +892,8 @@
}
while ((elm = va_arg(ap, char *))) {
- type = va_arg(ap, int);
- size = va_arg(ap, require_type);
+ type = va_arg(ap, require_type);
+ size = va_arg(ap, int);
/* Check if the field matches the criteria */
AST_RWLIST_TRAVERSE(&tableptr->columns, col, list) {
if (strcmp(col->name, elm) == 0) {
Modified: team/tilghman/adaptive_realtime/res/res_config_pgsql.c
URL: http://svn.digium.com/view/asterisk/team/tilghman/adaptive_realtime/res/res_config_pgsql.c?view=diff&rev=116556&r1=116555&r2=116556
==============================================================================
--- team/tilghman/adaptive_realtime/res/res_config_pgsql.c (original)
+++ team/tilghman/adaptive_realtime/res/res_config_pgsql.c Wed May 14 23:42:59 2008
@@ -49,6 +49,24 @@
#define MAX_DB_OPTION_SIZE 64
+struct columns {
+ char *name;
+ char *type;
+ int len;
+ unsigned int notnull:1;
+ unsigned int hasdefault:1;
+ AST_LIST_ENTRY(columns) list;
+};
+
+struct tables {
+ ast_mutex_t lock;
+ AST_LIST_HEAD_NOLOCK(psql_columns, columns) columns;
+ AST_LIST_ENTRY(tables) list;
+ char name[0];
+};
+
+static AST_LIST_HEAD_STATIC(psql_tables, tables);
+
static char dbhost[MAX_DB_OPTION_SIZE] = "";
static char dbuser[MAX_DB_OPTION_SIZE] = "";
static char dbpass[MAX_DB_OPTION_SIZE] = "";
@@ -64,6 +82,98 @@
static struct ast_cli_entry cli_realtime[] = {
AST_CLI_DEFINE(handle_cli_realtime_pgsql_status, "Shows connection information for the PostgreSQL RealTime driver"),
};
+
+static void destroy_table(struct tables *table)
+{
+ struct columns *column;
+ ast_mutex_lock(&table->lock);
+ while ((column = AST_LIST_REMOVE_HEAD(&table->columns, list))) {
+ ast_free(column);
+ }
+ ast_mutex_unlock(&table->lock);
+ ast_mutex_destroy(&table->lock);
+ ast_free(table);
+}
+
+static struct tables *find_table(const char *tablename)
+{
+ struct columns *column;
+ struct tables *table;
+ struct ast_str *sql = ast_str_create(330);
+ char *pgerror;
+ PGresult *result;
+ char *fname, *ftype, *flen, *fnotnull, *fdef;
+ int i, rows;
+
+ AST_LIST_LOCK(&psql_tables);
+ AST_LIST_TRAVERSE(&psql_tables, table, list) {
+ if (!strcasecmp(table->name, tablename)) {
+ ast_mutex_lock(&table->lock);
+ AST_LIST_UNLOCK(&psql_tables);
+ return table;
+ }
+ }
+
+ /* Not found, scan the table */
+ ast_str_set(&sql, 0, "SELECT a.attname, t.typname, a.attlen, a.attnotnull, d.adsrc 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", tablename);
+ result = PQexec(pgsqlConn, sql->str);
+ if (PQresultStatus(result) != PGRES_TUPLES_OK) {
+ pgerror = PQresultErrorMessage(result);
+ ast_log(LOG_ERROR, "Failed to query database columns: %s\n", pgerror);
+ PQclear(result);
+ AST_LIST_UNLOCK(&psql_tables);
+ return NULL;
+ }
+
+ if (!(table = ast_calloc(1, sizeof(*table) + strlen(tablename) + 1))) {
+ ast_log(LOG_ERROR, "Unable to allocate memory for new table structure\n");
+ AST_LIST_UNLOCK(&psql_tables);
+ return NULL;
+ }
+ strcpy(table->name, tablename); /* SAFE */
+ ast_mutex_init(&table->lock);
+ AST_LIST_HEAD_INIT_NOLOCK(&table->columns);
+
+ rows = PQntuples(result);
+ for (i = 0; i < rows; i++) {
+ fname = PQgetvalue(result, i, 0);
+ ftype = PQgetvalue(result, i, 1);
+ flen = PQgetvalue(result, i, 2);
+ fnotnull = PQgetvalue(result, i, 3);
+ fdef = PQgetvalue(result, i, 4);
+ ast_verb(4, "Found column '%s' of type '%s'\n", fname, ftype);
+
+ if (!(column = ast_calloc(1, sizeof(*column) + strlen(fname) + strlen(ftype) + 2))) {
+ ast_log(LOG_ERROR, "Unable to allocate column element for %s, %s\n", tablename, fname);
+ destroy_table(table);
+ AST_LIST_UNLOCK(&psql_tables);
+ return NULL;
+ }
+
+ sscanf(flen, "%d", &column->len);
+ column->name = (char *)column + sizeof(*column);
+ column->type = (char *)column + sizeof(*column) + strlen(fname) + 1;
+ strcpy(column->name, fname);
+ strcpy(column->type, ftype);
+ if (*fnotnull == 't') {
+ column->notnull = 1;
+ } else {
+ column->notnull = 0;
+ }
+ if (!ast_strlen_zero(fdef)) {
+ column->hasdefault = 1;
+ } else {
+ column->hasdefault = 0;
+ }
+ AST_LIST_INSERT_TAIL(&table->columns, column, list);
+ }
+ PQclear(result);
+
+ AST_LIST_INSERT_TAIL(&psql_tables, table, list);
+ ast_mutex_lock(&table->lock);
+ AST_LIST_UNLOCK(&psql_tables);
+ return table;
+}
static struct ast_variable *realtime_pgsql(const char *database, const char *table, va_list ap)
{
@@ -752,6 +862,51 @@
return cfg;
}
+static int require_pgsql(const char *database, const char *tablename, va_list ap)
+{
+ struct columns *column;
+ struct tables *table = find_table(tablename);
+ char *elm;
+ int type, size, res = 0;
+
+ if (!table) {
+ ast_log(LOG_WARNING, "Table %s not found in database. This table should exist if you're using realtime.\n", tablename);
+ }
+
+ while ((elm = va_arg(ap, char *))) {
+ type = va_arg(ap, require_type);
+ size = va_arg(ap, int);
+ AST_LIST_TRAVERSE(&table->columns, column, list) {
+ if (strcmp(column->name, elm) == 0) {
+ /* Char can hold anything, as long as it is large enough */
+ if ((strncmp(column->type, "char", 4) == 0 || strncmp(column->type, "varchar", 7) == 0) && (size > column->len)) {
+ ast_log(LOG_WARNING, "Column %s should be at least %d long, but is only %d long.\n", column->name, size, column->len);
+ res = -1;
+ } else if (strncmp(column->type, "int", 3) == 0) {
+ int typesize = atoi(column->type + 3);
+ /* Integers can hold only other integers */
+ if (type == RQ_INTEGER && ((typesize == 2 && size > 4) || (typesize == 4 && size > 10))) {
+ ast_log(LOG_WARNING, "Column '%s' may not be large enough for the required data length: %d\n", column->name, size);
+ res = -1;
+ } else if (type != RQ_INTEGER) {
+ ast_log(LOG_WARNING, "Column '%s' is of the incorrect type: (need %s(%d) but saw %s)\n", column->name, type == RQ_CHAR ? "char" : "something else ", size, column->type);
+ res = -1;
+ }
+ } else if (strncmp(column->type, "float", 5) == 0 && type != RQ_INTEGER && type != RQ_FLOAT) {
+ ast_log(LOG_WARNING, "Column %s cannot be a %s\n", column->name, column->type);
+ res = -1;
+ } else { /* There are other types that no module implements yet */
+ ast_log(LOG_WARNING, "Possibly unsupported column type '%s' on column '%s'\n", column->type, column->name);
+ res = -1;
+ }
+ break;
+ }
+ }
+ }
+ ast_mutex_unlock(&table->lock);
+ return res;
+}
+
static struct ast_config_engine pgsql_engine = {
.name = "pgsql",
.load_func = config_pgsql,
@@ -759,7 +914,8 @@
.realtime_multi_func = realtime_multi_pgsql,
.store_func = store_pgsql,
.destroy_func = destroy_pgsql,
- .update_func = update_pgsql
+ .update_func = update_pgsql,
+ .require_func = require_pgsql,
};
static int load_module(void)
@@ -776,6 +932,7 @@
static int unload_module(void)
{
+ struct tables *table;
/* Acquire control before doing anything to the module itself. */
ast_mutex_lock(&pgsql_lock);
@@ -786,6 +943,13 @@
ast_cli_unregister_multiple(cli_realtime, sizeof(cli_realtime) / sizeof(struct ast_cli_entry));
ast_config_engine_deregister(&pgsql_engine);
ast_verb(1, "PostgreSQL RealTime unloaded.\n");
+
+ /* Destroy cached table info */
+ AST_LIST_LOCK(&psql_tables);
+ while ((table = AST_LIST_REMOVE_HEAD(&psql_tables, list))) {
+ destroy_table(table);
+ }
+ AST_LIST_UNLOCK(&psql_tables);
/* Unlock so something else can destroy the lock. */
ast_mutex_unlock(&pgsql_lock);
More information about the asterisk-commits
mailing list