Index: apps/app_addon_sql_mysql.c =================================================================== --- apps/app_addon_sql_mysql.c (revision 600) +++ apps/app_addon_sql_mysql.c (working copy) @@ -84,7 +84,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; @@ -93,6 +105,58 @@ 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 MYSQLidshead *headp; + 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(&_mysql_ids_head, 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 MYSQLidshead *headp; + 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(&_mysql_ids_head, 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) { struct MYSQLidshead *headp; @@ -121,7 +185,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,*j; struct MYSQLidshead *headp; int maxidentifier=0; @@ -143,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 +257,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 ) { @@ -395,6 +460,17 @@ u = ast_module_user_add(chan); 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_channel_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); @@ -430,7 +506,15 @@ static int load_module(void) { struct MYSQLidshead *headp = &_mysql_ids_head; + struct ast_config *cfg; AST_LIST_HEAD_INIT(headp); + if ((cfg = ast_config_load("mysql.conf"))) { + 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); }