diff --git a/conf/autoload_configs/switch.conf.xml b/conf/autoload_configs/switch.conf.xml
index 4f72c6a65d..d2500a6463 100644
--- a/conf/autoload_configs/switch.conf.xml
+++ b/conf/autoload_configs/switch.conf.xml
@@ -24,6 +24,11 @@
+
+
+
+
+
diff --git a/src/include/private/switch_core_pvt.h b/src/include/private/switch_core_pvt.h
index ab0777ed3b..0ef64d1079 100644
--- a/src/include/private/switch_core_pvt.h
+++ b/src/include/private/switch_core_pvt.h
@@ -249,6 +249,8 @@ struct switch_runtime {
switch_dbtype_t odbc_dbtype;
char hostname[256];
int multiple_registrations;
+ uint32_t max_db_handles;
+ uint32_t db_handle_timeout;
};
extern struct switch_runtime runtime;
diff --git a/src/switch_core.c b/src/switch_core.c
index 50fe313f82..96e4b4ae27 100644
--- a/src/switch_core.c
+++ b/src/switch_core.c
@@ -1283,7 +1283,9 @@ SWITCH_DECLARE(switch_status_t) switch_core_init(switch_core_flag_t flags, switc
memset(&runtime, 0, sizeof(runtime));
gethostname(runtime.hostname, sizeof(runtime.hostname));
-
+ runtime.max_db_handles = 50;
+ runtime.db_handle_timeout = 5000000;;
+
runtime.runlevel++;
runtime.sql_buffer_len = 1024 * 32;
runtime.max_sql_buffer_len = 1024 * 1024;
@@ -1550,6 +1552,23 @@ static void switch_load_core_config(const char *file)
if (tmp > -1 && tmp < 11) {
switch_core_session_ctl(SCSC_DEBUG_LEVEL, &tmp);
}
+ } else if (!strcasecmp(var, "max-db-handles")) {
+ long tmp = atol(val);
+
+ if (tmp > 4 && tmp < 5001) {
+ runtime.max_db_handles = (uint32_t) tmp;
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "max-db-handles must be between 5 and 5000\n");
+ }
+ } else if (!strcasecmp(var, "db-handle-timeout")) {
+ long tmp = atol(val);
+
+ if (tmp > 0 && tmp < 5001) {
+ runtime.db_handle_timeout = (uint32_t) tmp * 1000000;
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "db-handle-timeout must be between 1 and 5000\n");
+ }
+
} else if (!strcasecmp(var, "multiple-registrations")) {
runtime.multiple_registrations = switch_true(val);
} else if (!strcasecmp(var, "sql-buffer-len")) {
diff --git a/src/switch_core_sqldb.c b/src/switch_core_sqldb.c
index 8dbdd44895..a4ed5ca83c 100644
--- a/src/switch_core_sqldb.c
+++ b/src/switch_core_sqldb.c
@@ -66,8 +66,8 @@ static struct {
switch_cache_db_handle_t *handle_pool;
switch_thread_cond_t *cond;
switch_mutex_t *cond_mutex;
- int total_handles;
- int total_used_handles;
+ uint32_t total_handles;
+ uint32_t total_used_handles;
} sql_manager;
@@ -273,11 +273,29 @@ SWITCH_DECLARE(switch_status_t) _switch_cache_db_get_db_handle(switch_cache_db_h
char db_callsite_str[CACHE_DB_LEN] = "";
switch_cache_db_handle_t *new_dbh = NULL;
switch_ssize_t hlen = -1;
+ int waiting = 0;
+ uint32_t yield_len = 100000, total_yield = 0;
const char *db_name = NULL;
const char *db_user = NULL;
const char *db_pass = NULL;
+ while(runtime.max_db_handles && sql_manager.total_handles >= runtime.max_db_handles && sql_manager.total_used_handles >= sql_manager.total_handles) {
+ if (!waiting++) {
+ switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_WARNING, "Max handles %u exceeded, blocking....\n",
+ runtime.max_db_handles);
+ }
+
+ switch_yield(yield_len);
+ total_yield += yield_len;
+
+ if (runtime.db_handle_timeout && total_yield > runtime.db_handle_timeout) {
+ switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_ERROR, "Error connecting\n");
+ *dbh = NULL;
+ return SWITCH_STATUS_FALSE;
+ }
+ }
+
switch (type) {
case SCDB_TYPE_ODBC:
{