diff --git a/src/include/switch_core.h b/src/include/switch_core.h index 8cf75988e5..590e01ace2 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -2077,8 +2077,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_preprocess_session(switch_core_sessio #define CACHE_DB_LEN 256 typedef enum { CDF_INUSE = (1 << 0), - CDF_PRUNE = (1 << 1), - CDF_RELEASED = (1 << 2) + CDF_PRUNE = (1 << 1) } cache_db_flag_t; typedef enum { @@ -2106,20 +2105,8 @@ typedef union { switch_cache_db_odbc_options_t odbc_options; } switch_cache_db_connection_options_t; -typedef struct { - char name[CACHE_DB_LEN]; - switch_cache_db_handle_type_t type; - switch_cache_db_native_handle_t native_handle; - time_t last_used; - switch_mutex_t *mutex; - switch_mutex_t *io_mutex; - switch_memory_pool_t *pool; - int32_t flags; - unsigned long hash; - char creator[CACHE_DB_LEN]; - char last_user[CACHE_DB_LEN]; -} switch_cache_db_handle_t; - +struct switch_cache_db_handle; +typedef struct switch_cache_db_handle switch_cache_db_handle_t; static inline const char *switch_cache_db_type_name(switch_cache_db_handle_type_t type) { @@ -2141,6 +2128,8 @@ static inline const char *switch_cache_db_type_name(switch_cache_db_handle_type_ return type_str; } +SWITCH_DECLARE(switch_cache_db_handle_type_t) switch_cache_db_get_type(switch_cache_db_handle_t *dbh); + /*! \brief Returns the handle to the pool, immediately available for other threads to use. @@ -2153,11 +2142,6 @@ SWITCH_DECLARE(void) switch_cache_db_dismiss_db_handle(switch_cache_db_handle_t \param [in] The handle */ SWITCH_DECLARE(void) switch_cache_db_release_db_handle(switch_cache_db_handle_t ** dbh); -/*! - \brief Removes the handle from the pool and frees up the handle resources. - \param [in] The handle -*/ -SWITCH_DECLARE(void) switch_cache_db_destroy_db_handle(switch_cache_db_handle_t ** dbh); /*! \brief Gets a new cached handle from the pool, potentially creating a new connection. The connection is bound to the thread until it (the thread) terminates unless @@ -2218,10 +2202,7 @@ SWITCH_DECLARE(switch_bool_t) switch_cache_db_test_reactive(switch_cache_db_hand 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, char *sql, uint32_t retries); -/*! - \brief Tries to detach all free connections from current thread. -*/ -SWITCH_DECLARE(void) switch_cache_db_detach(void); + SWITCH_DECLARE(uint32_t) switch_core_debug_level(void); SWITCH_DECLARE(void) switch_cache_db_flush_handles(void); SWITCH_DECLARE(const char *) switch_core_banner(void); diff --git a/src/switch_console.c b/src/switch_console.c index 43a5b17fb6..a73bb58e89 100644 --- a/src/switch_console.c +++ b/src/switch_console.c @@ -252,7 +252,7 @@ SWITCH_DECLARE(char *) switch_console_expand_alias(char *cmd, char *arg) } - if (db->type == SCDB_TYPE_CORE_DB) { + if (switch_cache_db_get_type(db) == SCDB_TYPE_CORE_DB) { sql = switch_mprintf("select command from aliases where alias='%q'", cmd); } else { sql = switch_mprintf("select command from aliases where alias='%w'", cmd); @@ -268,7 +268,7 @@ SWITCH_DECLARE(char *) switch_console_expand_alias(char *cmd, char *arg) switch_safe_free(sql); if (!r) { - if (db->type == SCDB_TYPE_CORE_DB) { + if (switch_cache_db_get_type(db) == SCDB_TYPE_CORE_DB) { sql = switch_mprintf("select command from aliases where alias='%q %q'", cmd, arg); } else { sql = switch_mprintf("select command from aliases where alias='%w %w'", cmd, arg); @@ -794,7 +794,7 @@ SWITCH_DECLARE(unsigned char) switch_console_complete(const char *line, const ch stream.write_function(&stream, "select distinct a1 from complete where " "a1 not in (select name from interfaces where hostname='%s') %s ", switch_core_get_hostname(), argc ? "and" : ""); } else { - if (db->type == SCDB_TYPE_CORE_DB) { + if (switch_cache_db_get_type(db) == SCDB_TYPE_CORE_DB) { stream.write_function(&stream, "select distinct a%d,'%q','%q' from complete where ", h.words + 1, switch_str_nil(dup), switch_str_nil(lp)); } else { stream.write_function(&stream, "select distinct a%d,'%q','%w' from complete where ", h.words + 1, switch_str_nil(dup), switch_str_nil(lp)); @@ -803,7 +803,7 @@ SWITCH_DECLARE(unsigned char) switch_console_complete(const char *line, const ch for (x = 0; x < argc && x < 11; x++) { if (h.words + 1 > argc) { - if (db->type == SCDB_TYPE_CORE_DB) { + if (switch_cache_db_get_type(db) == SCDB_TYPE_CORE_DB) { stream.write_function(&stream, "(a%d like '::%%' or a%d = '' or a%d = '%q')%q", x + 1, x + 1, x + 1, switch_str_nil(argv[x]), x == argc - 1 ? "" : " and "); } else { @@ -811,7 +811,7 @@ SWITCH_DECLARE(unsigned char) switch_console_complete(const char *line, const ch x + 1, x + 1, x + 1, switch_str_nil(argv[x]), x == argc - 1 ? "" : " and "); } } else { - if (db->type == SCDB_TYPE_CORE_DB) { + if (switch_cache_db_get_type(db) == SCDB_TYPE_CORE_DB) { stream.write_function(&stream, "(a%d like '::%%' or a%d = '' or a%d like '%q%%')%q", x + 1, x + 1, x + 1, switch_str_nil(argv[x]), x == argc - 1 ? "" : " and "); } else { @@ -1792,7 +1792,7 @@ SWITCH_DECLARE(switch_status_t) switch_console_set_complete(const char *string) if (argv[x + 1] && !strcasecmp(argv[x + 1], "_any_")) { mystream.write_function(&mystream, "%s", "'', "); } else { - if (db->type == SCDB_TYPE_CORE_DB) { + if (switch_cache_db_get_type(db) == SCDB_TYPE_CORE_DB) { mystream.write_function(&mystream, "'%q', ", switch_str_nil(argv[x + 1])); } else { mystream.write_function(&mystream, "'%w', ", switch_str_nil(argv[x + 1])); @@ -1808,7 +1808,7 @@ SWITCH_DECLARE(switch_status_t) switch_console_set_complete(const char *string) if (argv[x + 1] && !strcasecmp(argv[x + 1], "_any_")) { mystream.write_function(&mystream, "%s", "'', "); } else { - if (db->type == SCDB_TYPE_CORE_DB) { + if (switch_cache_db_get_type(db) == SCDB_TYPE_CORE_DB) { mystream.write_function(&mystream, "'%q', ", switch_str_nil(argv[x + 1])); } else { mystream.write_function(&mystream, "'%w', ", switch_str_nil(argv[x + 1])); @@ -1826,7 +1826,7 @@ SWITCH_DECLARE(switch_status_t) switch_console_set_complete(const char *string) } else { mystream.write_function(&mystream, "delete from complete where "); for (x = 0; x < argc - 1; x++) { - if (db->type == SCDB_TYPE_CORE_DB) { + if (switch_cache_db_get_type(db) == SCDB_TYPE_CORE_DB) { mystream.write_function(&mystream, "a%d = '%q'%q", x + 1, switch_str_nil(argv[x + 1]), x == argc - 2 ? "" : " and "); } else { mystream.write_function(&mystream, "a%d = '%w'%w", x + 1, switch_str_nil(argv[x + 1]), x == argc - 2 ? "" : " and "); @@ -1871,7 +1871,7 @@ SWITCH_DECLARE(switch_status_t) switch_console_set_alias(const char *string) sql = switch_mprintf("delete from aliases where alias='%q' and hostname='%q'", argv[1], switch_core_get_hostname()); switch_cache_db_persistant_execute(db, sql, 5); switch_safe_free(sql); - if (db->type == SCDB_TYPE_CORE_DB) { + if (switch_cache_db_get_type(db) == SCDB_TYPE_CORE_DB) { sql = switch_mprintf("insert into aliases (sticky, alias, command, hostname) values (1, '%q','%q','%q')", argv[1], argv[2], switch_core_get_hostname()); } else { @@ -1884,7 +1884,7 @@ SWITCH_DECLARE(switch_status_t) switch_console_set_alias(const char *string) sql = switch_mprintf("delete from aliases where alias='%q' and hostname='%q'", argv[1], switch_core_get_hostname()); switch_cache_db_persistant_execute(db, sql, 5); switch_safe_free(sql); - if (db->type == SCDB_TYPE_CORE_DB) { + if (switch_cache_db_get_type(db) == SCDB_TYPE_CORE_DB) { sql = switch_mprintf("insert into aliases (sticky, alias, command, hostname) values (0, '%q','%q','%q')", argv[1], argv[2], switch_core_get_hostname()); } else { diff --git a/src/switch_core_memory.c b/src/switch_core_memory.c index dd87f8f4a2..7e6abf9c77 100644 --- a/src/switch_core_memory.c +++ b/src/switch_core_memory.c @@ -409,9 +409,7 @@ 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"); #endif diff --git a/src/switch_core_sqldb.c b/src/switch_core_sqldb.c index a0529babf1..26c8c71711 100644 --- a/src/switch_core_sqldb.c +++ b/src/switch_core_sqldb.c @@ -36,6 +36,21 @@ #include "private/switch_core_pvt.h" //*#define DEBUG_SQL 1 +struct switch_cache_db_handle { + char name[CACHE_DB_LEN]; + switch_cache_db_handle_type_t type; + switch_cache_db_native_handle_t native_handle; + time_t last_used; + switch_mutex_t *mutex; + switch_mutex_t *io_mutex; + switch_memory_pool_t *pool; + int32_t flags; + unsigned long hash; + char creator[CACHE_DB_LEN]; + char last_user[CACHE_DB_LEN]; + struct switch_cache_db_handle *next; +}; + static struct { switch_cache_db_handle_t *event_db; switch_queue_t *sql_queue[2]; @@ -48,13 +63,74 @@ static struct { switch_bool_t manage; switch_mutex_t *io_mutex; switch_mutex_t *dbh_mutex; - switch_hash_t *dbh_hash; + switch_cache_db_handle_t *handle_pool; switch_thread_cond_t *cond; switch_mutex_t *cond_mutex; int total_handles; + int total_used_handles; } sql_manager; +static void add_handle(switch_cache_db_handle_t *dbh) +{ + switch_mutex_lock(sql_manager.dbh_mutex); + dbh->next = sql_manager.handle_pool; + sql_manager.handle_pool = dbh; + sql_manager.total_handles++; + switch_mutex_unlock(sql_manager.dbh_mutex); +} + +static void del_handle(switch_cache_db_handle_t *dbh) +{ + switch_cache_db_handle_t *dbhp, *last = NULL; + + switch_mutex_lock(sql_manager.dbh_mutex); + for (dbhp = sql_manager.handle_pool; dbhp; dbhp = dbhp->next) { + if (dbhp == dbh) { + if (last) { + last->next = dbhp->next; + } else { + sql_manager.handle_pool = dbhp->next; + } + sql_manager.total_handles--; + break; + } + + last = dbhp; + } + switch_mutex_unlock(sql_manager.dbh_mutex); +} + +static switch_cache_db_handle_t *get_handle(const char *db_str, const char *user_str) +{ + switch_ssize_t hlen = -1; + unsigned long hash = 0; + switch_cache_db_handle_t *dbhp, *r = NULL; + + + hash = switch_ci_hashfunc_default(db_str, &hlen); + + switch_mutex_lock(sql_manager.dbh_mutex); + for (dbhp = sql_manager.handle_pool; dbhp; dbhp = dbhp->next) { + if (dbhp->hash == hash && !switch_test_flag(dbhp, CDF_INUSE) && + !switch_test_flag(dbhp, CDF_PRUNE) && switch_mutex_trylock(dbhp->mutex) == SWITCH_STATUS_SUCCESS) { + r = dbhp; + + switch_set_flag(dbhp, CDF_INUSE); + sql_manager.total_used_handles++; + dbhp->hash = switch_ci_hashfunc_default(db_str, &hlen); + switch_set_string(dbhp->last_user, user_str); + + break; + } + } + switch_mutex_unlock(sql_manager.dbh_mutex); + + return r; + +} + + #define SWITCH_CORE_DB "core" /*! \brief Open the default system database @@ -92,99 +168,58 @@ SWITCH_DECLARE(switch_status_t) _switch_core_db_handle(switch_cache_db_handle_t #define SQL_CACHE_TIMEOUT 120 -#define SQL_RELEASE_TIMEOUT 5 #define SQL_REG_TIMEOUT 15 -static void sql_release(void) -{ - switch_hash_index_t *hi; - const void *var; - void *val; - switch_cache_db_handle_t *dbh = NULL; - - switch_mutex_lock(sql_manager.dbh_mutex); - - for (hi = switch_hash_first(NULL, sql_manager.dbh_hash); hi; hi = switch_hash_next(hi)) { - switch_hash_this(hi, &var, NULL, &val); - - if ((dbh = (switch_cache_db_handle_t *) val)) { - time_t diff = 0; - - diff = (time_t) switch_epoch_time_now(NULL) - dbh->last_used; - - if (switch_test_flag(dbh, CDF_RELEASED) && diff > SQL_RELEASE_TIMEOUT) { - switch_clear_flag(dbh, CDF_INUSE); - switch_clear_flag(dbh, CDF_RELEASED); - } - } - } - - switch_mutex_unlock(sql_manager.dbh_mutex); -} - static void sql_close(time_t prune) { - switch_hash_index_t *hi; - const void *var; - void *val; switch_cache_db_handle_t *dbh = NULL; int locked = 0; - char *key; switch_mutex_lock(sql_manager.dbh_mutex); top: locked = 0; - for (hi = switch_hash_first(NULL, sql_manager.dbh_hash); hi; hi = switch_hash_next(hi)) { - switch_hash_this(hi, &var, NULL, &val); - key = (char *) var; + for (dbh = sql_manager.handle_pool; dbh; dbh = dbh->next) { + time_t diff = 0; - if ((dbh = (switch_cache_db_handle_t *) val)) { - time_t diff = 0; - - if (prune > 0 && prune > dbh->last_used) { - diff = (time_t) prune - dbh->last_used; - } - - if (switch_test_flag(dbh, CDF_RELEASED) && diff > SQL_RELEASE_TIMEOUT) { - switch_clear_flag(dbh, CDF_INUSE); - switch_clear_flag(dbh, CDF_RELEASED); - } - - if (prune > 0 && (switch_test_flag(dbh, CDF_INUSE) || (diff < SQL_CACHE_TIMEOUT && !switch_test_flag(dbh, CDF_PRUNE)))) { - continue; - } - - if (switch_mutex_trylock(dbh->mutex) == SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10, "Dropping idle DB connection %s\n", key); - - switch (dbh->type) { - case SCDB_TYPE_ODBC: - { - switch_odbc_handle_destroy(&dbh->native_handle.odbc_dbh); - } - break; - case SCDB_TYPE_CORE_DB: - { - switch_core_db_close(dbh->native_handle.core_db_dbh); - dbh->native_handle.core_db_dbh = NULL; - } - break; - } - - switch_core_hash_delete(sql_manager.dbh_hash, key); - sql_manager.total_handles--; - switch_mutex_unlock(dbh->mutex); - switch_core_destroy_memory_pool(&dbh->pool); - goto top; - - } else { - if (!prune) - locked++; - continue; - } + if (prune > 0 && prune > dbh->last_used) { + diff = (time_t) prune - dbh->last_used; } + + if (prune > 0 && (switch_test_flag(dbh, CDF_INUSE) || (diff < SQL_CACHE_TIMEOUT && !switch_test_flag(dbh, CDF_PRUNE)))) { + continue; + } + + if (switch_mutex_trylock(dbh->mutex) == SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10, "Dropping idle DB connection %s\n", dbh->name); + + switch (dbh->type) { + case SCDB_TYPE_ODBC: + { + switch_odbc_handle_destroy(&dbh->native_handle.odbc_dbh); + } + break; + case SCDB_TYPE_CORE_DB: + { + switch_core_db_close(dbh->native_handle.core_db_dbh); + dbh->native_handle.core_db_dbh = NULL; + } + break; + } + + del_handle(dbh); + switch_mutex_unlock(dbh->mutex); + switch_core_destroy_memory_pool(&dbh->pool); + goto top; + + } else { + if (!prune) { + locked++; + } + continue; + } + } if (locked) { @@ -195,6 +230,11 @@ static void sql_close(time_t prune) } +SWITCH_DECLARE(switch_cache_db_handle_type_t) switch_cache_db_get_type(switch_cache_db_handle_t *dbh) +{ + return dbh->type; +} + SWITCH_DECLARE(void) switch_cache_db_flush_handles(void) { sql_close(switch_epoch_time_now(NULL) + SQL_CACHE_TIMEOUT + 1); @@ -204,10 +244,13 @@ SWITCH_DECLARE(void) switch_cache_db_flush_handles(void) SWITCH_DECLARE(void) switch_cache_db_release_db_handle(switch_cache_db_handle_t **dbh) { if (dbh && *dbh) { - switch_set_flag((*dbh), CDF_RELEASED); + switch_mutex_lock(sql_manager.dbh_mutex); (*dbh)->last_used = switch_epoch_time_now(NULL); + switch_clear_flag((*dbh), CDF_INUSE); switch_mutex_unlock((*dbh)->mutex); + sql_manager.total_used_handles--; *dbh = NULL; + switch_mutex_unlock(sql_manager.dbh_mutex); } } @@ -218,83 +261,15 @@ SWITCH_DECLARE(void) switch_cache_db_dismiss_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(sql_manager.dbh_mutex); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10, "Deleting DB connection %s\n", (*dbh)->name); - - switch ((*dbh)->type) { - case SCDB_TYPE_ODBC: - { - switch_odbc_handle_destroy(&(*dbh)->native_handle.odbc_dbh); - } - break; - case SCDB_TYPE_CORE_DB: - { - switch_core_db_close((*dbh)->native_handle.core_db_dbh); - (*dbh)->native_handle.core_db_dbh = NULL; - } - break; - } - - - switch_core_hash_delete(sql_manager.dbh_hash, (*dbh)->name); - sql_manager.total_handles--; - switch_mutex_unlock((*dbh)->mutex); - switch_core_destroy_memory_pool(&(*dbh)->pool); - *dbh = NULL; - switch_mutex_unlock(sql_manager.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; - - if (!sql_manager.dbh_hash) { - return; - } - snprintf(thread_str, sizeof(thread_str) - 1, "%lu", (unsigned long) (intptr_t) switch_thread_self()); - switch_mutex_lock(sql_manager.dbh_mutex); - - for (hi = switch_hash_first(NULL, sql_manager.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_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10, - "Detach cached DB handle %s [%s]\n", thread_str, switch_cache_db_type_name(dbh->type)); - switch_set_flag(dbh, CDF_RELEASED); - - } - switch_mutex_unlock(dbh->mutex); - } - } - } - - switch_mutex_unlock(sql_manager.dbh_mutex); -} - SWITCH_DECLARE(switch_status_t) _switch_cache_db_get_db_handle(switch_cache_db_handle_t **dbh, switch_cache_db_handle_type_t type, switch_cache_db_connection_options_t *connection_options, const char *file, const char *func, int line) { - switch_thread_id_t self = switch_thread_self(); - char thread_str[CACHE_DB_LEN] = ""; char db_str[CACHE_DB_LEN] = ""; char db_callsite_str[CACHE_DB_LEN] = ""; switch_cache_db_handle_t *new_dbh = NULL; switch_ssize_t hlen = -1; - int locked = 0; const char *db_name = NULL; const char *db_user = NULL; @@ -322,57 +297,14 @@ SWITCH_DECLARE(switch_status_t) _switch_cache_db_get_db_handle(switch_cache_db_h } snprintf(db_str, sizeof(db_str) - 1, "db=\"%s\";user=\"%s\";pass=\"%s\"", db_name, db_user, db_pass); - snprintf(thread_str, sizeof(thread_str) - 1, "%s;thread=\"%lu\"", db_str, (unsigned long) (intptr_t) self); snprintf(db_callsite_str, sizeof(db_callsite_str) - 1, "%s:%d", file, line); switch_mutex_lock(sql_manager.dbh_mutex); - if ((new_dbh = switch_core_hash_find(sql_manager.dbh_hash, thread_str))) { - if ((switch_test_flag(new_dbh, CDF_INUSE) && !switch_test_flag(new_dbh, CDF_RELEASED)) || - switch_test_flag(new_dbh, CDF_PRUNE) || switch_mutex_trylock(new_dbh->mutex) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_DEBUG10, - "Cached DB handle %s already in use. [%s]\n", new_dbh->name, switch_cache_db_type_name(new_dbh->type)); - new_dbh = NULL; - } else { - switch_set_string(new_dbh->last_user, db_callsite_str); - switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_DEBUG10, - "Reuse Cached DB handle %s [%s]\n", new_dbh->name, switch_cache_db_type_name(new_dbh->type)); - locked = 1; - switch_clear_flag(new_dbh, CDF_RELEASED); - } - } - - if (!new_dbh) { - switch_hash_index_t *hi; - const void *var; - void *val; - char *key; - unsigned long hash = 0; - - hash = switch_ci_hashfunc_default(db_str, &hlen); - - for (hi = switch_hash_first(NULL, sql_manager.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 (hash == new_dbh->hash && !strncasecmp(new_dbh->name, db_str, strlen(db_str)) && - !switch_test_flag(new_dbh, CDF_INUSE) && !switch_test_flag(new_dbh, CDF_PRUNE) - && switch_mutex_trylock(new_dbh->mutex) == SWITCH_STATUS_SUCCESS) { - switch_set_flag(new_dbh, CDF_INUSE); - switch_set_string(new_dbh->name, thread_str); - new_dbh->hash = switch_ci_hashfunc_default(db_str, &hlen); - switch_set_string(new_dbh->last_user, db_callsite_str); - switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_DEBUG10, - "Reuse Unused Cached DB handle %s [%s]\n", new_dbh->name, switch_cache_db_type_name(new_dbh->type)); - break; - } - } - new_dbh = NULL; - } - } - - if (!new_dbh) { + if ((new_dbh = get_handle(db_str, db_callsite_str))) { + switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_DEBUG10, + "Reuse Unused Cached DB handle %s [%s]\n", new_dbh->name, switch_cache_db_type_name(new_dbh->type)); + } else { switch_memory_pool_t *pool = NULL; switch_core_db_t *db = NULL; switch_odbc_handle_t *odbc_dbh = NULL; @@ -412,7 +344,7 @@ SWITCH_DECLARE(switch_status_t) _switch_cache_db_get_db_handle(switch_cache_db_h } switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_DEBUG10, - "Create Cached DB handle %s [%s] %s:%d\n", thread_str, switch_cache_db_type_name(type), file, line); + "Create Cached DB handle %s [%s] %s:%d\n", new_dbh->name, switch_cache_db_type_name(type), file, line); switch_core_new_memory_pool(&pool); new_dbh = switch_core_alloc(pool, sizeof(*new_dbh)); @@ -420,8 +352,9 @@ SWITCH_DECLARE(switch_status_t) _switch_cache_db_get_db_handle(switch_cache_db_h new_dbh->type = type; - switch_set_string(new_dbh->name, thread_str); + switch_set_string(new_dbh->name, db_str); switch_set_flag(new_dbh, CDF_INUSE); + sql_manager.total_used_handles++; new_dbh->hash = switch_ci_hashfunc_default(db_str, &hlen); @@ -433,10 +366,8 @@ SWITCH_DECLARE(switch_status_t) _switch_cache_db_get_db_handle(switch_cache_db_h switch_mutex_init(&new_dbh->mutex, SWITCH_MUTEX_UNNESTED, new_dbh->pool); switch_set_string(new_dbh->creator, db_callsite_str); - if (!locked) switch_mutex_lock(new_dbh->mutex); - - switch_core_hash_insert(sql_manager.dbh_hash, new_dbh->name, new_dbh); - sql_manager.total_handles++; + switch_mutex_lock(new_dbh->mutex); + add_handle(new_dbh); } end: @@ -926,14 +857,7 @@ static void *SWITCH_THREAD_FUNC switch_core_sql_db_thread(switch_thread_t *threa sql_manager.db_thread_running = 1; while (sql_manager.db_thread_running == 1) { - sec++; - - if ((sec % SQL_RELEASE_TIMEOUT) == 0 || sec == 1) { - sql_release(); - wake_thread(0); - } - - if (sec == SQL_CACHE_TIMEOUT) { + if (++sec == SQL_CACHE_TIMEOUT) { sql_close(switch_epoch_time_now(NULL)); wake_thread(0); sec = 0; @@ -1783,8 +1707,6 @@ switch_status_t switch_core_sqldb_start(switch_memory_pool_t *pool, switch_bool_ switch_thread_cond_create(&sql_manager.cond, sql_manager.memory_pool); - switch_core_hash_init(&sql_manager.dbh_hash, sql_manager.memory_pool); - top: if (!sql_manager.manage) goto skip; @@ -1966,65 +1888,57 @@ void switch_core_sqldb_stop(void) switch_cache_db_flush_handles(); sql_close(0); - - switch_core_hash_destroy(&sql_manager.dbh_hash); - } SWITCH_DECLARE(void) switch_cache_db_status(switch_stream_handle_t *stream) { /* return some status info suitable for the cli */ - switch_hash_index_t *hi; switch_cache_db_handle_t *dbh = NULL; - void *val; - const void *var; - char *key; switch_bool_t locked = SWITCH_FALSE; time_t now = switch_epoch_time_now(NULL); char cleankey_str[CACHE_DB_LEN]; char *pos1 = NULL; char *pos2 = NULL; - int count = 0; + int count = 0, used = 0; switch_mutex_lock(sql_manager.dbh_mutex); - for (hi = switch_hash_first(NULL, sql_manager.dbh_hash); hi; hi = switch_hash_next(hi)) { - switch_hash_this(hi, &var, NULL, &val); - key = (char *) var; + for (dbh = sql_manager.handle_pool; dbh; dbh = dbh->next) { + char *needle = "pass=\""; + time_t diff = 0; - if ((dbh = (switch_cache_db_handle_t *) val)) { - char *needle = "pass=\""; - time_t diff = 0; + diff = now - dbh->last_used; - diff = now - dbh->last_used; - - if (switch_mutex_trylock(dbh->mutex) == SWITCH_STATUS_SUCCESS) { - switch_mutex_unlock(dbh->mutex); - locked = SWITCH_FALSE; - } else { - locked = SWITCH_TRUE; - } - - /* sanitize password */ - memset(cleankey_str, 0, sizeof(cleankey_str)); - pos1 = strstr(key, needle) + strlen(needle); - pos2 = strstr(pos1, "\""); - strncpy(cleankey_str, key, pos1 - key); - strcpy(&cleankey_str[pos1 - key], pos2); - - count++; - stream->write_function(stream, "%s\n\tType: %s\n\tLast used: %d\n\tFlags: %s, %s\n" - "\tCreator: %s\n\tLast User: %s\n", - cleankey_str, - switch_cache_db_type_name(dbh->type), - diff, - locked ? "Locked" : "Unlocked", - switch_test_flag(dbh, CDF_INUSE) ? switch_test_flag(dbh, CDF_RELEASED) ? "Released" : - "Attached" : "Detached", dbh->creator, dbh->last_user); + if (switch_mutex_trylock(dbh->mutex) == SWITCH_STATUS_SUCCESS) { + switch_mutex_unlock(dbh->mutex); + locked = SWITCH_FALSE; + } else { + locked = SWITCH_TRUE; } + + /* sanitize password */ + memset(cleankey_str, 0, sizeof(cleankey_str)); + pos1 = strstr(dbh->name, needle) + strlen(needle); + pos2 = strstr(pos1, "\""); + strncpy(cleankey_str, dbh->name, pos1 - dbh->name); + strcpy(&cleankey_str[pos1 - dbh->name], pos2); + + count++; + + if (switch_test_flag(dbh, CDF_INUSE)) { + used++; + } + + stream->write_function(stream, "%s\n\tType: %s\n\tLast used: %d\n\tFlags: %s, %s\n" + "\tCreator: %s\n\tLast User: %s\n", + cleankey_str, + switch_cache_db_type_name(dbh->type), + diff, + locked ? "Locked" : "Unlocked", + switch_test_flag(dbh, CDF_INUSE) ? "Attached" : "Detached", dbh->creator, dbh->last_user); } - stream->write_function(stream, "%d total\n", count); + stream->write_function(stream, "%d total. %d in use.\n", count, used); switch_mutex_unlock(sql_manager.dbh_mutex); }