diff options
Diffstat (limited to 'res/res_config_pgsql.c')
-rw-r--r-- | res/res_config_pgsql.c | 365 |
1 files changed, 240 insertions, 125 deletions
diff --git a/res/res_config_pgsql.c b/res/res_config_pgsql.c index f7c1f3a6a..fe672bf62 100644 --- a/res/res_config_pgsql.c +++ b/res/res_config_pgsql.c @@ -42,6 +42,10 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/cli.h" AST_MUTEX_DEFINE_STATIC(pgsql_lock); +AST_THREADSTORAGE(sql_buf); +AST_THREADSTORAGE(findtable_buf); +AST_THREADSTORAGE(where_buf); +AST_THREADSTORAGE(escapebuf_buf); #define RES_CONFIG_PGSQL_CONF "res_pgsql.conf" @@ -59,7 +63,7 @@ struct columns { }; struct tables { - ast_mutex_t lock; + ast_rwlock_t lock; AST_LIST_HEAD_NOLOCK(psql_columns, columns) columns; AST_LIST_ENTRY(tables) list; char name[0]; @@ -87,15 +91,24 @@ static struct ast_cli_entry cli_realtime[] = { AST_CLI_DEFINE(handle_cli_realtime_pgsql_cache, "Shows cached tables within the PostgreSQL realtime driver"), }; +#define ESCAPE_STRING(buffer, stringname) \ + do { \ + int len; \ + if ((len = strlen(stringname)) > (buffer->len - 1) / 2) { \ + ast_str_make_space(&buffer, len * 2 + 1); \ + } \ + PQescapeStringConn(pgsqlConn, buffer->str, stringname, len, &pgresult); \ + } while (0) + static void destroy_table(struct tables *table) { struct columns *column; - ast_mutex_lock(&table->lock); + ast_rwlock_wrlock(&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_rwlock_unlock(&table->lock); + ast_rwlock_destroy(&table->lock); ast_free(table); } @@ -103,7 +116,7 @@ static struct tables *find_table(const char *tablename) { struct columns *column; struct tables *table; - struct ast_str *sql = ast_str_create(330); + struct ast_str *sql = ast_str_thread_get(&findtable_buf, 330); char *pgerror; PGresult *result; char *fname, *ftype, *flen, *fnotnull, *fdef; @@ -113,7 +126,7 @@ static struct tables *find_table(const char *tablename) AST_LIST_TRAVERSE(&psql_tables, table, list) { if (!strcasecmp(table->name, tablename)) { ast_debug(1, "Found table in cache; now locking\n"); - ast_mutex_lock(&table->lock); + ast_rwlock_rdlock(&table->lock); ast_debug(1, "Lock cached table; now returning\n"); AST_LIST_UNLOCK(&psql_tables); return table; @@ -140,9 +153,9 @@ static struct tables *find_table(const char *tablename) return NULL; } strcpy(table->name, tablename); /* SAFE */ - ast_mutex_init(&table->lock); + ast_rwlock_init(&table->lock); AST_LIST_HEAD_INIT_NOLOCK(&table->columns); - + rows = PQntuples(result); for (i = 0; i < rows; i++) { fname = PQgetvalue(result, i, 0); @@ -186,23 +199,39 @@ static struct tables *find_table(const char *tablename) PQclear(result); AST_LIST_INSERT_TAIL(&psql_tables, table, list); - ast_mutex_lock(&table->lock); + ast_rwlock_rdlock(&table->lock); AST_LIST_UNLOCK(&psql_tables); return table; } -static struct ast_variable *realtime_pgsql(const char *database, const char *table, va_list ap) +#define release_table(table) ast_rwlock_unlock(&(table)->lock); + +static struct columns *find_column(struct tables *t, const char *colname) +{ + struct columns *column; + + /* Check that the column exists in the table */ + AST_LIST_TRAVERSE(&t->columns, column, list) { + if (strcmp(column->name, colname) == 0) { + return column; + } + } + return NULL; +} + +static struct ast_variable *realtime_pgsql(const char *database, const char *tablename, va_list ap) { PGresult *result = NULL; - int num_rows = 0, pgerror; - char sql[256], escapebuf[513]; + int num_rows = 0, pgresult; + struct ast_str *sql = ast_str_thread_get(&sql_buf, 100); + struct ast_str *escapebuf = ast_str_thread_get(&escapebuf_buf, 100); char *stringp; char *chunk; char *op; const char *newparam, *newval; struct ast_variable *var = NULL, *prev = NULL; - if (!table) { + if (!tablename) { ast_log(LOG_WARNING, "PostgreSQL RealTime: No table specified.\n"); return NULL; } @@ -216,7 +245,7 @@ static struct ast_variable *realtime_pgsql(const char *database, const char *tab if (pgsqlConn) { PQfinish(pgsqlConn); pgsqlConn = NULL; - }; + } return NULL; } @@ -224,15 +253,14 @@ static struct ast_variable *realtime_pgsql(const char *database, const char *tab If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */ op = strchr(newparam, ' ') ? "" : " ="; - PQescapeStringConn(pgsqlConn, escapebuf, newval, (sizeof(escapebuf) - 1) / 2, &pgerror); - if (pgerror) { + ESCAPE_STRING(escapebuf, newval); + if (pgresult) { ast_log(LOG_ERROR, "Postgres detected invalid input: '%s'\n", newval); va_end(ap); return NULL; } - snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s '%s'", table, newparam, op, - escapebuf); + ast_str_set(&sql, 0, "SELECT * FROM %s WHERE %s%s '%s'", tablename, newparam, op, escapebuf->str); while ((newparam = va_arg(ap, const char *))) { newval = va_arg(ap, const char *); if (!strchr(newparam, ' ')) @@ -240,15 +268,14 @@ static struct ast_variable *realtime_pgsql(const char *database, const char *tab else op = ""; - PQescapeStringConn(pgsqlConn, escapebuf, newval, (sizeof(escapebuf) - 1) / 2, &pgerror); - if (pgerror) { + ESCAPE_STRING(escapebuf, newval); + if (pgresult) { ast_log(LOG_ERROR, "Postgres detected invalid input: '%s'\n", newval); va_end(ap); return NULL; } - snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s '%s'", newparam, - op, escapebuf); + ast_str_append(&sql, 0, " AND %s%s '%s'", newparam, op, escapebuf->str); } va_end(ap); @@ -259,10 +286,10 @@ static struct ast_variable *realtime_pgsql(const char *database, const char *tab return NULL; } - if (!(result = PQexec(pgsqlConn, sql))) { + if (!(result = PQexec(pgsqlConn, sql->str))) { ast_log(LOG_WARNING, - "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n"); - ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql); + "PostgreSQL RealTime: Failed to query '%s@%s'. Check debug for more info.\n", tablename, database); + ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql->str); ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s\n", PQerrorMessage(pgsqlConn)); ast_mutex_unlock(&pgsql_lock); return NULL; @@ -272,8 +299,8 @@ static struct ast_variable *realtime_pgsql(const char *database, const char *tab && result_status != PGRES_TUPLES_OK && result_status != PGRES_NONFATAL_ERROR) { ast_log(LOG_WARNING, - "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n"); - ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql); + "PostgreSQL RealTime: Failed to query '%s@%s'. Check debug for more info.\n", tablename, database); + ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql->str); ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s (%s)\n", PQresultErrorMessage(result), PQresStatus(result_status)); ast_mutex_unlock(&pgsql_lock); @@ -281,7 +308,7 @@ static struct ast_variable *realtime_pgsql(const char *database, const char *tab } } - ast_debug(1, "PostgreSQL RealTime: Result=%p Query: %s\n", result, sql); + ast_debug(1, "PostgreSQL RealTime: Result=%p Query: %s\n", result, sql->str); if ((num_rows = PQntuples(result)) > 0) { int i = 0; @@ -318,7 +345,7 @@ static struct ast_variable *realtime_pgsql(const char *database, const char *tab } ast_free(fieldnames); } else { - ast_debug(1, "Postgresql RealTime: Could not find any rows in table %s.\n", table); + ast_debug(1, "Postgresql RealTime: Could not find any rows in table %s@%s.\n", tablename, database); } ast_mutex_unlock(&pgsql_lock); @@ -330,8 +357,9 @@ static struct ast_variable *realtime_pgsql(const char *database, const char *tab static struct ast_config *realtime_multi_pgsql(const char *database, const char *table, va_list ap) { PGresult *result = NULL; - int num_rows = 0, pgerror; - char sql[256], escapebuf[513]; + int num_rows = 0, pgresult; + struct ast_str *sql = ast_str_thread_get(&sql_buf, 100); + struct ast_str *escapebuf = ast_str_thread_get(&escapebuf_buf, 100); const char *initfield = NULL; char *stringp; char *chunk; @@ -358,7 +386,7 @@ static struct ast_config *realtime_multi_pgsql(const char *database, const char if (pgsqlConn) { PQfinish(pgsqlConn); pgsqlConn = NULL; - }; + } return NULL; } @@ -375,15 +403,14 @@ static struct ast_config *realtime_multi_pgsql(const char *database, const char else op = ""; - PQescapeStringConn(pgsqlConn, escapebuf, newval, (sizeof(escapebuf) - 1) / 2, &pgerror); - if (pgerror) { + ESCAPE_STRING(escapebuf, newval); + if (pgresult) { ast_log(LOG_ERROR, "Postgres detected invalid input: '%s'\n", newval); va_end(ap); return NULL; } - snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s '%s'", table, newparam, op, - escapebuf); + ast_str_set(&sql, 0, "SELECT * FROM %s WHERE %s%s '%s'", table, newparam, op, escapebuf->str); while ((newparam = va_arg(ap, const char *))) { newval = va_arg(ap, const char *); if (!strchr(newparam, ' ')) @@ -391,19 +418,18 @@ static struct ast_config *realtime_multi_pgsql(const char *database, const char else op = ""; - PQescapeStringConn(pgsqlConn, escapebuf, newval, (sizeof(escapebuf) - 1) / 2, &pgerror); - if (pgerror) { + ESCAPE_STRING(escapebuf, newval); + if (pgresult) { ast_log(LOG_ERROR, "Postgres detected invalid input: '%s'\n", newval); va_end(ap); return NULL; } - snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s '%s'", newparam, - op, escapebuf); + ast_str_append(&sql, 0, " AND %s%s '%s'", newparam, op, escapebuf->str); } if (initfield) { - snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " ORDER BY %s", initfield); + ast_str_append(&sql, 0, " ORDER BY %s", initfield); } va_end(ap); @@ -415,10 +441,10 @@ static struct ast_config *realtime_multi_pgsql(const char *database, const char return NULL; } - if (!(result = PQexec(pgsqlConn, sql))) { + if (!(result = PQexec(pgsqlConn, sql->str))) { ast_log(LOG_WARNING, - "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n"); - ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql); + "PostgreSQL RealTime: Failed to query %s@%s. Check debug for more info.\n", table, database); + ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql->str); ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s\n", PQerrorMessage(pgsqlConn)); ast_mutex_unlock(&pgsql_lock); return NULL; @@ -428,8 +454,8 @@ static struct ast_config *realtime_multi_pgsql(const char *database, const char && result_status != PGRES_TUPLES_OK && result_status != PGRES_NONFATAL_ERROR) { ast_log(LOG_WARNING, - "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n"); - ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql); + "PostgreSQL RealTime: Failed to query %s@%s. Check debug for more info.\n", table, database); + ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql->str); ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s (%s)\n", PQresultErrorMessage(result), PQresStatus(result_status)); ast_mutex_unlock(&pgsql_lock); @@ -437,7 +463,7 @@ static struct ast_config *realtime_multi_pgsql(const char *database, const char } } - ast_debug(1, "PostgreSQL RealTime: Result=%p Query: %s\n", result, sql); + ast_debug(1, "PostgreSQL RealTime: Result=%p Query: %s\n", result, sql->str); if ((num_rows = PQntuples(result)) > 0) { int numFields = PQnfields(result); @@ -490,22 +516,20 @@ static int update_pgsql(const char *database, const char *tablename, const char const char *lookup, va_list ap) { PGresult *result = NULL; - int numrows = 0, pgerror; - char escapebuf[513]; + int numrows = 0, pgresult; const char *newparam, *newval; - struct ast_str *sql = ast_str_create(100); + struct ast_str *sql = ast_str_thread_get(&sql_buf, 100); + struct ast_str *escapebuf = ast_str_thread_get(&escapebuf_buf, 100); struct tables *table; struct columns *column = NULL; if (!tablename) { ast_log(LOG_WARNING, "PostgreSQL RealTime: No table specified.\n"); - ast_free(sql); return -1; } if (!(table = find_table(tablename))) { ast_log(LOG_ERROR, "Table '%s' does not exist!!\n", tablename); - ast_free(sql); return -1; } @@ -518,9 +542,8 @@ static int update_pgsql(const char *database, const char *tablename, const char if (pgsqlConn) { PQfinish(pgsqlConn); pgsqlConn = NULL; - }; - ast_mutex_unlock(&table->lock); - ast_free(sql); + } + release_table(table); return -1; } @@ -533,62 +556,51 @@ static int update_pgsql(const char *database, const char *tablename, const char if (!column) { ast_log(LOG_ERROR, "PostgreSQL RealTime: Updating on column '%s', but that column does not exist within the table '%s'!\n", newparam, tablename); - ast_mutex_unlock(&table->lock); - ast_free(sql); + release_table(table); return -1; } /* Create the first part of the query using the first parameter/value pairs we just extracted If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */ - PQescapeStringConn(pgsqlConn, escapebuf, newval, (sizeof(escapebuf) - 1) / 2, &pgerror); - if (pgerror) { + ESCAPE_STRING(escapebuf, newval); + if (pgresult) { ast_log(LOG_ERROR, "Postgres detected invalid input: '%s'\n", newval); va_end(ap); - ast_mutex_unlock(&table->lock); - ast_free(sql); + release_table(table); return -1; } - ast_str_set(&sql, 0, "UPDATE %s SET %s = '%s'", tablename, newparam, escapebuf); + ast_str_set(&sql, 0, "UPDATE %s SET %s = '%s'", tablename, newparam, escapebuf->str); while ((newparam = va_arg(ap, const char *))) { newval = va_arg(ap, const char *); - /* If the column is not within the table, then skip it */ - AST_LIST_TRAVERSE(&table->columns, column, list) { - if (strcmp(column->name, newparam) == 0) { - break; - } - } - - if (!column) { + if (!find_column(table, newparam)) { ast_log(LOG_WARNING, "Attempted to update column '%s' in table '%s', but column does not exist!\n", newparam, tablename); continue; } - PQescapeStringConn(pgsqlConn, escapebuf, newval, (sizeof(escapebuf) - 1) / 2, &pgerror); - if (pgerror) { + ESCAPE_STRING(escapebuf, newval); + if (pgresult) { ast_log(LOG_ERROR, "Postgres detected invalid input: '%s'\n", newval); va_end(ap); - ast_mutex_unlock(&table->lock); - ast_free(sql); + release_table(table); return -1; } - ast_str_append(&sql, 0, ", %s = '%s'", newparam, escapebuf); + ast_str_append(&sql, 0, ", %s = '%s'", newparam, escapebuf->str); } va_end(ap); - ast_mutex_unlock(&table->lock); + release_table(table); - PQescapeStringConn(pgsqlConn, escapebuf, lookup, (sizeof(escapebuf) - 1) / 2, &pgerror); - if (pgerror) { + ESCAPE_STRING(escapebuf, lookup); + if (pgresult) { ast_log(LOG_ERROR, "Postgres detected invalid input: '%s'\n", lookup); va_end(ap); - ast_free(sql); return -1; } - ast_str_append(&sql, 0, " WHERE %s = '%s'", keyfield, escapebuf); + ast_str_append(&sql, 0, " WHERE %s = '%s'", keyfield, escapebuf->str); ast_debug(1, "PostgreSQL RealTime: Update SQL: %s\n", sql->str); @@ -596,7 +608,6 @@ static int update_pgsql(const char *database, const char *tablename, const char ast_mutex_lock(&pgsql_lock); if (!pgsql_reconnect(database)) { ast_mutex_unlock(&pgsql_lock); - ast_free(sql); return -1; } @@ -642,22 +653,145 @@ static int update_pgsql(const char *database, const char *tablename, const char return -1; } -#define ESCAPE_STRING(buffer, stringname) \ - do { \ - int len; \ - if ((len = strlen(stringname)) > (buffer->len - 1) / 2) { \ - ast_str_make_space(&buffer, len * 2 + 1); \ - } \ - PQescapeStringConn(pgsqlConn, buffer->str, stringname, len, &pgresult); \ - } while (0) +static int update2_pgsql(const char *database, const char *tablename, va_list ap) +{ + PGresult *result = NULL; + int numrows = 0, pgresult, first = 1; + struct ast_str *escapebuf = ast_str_thread_get(&escapebuf_buf, 16); + const char *newparam, *newval; + struct ast_str *sql = ast_str_thread_get(&sql_buf, 100); + struct ast_str *where = ast_str_thread_get(&where_buf, 100); + struct tables *table; + + if (!tablename) { + ast_log(LOG_WARNING, "PostgreSQL RealTime: No table specified.\n"); + return -1; + } + + if (!escapebuf || !sql || !where) { + /* Memory error, already handled */ + return -1; + } + + if (!(table = find_table(tablename))) { + ast_log(LOG_ERROR, "Table '%s' does not exist!!\n", tablename); + return -1; + } + + ast_str_set(&sql, 0, "UPDATE %s SET ", tablename); + ast_str_set(&where, 0, "WHERE"); + + while ((newparam = va_arg(ap, const char *))) { + if (!find_column(table, newparam)) { + ast_log(LOG_ERROR, "Attempted to update based on criteria column '%s' (%s@%s), but that column does not exist!\n", newparam, tablename, database); + release_table(table); + return -1; + } + + newval = va_arg(ap, const char *); + ESCAPE_STRING(escapebuf, newval); + if (pgresult) { + ast_log(LOG_ERROR, "Postgres detected invalid input: '%s'\n", newval); + release_table(table); + ast_free(sql); + return -1; + } + ast_str_append(&where, 0, "%s %s='%s'", first ? "" : " AND", newparam, escapebuf->str); + first = 0; + } + + if (first) { + ast_log(LOG_WARNING, + "PostgreSQL RealTime: Realtime update requires at least 1 parameter and 1 value to search on.\n"); + if (pgsqlConn) { + PQfinish(pgsqlConn); + pgsqlConn = NULL; + } + release_table(table); + return -1; + } + + /* Now retrieve the columns to update */ + first = 1; + while ((newparam = va_arg(ap, const char *))) { + newval = va_arg(ap, const char *); + + /* If the column is not within the table, then skip it */ + if (!find_column(table, newparam)) { + ast_log(LOG_NOTICE, "Attempted to update column '%s' in table '%s@%s', but column does not exist!\n", newparam, tablename, database); + continue; + } + + ESCAPE_STRING(escapebuf, newval); + if (pgresult) { + ast_log(LOG_ERROR, "Postgres detected invalid input: '%s'\n", newval); + release_table(table); + ast_free(sql); + return -1; + } + + ast_str_append(&sql, 0, "%s %s='%s'", first ? "" : ",", newparam, escapebuf->str); + } + release_table(table); + + ast_str_append(&sql, 0, " %s", where->str); + + ast_debug(1, "PostgreSQL RealTime: Update SQL: %s\n", sql->str); + + /* We now have our complete statement; connect to the server and execute it. */ + ast_mutex_lock(&pgsql_lock); + if (!pgsql_reconnect(database)) { + ast_mutex_unlock(&pgsql_lock); + return -1; + } + + if (!(result = PQexec(pgsqlConn, sql->str))) { + ast_log(LOG_WARNING, + "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n"); + ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql->str); + ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s\n", PQerrorMessage(pgsqlConn)); + ast_mutex_unlock(&pgsql_lock); + return -1; + } else { + ExecStatusType result_status = PQresultStatus(result); + if (result_status != PGRES_COMMAND_OK + && result_status != PGRES_TUPLES_OK + && result_status != PGRES_NONFATAL_ERROR) { + ast_log(LOG_WARNING, + "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n"); + ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql->str); + ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s (%s)\n", + PQresultErrorMessage(result), PQresStatus(result_status)); + ast_mutex_unlock(&pgsql_lock); + return -1; + } + } + + numrows = atoi(PQcmdTuples(result)); + ast_mutex_unlock(&pgsql_lock); + + ast_debug(1, "PostgreSQL RealTime: Updated %d rows on table: %s\n", numrows, tablename); + + /* From http://dev.pgsql.com/doc/pgsql/en/pgsql-affected-rows.html + * An integer greater than zero indicates the number of rows affected + * Zero indicates that no records were updated + * -1 indicates that the query returned an error (although, if the query failed, it should have been caught above.) + */ + + if (numrows >= 0) { + return (int) numrows; + } + + return -1; +} static int store_pgsql(const char *database, const char *table, va_list ap) { PGresult *result = NULL; Oid insertid; - struct ast_str *buf = ast_str_create(256); - struct ast_str *sql1 = ast_str_create(256); - struct ast_str *sql2 = ast_str_create(256); + struct ast_str *buf = ast_str_thread_get(&escapebuf_buf, 256); + struct ast_str *sql1 = ast_str_thread_get(&sql_buf, 256); + struct ast_str *sql2 = ast_str_thread_get(&where_buf, 256); int pgresult; const char *newparam, *newval; @@ -710,9 +844,6 @@ static int store_pgsql(const char *database, const char *table, va_list ap) ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql1->str); ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s\n", PQerrorMessage(pgsqlConn)); ast_mutex_unlock(&pgsql_lock); - ast_free(sql1); - ast_free(sql2); - ast_free(buf); return -1; } else { ExecStatusType result_status = PQresultStatus(result); @@ -725,18 +856,12 @@ static int store_pgsql(const char *database, const char *table, va_list ap) ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s (%s)\n", PQresultErrorMessage(result), PQresStatus(result_status)); ast_mutex_unlock(&pgsql_lock); - ast_free(sql1); - ast_free(sql2); - ast_free(buf); return -1; } } insertid = PQoidValue(result); ast_mutex_unlock(&pgsql_lock); - ast_free(sql1); - ast_free(sql2); - ast_free(buf); ast_debug(1, "PostgreSQL RealTime: row inserted on table: %s, id: %u\n", table, insertid); @@ -757,8 +882,8 @@ static int destroy_pgsql(const char *database, const char *table, const char *ke PGresult *result = NULL; int numrows = 0; int pgresult; - struct ast_str *sql = ast_str_create(256); - struct ast_str *buf1 = ast_str_create(60), *buf2 = ast_str_create(60); + struct ast_str *sql = ast_str_thread_get(&sql_buf, 256); + struct ast_str *buf1 = ast_str_thread_get(&where_buf, 60), *buf2 = ast_str_thread_get(&escapebuf_buf, 60); const char *newparam, *newval; if (!table) { @@ -810,9 +935,6 @@ static int destroy_pgsql(const char *database, const char *table, const char *ke ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql->str); ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s\n", PQerrorMessage(pgsqlConn)); ast_mutex_unlock(&pgsql_lock); - ast_free(buf1); - ast_free(buf2); - ast_free(sql); return -1; } else { ExecStatusType result_status = PQresultStatus(result); @@ -825,18 +947,12 @@ static int destroy_pgsql(const char *database, const char *table, const char *ke ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s (%s)\n", PQresultErrorMessage(result), PQresStatus(result_status)); ast_mutex_unlock(&pgsql_lock); - ast_free(buf1); - ast_free(buf2); - ast_free(sql); return -1; } } numrows = atoi(PQcmdTuples(result)); ast_mutex_unlock(&pgsql_lock); - ast_free(buf1); - ast_free(buf2); - ast_free(sql); ast_debug(1, "PostgreSQL RealTime: Deleted %d rows on table: %s\n", numrows, table); @@ -861,9 +977,7 @@ static struct ast_config *config_pgsql(const char *database, const char *table, long num_rows; struct ast_variable *new_v; struct ast_category *cur_cat = NULL; - char sqlbuf[1024] = ""; - char *sql = sqlbuf; - size_t sqlleft = sizeof(sqlbuf); + struct ast_str *sql = ast_str_thread_get(&sql_buf, 100); char last[80] = ""; int last_cat_metric = 0; @@ -874,11 +988,11 @@ static struct ast_config *config_pgsql(const char *database, const char *table, return NULL; } - ast_build_string(&sql, &sqlleft, "SELECT category, var_name, var_val, cat_metric FROM %s ", table); - ast_build_string(&sql, &sqlleft, "WHERE filename='%s' and commented=0", file); - ast_build_string(&sql, &sqlleft, "ORDER BY cat_metric DESC, var_metric ASC, category, var_name "); + ast_str_set(&sql, 0, "SELECT category, var_name, var_val, cat_metric FROM %s " + "WHERE filename='%s' and commented=0" + "ORDER BY cat_metric DESC, var_metric ASC, category, var_name ", table, file); - ast_debug(1, "PostgreSQL RealTime: Static SQL: %s\n", sqlbuf); + ast_debug(1, "PostgreSQL RealTime: Static SQL: %s\n", sql->str); /* We now have our complete statement; Lets connect to the server and execute it. */ ast_mutex_lock(&pgsql_lock); @@ -887,10 +1001,10 @@ static struct ast_config *config_pgsql(const char *database, const char *table, return NULL; } - if (!(result = PQexec(pgsqlConn, sqlbuf))) { + if (!(result = PQexec(pgsqlConn, sql->str))) { ast_log(LOG_WARNING, - "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n"); - ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql); + "PostgreSQL RealTime: Failed to query '%s@%s'. Check debug for more info.\n", table, database); + ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql->str); ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s\n", PQerrorMessage(pgsqlConn)); ast_mutex_unlock(&pgsql_lock); return NULL; @@ -901,7 +1015,7 @@ static struct ast_config *config_pgsql(const char *database, const char *table, && result_status != PGRES_NONFATAL_ERROR) { ast_log(LOG_WARNING, "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n"); - ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql); + ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql->str); ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s (%s)\n", PQresultErrorMessage(result), PQresStatus(result_status)); ast_mutex_unlock(&pgsql_lock); @@ -1067,7 +1181,7 @@ static int require_pgsql(const char *database, const char *tablename, va_list ap } } } - ast_mutex_unlock(&table->lock); + release_table(table); return res; } @@ -1101,6 +1215,7 @@ static struct ast_config_engine pgsql_engine = { .store_func = store_pgsql, .destroy_func = destroy_pgsql, .update_func = update_pgsql, + .update2_func = update2_pgsql, .require_func = require_pgsql, .unload_func = unload_pgsql, }; @@ -1353,7 +1468,7 @@ static char *handle_cli_realtime_pgsql_cache(struct ast_cli_entry *e, int cmd, s AST_LIST_TRAVERSE(&cur->columns, col, list) { ast_cli(a->fd, "%-20.20s %-20.20s %3d %-8.8s\n", col->name, col->type, col->len, col->notnull ? "NOT NULL" : ""); } - ast_mutex_unlock(&cur->lock); + release_table(cur); } else { ast_cli(a->fd, "No such table '%s'\n", a->argv[4]); } |