]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
FS-3106 --comment-only Try this newer refactored version which completely removes...
authorAnthony Minessale <anthm@freeswitch.org>
Thu, 3 Mar 2011 18:54:20 +0000 (12:54 -0600)
committerAnthony Minessale <anthm@freeswitch.org>
Thu, 3 Mar 2011 18:54:20 +0000 (12:54 -0600)
src/include/switch_core.h
src/switch_console.c
src/switch_core_memory.c
src/switch_core_sqldb.c

index 8cf75988e57ff8d9cd81bea784c3aa4a54f8f305..590e01ace27f8d40ea623257a6099d29226a1000 100644 (file)
@@ -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);
index 43a5b17fb648d269b95182e8021af2f997691a71..a73bb58e89836b0b016c6e29f2ad33ed101f94be 100644 (file)
@@ -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 {
index dd87f8f4a248f55789fdff81a92e247707698598..7e6abf9c77c08ad797cf569b17bf167444c0a8e9 100644 (file)
@@ -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
index a0529babf1d96b40b969bced594fe55c7fa74e48..26c8c71711abcb29659ab5a070583f2630a8f4c8 100644 (file)
 #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;
-
-               if ((dbh = (switch_cache_db_handle_t *) val)) {
-                       time_t diff = 0;
+       for (dbh = sql_manager.handle_pool; dbh; dbh = dbh->next) {
+               time_t diff = 0;
 
-                       if (prune > 0 && prune > dbh->last_used) {
-                               diff = (time_t) prune - dbh->last_used;
-                       }
+               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 (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);
+               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;
+                       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;
+                       del_handle(dbh);
+                       switch_mutex_unlock(dbh->mutex);
+                       switch_core_destroy_memory_pool(&dbh->pool);
+                       goto top;
 
-                       } else {
-                               if (!prune)
-                                       locked++;
-                               continue;
+               } 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;
-
-               if ((dbh = (switch_cache_db_handle_t *) val)) {
-                       char *needle = "pass=\"";
-                       time_t diff = 0;
+       for (dbh = sql_manager.handle_pool; dbh; dbh = dbh->next) {
+               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;
-                       }
+               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);
+               /* 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);
 }