Index: res/res_config_mysql.c =================================================================== --- res/res_config_mysql.c (revision 915) +++ res/res_config_mysql.c (working copy) @@ -200,6 +200,7 @@ MYSQL_ROW row; if (!(dbh = find_database(database, 1))) { + ast_log(LOG_WARNING, "Database '%s' not found!\n", database); return NULL; } @@ -217,6 +218,7 @@ ast_str_set(&sql, 0, "DESC %s", tablename); if (!mysql_reconnect(dbh)) { + ast_log(LOG_WARNING, "Unable to connect to database '%s'\n", database); release_database(dbh); AST_LIST_UNLOCK(&mysql_tables); return NULL; Index: apps/app_addon_sql_mysql.c =================================================================== --- apps/app_addon_sql_mysql.c (revision 915) +++ apps/app_addon_sql_mysql.c (working copy) @@ -90,7 +90,19 @@ #define AST_MYSQL_ID_RESID 2 #define AST_MYSQL_ID_FETCHID 3 +int autoclear = 0; + +static void mysql_ds_destroy(void *data); +static void mysql_ds_fixup(void *data, struct ast_channel *oldchan, struct ast_channel *newchan); + +static struct ast_datastore_info mysql_ds_info = { + .type = "APP_ADDON_SQL_MYSQL", + .destroy = mysql_ds_destroy, + .chan_fixup = mysql_ds_fixup, +}; + struct ast_MYSQL_id { + struct ast_channel *owner; int identifier_type; /* 0=dummy, 1=connid, 2=resultid */ int identifier; void *data; @@ -99,6 +111,56 @@ AST_LIST_HEAD(MYSQLidshead,ast_MYSQL_id) _mysql_ids_head; +static void mysql_ds_destroy(void *data) +{ + /* Destroy any IDs owned by the channel */ + struct ast_MYSQL_id *i; + if (AST_LIST_LOCK(&_mysql_ids_head)) { + ast_log(LOG_WARNING, "Unable to lock identifiers list\n"); + } else { + AST_LIST_TRAVERSE_SAFE_BEGIN(&_mysql_ids_head, i, entries) { + if (i->owner == data) { + AST_LIST_REMOVE_CURRENT(entries); + if (i->identifier_type == AST_MYSQL_ID_CONNID) { + /* Drop connection */ + mysql_close(i->data); + } else if (i->identifier_type == AST_MYSQL_ID_RESID) { + /* Drop result */ + mysql_free_result(i->data); + } + ast_free(i); + } + } + AST_LIST_TRAVERSE_SAFE_END + AST_LIST_UNLOCK(&_mysql_ids_head); + } +} + +static void mysql_ds_fixup(void *data, struct ast_channel *oldchan, struct ast_channel *newchan) +{ + /* Destroy any IDs owned by the channel */ + struct ast_MYSQL_id *i; + if (AST_LIST_LOCK(&_mysql_ids_head)) { + ast_log(LOG_WARNING, "Unable to lock identifiers list\n"); + } else { + AST_LIST_TRAVERSE_SAFE_BEGIN(&_mysql_ids_head, i, entries) { + if (i->owner == data) { + AST_LIST_REMOVE_CURRENT(entries); + if (i->identifier_type == AST_MYSQL_ID_CONNID) { + /* Drop connection */ + mysql_close(i->data); + } else if (i->identifier_type == AST_MYSQL_ID_RESID) { + /* Drop result */ + mysql_free_result(i->data); + } + ast_free(i); + } + } + AST_LIST_TRAVERSE_SAFE_END + AST_LIST_UNLOCK(&_mysql_ids_head); + } +} + /* helpful procs */ static void *find_identifier(int identifier, int identifier_type) { @@ -126,7 +188,7 @@ return res; } -static int add_identifier(int identifier_type, void *data) +static int add_identifier(struct ast_channel *chan, int identifier_type, void *data) { struct ast_MYSQL_id *i = NULL, *j = NULL; struct MYSQLidshead *headp = &_mysql_ids_head; @@ -145,6 +207,7 @@ i->identifier = maxidentifier + 1; i->identifier_type = identifier_type; i->data = data; + i->owner = chan; AST_LIST_INSERT_HEAD(headp, i, entries); AST_LIST_UNLOCK(headp); } @@ -192,7 +255,7 @@ static int add_identifier_and_set_asterisk_int(struct ast_channel *chan, char *varname, int identifier_type, void *data) { - return set_asterisk_int(chan, varname, add_identifier(identifier_type, data)); + return set_asterisk_int(chan, varname, add_identifier(chan, identifier_type, data)); } static int safe_scan_int(char **data, char *delim, int def) @@ -460,6 +523,17 @@ result = 0; + if (autoclear) { + struct ast_datastore *mysql_store = ast_channel_datastore_find(chan, &mysql_ds_info, NULL); + if (!mysql_store) { + if (!(mysql_store = ast_datastore_alloc(&mysql_ds_info, NULL))) { + ast_log(LOG_WARNING, "Unable to allocate new datastore.\n"); + } else { + mysql_store->data = chan; + ast_channel_datastore_add(chan, mysql_store); + } + } + } ast_mutex_lock(&_mysql_mutex); if (strncasecmp("connect", data, strlen("connect")) == 0) { @@ -496,7 +570,16 @@ static int load_module(void) { struct MYSQLidshead *headp = &_mysql_ids_head; + struct ast_config *cfg; + struct ast_flags flags = { 0, }; AST_LIST_HEAD_INIT(headp); + if ((cfg = ast_config_load("mysql.conf", flags))) { + const char *tmp = ast_variable_retrieve(cfg, "general", "autoclear"); + if (tmp && ast_true(tmp)) { + autoclear = 1; + } + ast_config_destroy(cfg); + } return ast_register_application(app, MYSQL_exec, synopsis, descrip); }