diff --git a/src/include/switch_core.h b/src/include/switch_core.h index 491f92bfff..cdca5308aa 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -1916,15 +1916,23 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_preprocess_session(switch_core_sessio \} */ +#define CACHE_DB_LEN 256 +typedef enum { + CDF_INUSE = (1 << 0) +} cache_db_flag_t; + typedef struct { + char name[CACHE_DB_LEN]; switch_core_db_t *db; switch_odbc_handle_t *odbc_dbh; time_t last_used; switch_mutex_t *mutex; switch_memory_pool_t *pool; + int32_t flags; } switch_cache_db_handle_t; SWITCH_DECLARE(void) switch_cache_db_release_db_handle(switch_cache_db_handle_t **dbh); +SWITCH_DECLARE(void) switch_cache_db_destroy_db_handle(switch_cache_db_handle_t **dbh); SWITCH_DECLARE(switch_status_t) switch_cache_db_get_db_handle(switch_cache_db_handle_t **dbh, const char *db_name, const char *odbc_user, const char *odbc_pass); SWITCH_DECLARE(switch_status_t) switch_cache_db_execute_sql(switch_cache_db_handle_t *dbh, const char *sql, char **err); @@ -1935,6 +1943,7 @@ SWITCH_DECLARE(switch_status_t)switch_core_db_handle(switch_cache_db_handle_t ** SWITCH_DECLARE(void) switch_cache_db_test_reactive(switch_cache_db_handle_t *db, const char *test_sql, const char *drop_sql, const char *reactive_sql); SWITCH_DECLARE(switch_status_t) switch_cache_db_persistant_execute(switch_cache_db_handle_t *dbh, const char *sql, uint32_t retries); SWITCH_DECLARE(switch_status_t) switch_cache_db_persistant_execute_trans(switch_cache_db_handle_t *dbh, const char *sql, uint32_t retries); +SWITCH_DECLARE(void) switch_cache_db_detach(void); SWITCH_END_EXTERN_C #endif diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index b69aa5560c..f857a392c4 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -4123,7 +4123,7 @@ sofia_cache_db_handle_t *sofia_glue_get_db_handle(sofia_profile_t *profile) if (db) dbh->db = db; else dbh->odbc_dbh = odbc_dbh; - switch_mutex_init(&dbh->mutex, 0, dbh->pool); + switch_mutex_init(&dbh->mutex, SWITCH_MUTEX_UNNESTED, dbh->pool); switch_mutex_lock(dbh->mutex); switch_core_hash_insert(profile->db_hash, thread_str, dbh); diff --git a/src/switch_apr.c b/src/switch_apr.c index 6a0592badc..35bf67c69b 100644 --- a/src/switch_apr.c +++ b/src/switch_apr.c @@ -630,10 +630,12 @@ SWITCH_DECLARE(switch_status_t) switch_threadattr_priority_increase(switch_threa return stat; } +static char TT_KEY[] = "1"; SWITCH_DECLARE(switch_status_t) switch_thread_create(switch_thread_t **new_thread, switch_threadattr_t *attr, switch_thread_start_t func, void *data, switch_memory_pool_t *cont) { + switch_core_memory_pool_set_data(cont, "_in_thread", TT_KEY); return apr_thread_create(new_thread, attr, func, data, cont); } diff --git a/src/switch_core_memory.c b/src/switch_core_memory.c index 474645e505..4a0ad30423 100644 --- a/src/switch_core_memory.c +++ b/src/switch_core_memory.c @@ -391,6 +391,9 @@ SWITCH_DECLARE(switch_status_t) switch_core_perform_new_memory_pool(switch_memor SWITCH_DECLARE(switch_status_t) switch_core_perform_destroy_memory_pool(switch_memory_pool_t **pool, const char *file, const char *func, int line) { switch_assert(pool != NULL); + if (switch_core_memory_pool_get_data(*pool, "_in_thread")) { + switch_cache_db_detach(); + } #ifdef DEBUG_ALLOC2 switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_CONSOLE, "Free Pool\n"); diff --git a/src/switch_core_sqldb.c b/src/switch_core_sqldb.c index 7e5d7dce96..8965e78e32 100644 --- a/src/switch_core_sqldb.c +++ b/src/switch_core_sqldb.c @@ -106,6 +106,7 @@ static void sql_close(time_t prune) switch_mutex_unlock(dbh_mutex); } + SWITCH_DECLARE(void) switch_cache_db_release_db_handle(switch_cache_db_handle_t **dbh) { if (dbh && *dbh) { @@ -114,19 +115,89 @@ SWITCH_DECLARE(void) switch_cache_db_release_db_handle(switch_cache_db_handle_t } } + +SWITCH_DECLARE(void) switch_cache_db_destroy_db_handle(switch_cache_db_handle_t **dbh) +{ + if (dbh && *dbh) { + switch_mutex_lock(dbh_mutex); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Deleting DB connection %s\n", (*dbh)->name); + if ((*dbh)->db) { + switch_core_db_close((*dbh)->db); + (*dbh)->db = NULL; + } else if (switch_odbc_available() && (*dbh)->odbc_dbh) { + switch_odbc_handle_destroy(&(*dbh)->odbc_dbh); + } + + switch_core_hash_delete(dbh_hash, (*dbh)->name); + switch_mutex_unlock((*dbh)->mutex); + switch_core_destroy_memory_pool(&(*dbh)->pool); + *dbh = NULL; + switch_mutex_unlock(dbh_mutex); + } +} + +SWITCH_DECLARE(void) switch_cache_db_detach(void) +{ + char thread_str[CACHE_DB_LEN] = ""; + switch_hash_index_t *hi; + const void *var; + void *val; + char *key; + switch_cache_db_handle_t *dbh = NULL; + + snprintf(thread_str, sizeof(thread_str) - 1, "%lu", (unsigned long)(intptr_t)switch_thread_self()); + switch_mutex_lock(dbh_mutex); + + for (hi = switch_hash_first(NULL, dbh_hash); hi; hi = switch_hash_next(hi)) { + switch_hash_this(hi, &var, NULL, &val); + key = (char *) var; + if ((dbh = (switch_cache_db_handle_t *) val)) { + if (switch_mutex_trylock(dbh->mutex) == SWITCH_STATUS_SUCCESS) { + if (strstr(dbh->name, thread_str)) { + switch_clear_flag(dbh, CDF_INUSE); + } + switch_mutex_unlock(dbh->mutex); + } + } + } + + switch_mutex_unlock(dbh_mutex); +} + SWITCH_DECLARE(switch_status_t)switch_cache_db_get_db_handle(switch_cache_db_handle_t **dbh, const char *db_name, const char *odbc_user, const char *odbc_pass) { switch_thread_id_t self = switch_thread_self(); - char thread_str[256] = ""; + char thread_str[CACHE_DB_LEN] = ""; switch_cache_db_handle_t *new_dbh = NULL; switch_assert(db_name); snprintf(thread_str, sizeof(thread_str) - 1, "%s_%lu", db_name, (unsigned long)(intptr_t)self); - + switch_mutex_lock(dbh_mutex); if (!(new_dbh = switch_core_hash_find(dbh_hash, thread_str))) { + switch_hash_index_t *hi; + const void *var; + void *val; + char *key; + + for (hi = switch_hash_first(NULL, dbh_hash); hi; hi = switch_hash_next(hi)) { + switch_hash_this(hi, &var, NULL, &val); + key = (char *) var; + + if ((new_dbh = (switch_cache_db_handle_t *) val)) { + if (!switch_test_flag(new_dbh, CDF_INUSE) && switch_mutex_trylock(new_dbh->mutex) == SWITCH_STATUS_SUCCESS) { + switch_set_flag(new_dbh, CDF_INUSE); + switch_set_string(new_dbh->name, thread_str); + break; + } + } + new_dbh = NULL; + } + } + + if (!new_dbh) { switch_memory_pool_t *pool = NULL; switch_core_db_t *db = NULL; switch_odbc_handle_t *odbc_dbh = NULL; @@ -149,13 +220,14 @@ SWITCH_DECLARE(switch_status_t)switch_cache_db_get_db_handle(switch_cache_db_han switch_core_new_memory_pool(&pool); new_dbh = switch_core_alloc(pool, sizeof(*new_dbh)); new_dbh->pool = pool; - + switch_set_string(new_dbh->name, thread_str); + switch_set_flag(new_dbh, CDF_INUSE); if (db) new_dbh->db = db; else new_dbh->odbc_dbh = odbc_dbh; - switch_mutex_init(&new_dbh->mutex, 0, new_dbh->pool); + switch_mutex_init(&new_dbh->mutex, SWITCH_MUTEX_UNNESTED, new_dbh->pool); switch_mutex_lock(new_dbh->mutex); - switch_core_hash_insert(dbh_hash, thread_str, new_dbh); + switch_core_hash_insert(dbh_hash, new_dbh->name, new_dbh); } end: