aboutsummaryrefslogtreecommitdiffstats
path: root/res/res_config_odbc.c
diff options
context:
space:
mode:
authortilghman <tilghman@f38db490-d61c-443f-a65b-d21fe96a405b>2008-06-10 21:14:58 +0000
committertilghman <tilghman@f38db490-d61c-443f-a65b-d21fe96a405b>2008-06-10 21:14:58 +0000
commit2a6397c89e0c4fe7beb267f1c2a53c103b0784af (patch)
tree63782d149f56bb06e85bbb2b6965ccf440e87442 /res/res_config_odbc.c
parente3f8a4c03c12f5957336ee3c3ffce325d1214bc4 (diff)
Move the table cache routines to res_odbc, so they can be used from other
places (app_voicemail, for example). (Related to bug #11678) git-svn-id: http://svn.digium.com/svn/asterisk/trunk@121683 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'res/res_config_odbc.c')
-rw-r--r--res/res_config_odbc.c200
1 files changed, 9 insertions, 191 deletions
diff --git a/res/res_config_odbc.c b/res/res_config_odbc.c
index 4bd6f20d4..4c579b978 100644
--- a/res/res_config_odbc.c
+++ b/res/res_config_odbc.c
@@ -54,153 +54,6 @@ struct custom_prepare_struct {
unsigned long long skip;
};
-/*!\brief The structures referenced are in include/asterisk/res_odbc.h */
-static AST_RWLIST_HEAD_STATIC(odbc_tables, odbc_cache_tables);
-
-static void destroy_table_cache(struct odbc_cache_tables *table) {
- struct odbc_cache_columns *col;
- ast_debug(1, "Destroying table cache for %s\n", table->table);
- AST_RWLIST_WRLOCK(&table->columns);
- while ((col = AST_RWLIST_REMOVE_HEAD(&table->columns, list))) {
- ast_free(col);
- }
- AST_RWLIST_UNLOCK(&table->columns);
- AST_RWLIST_HEAD_DESTROY(&table->columns);
- ast_free(table);
-}
-
-#define release_table(ptr) if (ptr) { AST_RWLIST_UNLOCK(&(ptr)->columns); }
-
-/*!
- * \brief Find or create an entry describing the table specified.
- * \param obj An active ODBC handle on which to query the table
- * \param table Tablename to describe
- * \retval A structure describing the table layout, or NULL, if the table is not found or another error occurs.
- * When a structure is returned, the contained columns list will be
- * rdlock'ed, to ensure that it will be retained in memory.
- */
-static struct odbc_cache_tables *find_table(const char *database, const char *tablename)
-{
- struct odbc_cache_tables *tableptr;
- struct odbc_cache_columns *entry;
- char columnname[80];
- SQLLEN sqlptr;
- SQLHSTMT stmt = NULL;
- int res = 0, error = 0, try = 0;
- struct odbc_obj *obj = ast_odbc_request_obj(database, 0);
-
- AST_RWLIST_RDLOCK(&odbc_tables);
- AST_RWLIST_TRAVERSE(&odbc_tables, tableptr, list) {
- if (strcmp(tableptr->connection, database) == 0 && strcmp(tableptr->table, tablename) == 0) {
- break;
- }
- }
- if (tableptr) {
- AST_RWLIST_RDLOCK(&tableptr->columns);
- AST_RWLIST_UNLOCK(&odbc_tables);
- return tableptr;
- }
-
- if (!obj) {
- ast_log(LOG_WARNING, "Unable to retrieve database handle for table description '%s@%s'\n", tablename, database);
- return NULL;
- }
-
- /* Table structure not already cached; build it now. */
- do {
-retry:
- res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt);
- if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
- if (try == 0) {
- try = 1;
- ast_odbc_sanity_check(obj);
- goto retry;
- }
- ast_log(LOG_WARNING, "SQL Alloc Handle failed on connection '%s'!\n", database);
- break;
- }
-
- res = SQLColumns(stmt, NULL, 0, NULL, 0, (unsigned char *)tablename, SQL_NTS, (unsigned char *)"%", SQL_NTS);
- if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
- if (try == 0) {
- try = 1;
- SQLFreeHandle(SQL_HANDLE_STMT, stmt);
- ast_odbc_sanity_check(obj);
- goto retry;
- }
- ast_log(LOG_ERROR, "Unable to query database columns on connection '%s'.\n", database);
- break;
- }
-
- if (!(tableptr = ast_calloc(sizeof(char), sizeof(*tableptr) + strlen(database) + 1 + strlen(tablename) + 1))) {
- ast_log(LOG_ERROR, "Out of memory creating entry for table '%s' on connection '%s'\n", tablename, database);
- break;
- }
-
- tableptr->connection = (char *)tableptr + sizeof(*tableptr);
- tableptr->table = (char *)tableptr + sizeof(*tableptr) + strlen(database) + 1;
- strcpy(tableptr->connection, database); /* SAFE */
- strcpy(tableptr->table, tablename); /* SAFE */
- AST_RWLIST_HEAD_INIT(&(tableptr->columns));
-
- while ((res = SQLFetch(stmt)) != SQL_NO_DATA && res != SQL_ERROR) {
- SQLGetData(stmt, 4, SQL_C_CHAR, columnname, sizeof(columnname), &sqlptr);
-
- if (!(entry = ast_calloc(sizeof(char), sizeof(*entry) + strlen(columnname) + 1))) {
- ast_log(LOG_ERROR, "Out of memory creating entry for column '%s' in table '%s' on connection '%s'\n", columnname, tablename, database);
- error = 1;
- break;
- }
- entry->name = (char *)entry + sizeof(*entry);
- strcpy(entry->name, columnname);
-
- SQLGetData(stmt, 5, SQL_C_SHORT, &entry->type, sizeof(entry->type), NULL);
- SQLGetData(stmt, 7, SQL_C_LONG, &entry->size, sizeof(entry->size), NULL);
- SQLGetData(stmt, 9, SQL_C_SHORT, &entry->decimals, sizeof(entry->decimals), NULL);
- SQLGetData(stmt, 10, SQL_C_SHORT, &entry->radix, sizeof(entry->radix), NULL);
- SQLGetData(stmt, 11, SQL_C_SHORT, &entry->nullable, sizeof(entry->nullable), NULL);
- SQLGetData(stmt, 16, SQL_C_LONG, &entry->octetlen, sizeof(entry->octetlen), NULL);
-
- /* Specification states that the octenlen should be the maximum number of bytes
- * returned in a char or binary column, but it seems that some drivers just set
- * it to NULL. (Bad Postgres! No biscuit!) */
- if (entry->octetlen == 0) {
- entry->octetlen = entry->size;
- }
-
- ast_verb(10, "Found %s column with type %hd with len %ld, octetlen %ld, and numlen (%hd,%hd)\n", entry->name, entry->type, (long) entry->size, (long) entry->octetlen, entry->decimals, entry->radix);
- /* Insert column info into column list */
- AST_LIST_INSERT_TAIL(&(tableptr->columns), entry, list);
- }
- SQLFreeHandle(SQL_HANDLE_STMT, stmt);
-
- AST_RWLIST_INSERT_TAIL(&odbc_tables, tableptr, list);
- AST_RWLIST_RDLOCK(&(tableptr->columns));
- } while (0);
-
- AST_RWLIST_UNLOCK(&odbc_tables);
-
- if (error) {
- destroy_table_cache(tableptr);
- tableptr = NULL;
- }
- if (obj) {
- ast_odbc_release_obj(obj);
- }
- return tableptr;
-}
-
-static struct odbc_cache_columns *find_column(struct odbc_cache_tables *table, const char *colname)
-{
- struct odbc_cache_columns *col;
- AST_RWLIST_TRAVERSE(&table->columns, col, list) {
- if (strcasecmp(col->name, colname) == 0) {
- return col;
- }
- }
- return NULL;
-}
-
static SQLHSTMT custom_prepare(struct odbc_obj *obj, void *data)
{
int res, x = 1, count = 0;
@@ -552,38 +405,38 @@ static int update_odbc(const char *database, const char *table, const char *keyf
int res, count = 0;
va_list aq;
struct custom_prepare_struct cps = { .sql = sql, .extra = lookup };
- struct odbc_cache_tables *tableptr = find_table(database, table);
+ struct odbc_cache_tables *tableptr = ast_odbc_find_table(database, table);
struct odbc_cache_columns *column;
va_copy(cps.ap, ap);
va_copy(aq, ap);
if (!table) {
- release_table(tableptr);
+ ast_odbc_release_table(tableptr);
return -1;
}
obj = ast_odbc_request_obj(database, 0);
if (!obj) {
- release_table(tableptr);
+ ast_odbc_release_table(tableptr);
return -1;
}
newparam = va_arg(aq, const char *);
if (!newparam) {
ast_odbc_release_obj(obj);
- release_table(tableptr);
+ ast_odbc_release_table(tableptr);
return -1;
}
newval = va_arg(aq, const char *);
- if (tableptr && !(column = find_column(tableptr, newparam))) {
+ if (tableptr && !(column = ast_odbc_find_column(tableptr, newparam))) {
ast_log(LOG_WARNING, "Key field '%s' does not exist in table '%s@%s'. Update will fail\n", newparam, table, database);
}
snprintf(sql, sizeof(sql), "UPDATE %s SET %s=?", table, newparam);
while((newparam = va_arg(aq, const char *))) {
- if ((tableptr && (column = find_column(tableptr, newparam))) || count > 63) {
+ if ((tableptr && (column = ast_odbc_find_column(tableptr, newparam))) || count > 63) {
snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), ", %s=?", newparam);
newval = va_arg(aq, const char *);
} else { /* the column does not exist in the table OR we've exceeded the space in our flag field */
@@ -593,7 +446,7 @@ static int update_odbc(const char *database, const char *table, const char *keyf
}
va_end(aq);
snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " WHERE %s=?", keyfield);
- release_table(tableptr);
+ ast_odbc_release_table(tableptr);
stmt = ast_odbc_prepare_and_execute(obj, custom_prepare, &cps);
@@ -883,7 +736,7 @@ static struct ast_config *config_odbc(const char *database, const char *table, c
static int require_odbc(const char *database, const char *table, va_list ap)
{
- struct odbc_cache_tables *tableptr = find_table(database, table);
+ struct odbc_cache_tables *tableptr = ast_odbc_find_table(database, table);
struct odbc_cache_columns *col;
char *elm;
int type, size;
@@ -1034,23 +887,6 @@ static int require_odbc(const char *database, const char *table, va_list ap)
#undef warn_length
#undef warn_type
-static int unload_odbc(const char *database, const char *tablename)
-{
- struct odbc_cache_tables *tableptr;
-
- AST_RWLIST_RDLOCK(&odbc_tables);
- AST_RWLIST_TRAVERSE_SAFE_BEGIN(&odbc_tables, tableptr, list) {
- if (strcmp(tableptr->connection, database) == 0 && strcmp(tableptr->table, tablename) == 0) {
- AST_LIST_REMOVE_CURRENT(list);
- destroy_table_cache(tableptr);
- break;
- }
- }
- AST_RWLIST_TRAVERSE_SAFE_END
- AST_RWLIST_UNLOCK(&odbc_tables);
- return tableptr ? 0 : -1;
-}
-
static struct ast_config_engine odbc_engine = {
.name = "odbc",
.load_func = config_odbc,
@@ -1060,22 +896,13 @@ static struct ast_config_engine odbc_engine = {
.destroy_func = destroy_odbc,
.update_func = update_odbc,
.require_func = require_odbc,
- .unload_func = unload_odbc,
+ .unload_func = ast_odbc_clear_cache,
};
static int unload_module (void)
{
- struct odbc_cache_tables *table;
-
ast_config_engine_deregister(&odbc_engine);
- /* Empty the cache */
- AST_RWLIST_WRLOCK(&odbc_tables);
- while ((table = AST_RWLIST_REMOVE_HEAD(&odbc_tables, list))) {
- destroy_table_cache(table);
- }
- AST_RWLIST_UNLOCK(&odbc_tables);
-
ast_verb(1, "res_config_odbc unloaded.\n");
return 0;
}
@@ -1089,15 +916,6 @@ static int load_module (void)
static int reload_module(void)
{
- struct odbc_cache_tables *table;
-
- /* Empty the cache; it will get rebuilt the next time the tables are needed. */
- AST_RWLIST_WRLOCK(&odbc_tables);
- while ((table = AST_RWLIST_REMOVE_HEAD(&odbc_tables, list))) {
- destroy_table_cache(table);
- }
- AST_RWLIST_UNLOCK(&odbc_tables);
-
return 0;
}