char odbc_driver[256];
BOOL is_firebird;
int affected_rows;
+ int num_retries;
};
#endif
new_handle->env = SQL_NULL_HANDLE;
new_handle->state = SWITCH_ODBC_STATE_INIT;
new_handle->affected_rows = 0;
+ new_handle->num_retries = DEFAULT_ODBC_RETRIES;
return new_handle;
return NULL;
}
+SWITCH_DECLARE(void) switch_odbc_set_num_retries(switch_odbc_handle_t *handle, int num_retries)
+{
+#ifdef SWITCH_HAVE_ODBC
+ if (handle) {
+ handle->num_retries = num_retries;
+ }
+#endif
+}
+
SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_handle_disconnect(switch_odbc_handle_t *handle)
{
#ifdef SWITCH_HAVE_ODBC
#ifdef SWITCH_HAVE_ODBC
+static switch_odbc_status_t init_odbc_handles(switch_odbc_handle_t *handle, switch_bool_t do_reinit)
+{
+ int result;
+
+ if (!handle) {
+ return SWITCH_ODBC_FAIL;
+ }
+
+ /* if handle is already initialized, and we're supposed to reinit - free old handle first */
+ if (do_reinit == SWITCH_TRUE && handle->env != SQL_NULL_HANDLE) {
+ SQLFreeHandle(SQL_HANDLE_DBC, handle->con);
+ SQLFreeHandle(SQL_HANDLE_ENV, handle->env);
+ handle->env = SQL_NULL_HANDLE;
+ }
+
+ if (handle->env == SQL_NULL_HANDLE) {
+ result = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &handle->env);
+
+ if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error AllocHandle\n");
+ handle->env = SQL_NULL_HANDLE; /* Reset handle value, just in case */
+ return SWITCH_ODBC_FAIL;
+ }
+
+ result = SQLSetEnvAttr(handle->env, SQL_ATTR_ODBC_VERSION, (void *) SQL_OV_ODBC3, 0);
+
+ if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error SetEnv\n");
+ SQLFreeHandle(SQL_HANDLE_ENV, handle->env);
+ handle->env = SQL_NULL_HANDLE; /* Reset handle value after it's freed */
+ return SWITCH_ODBC_FAIL;
+ }
+
+ result = SQLAllocHandle(SQL_HANDLE_DBC, handle->env, &handle->con);
+
+ if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error AllocHDB %d\n", result);
+ SQLFreeHandle(SQL_HANDLE_ENV, handle->env);
+ handle->env = SQL_NULL_HANDLE; /* Reset handle value after it's freed */
+ return SWITCH_ODBC_FAIL;
+ }
+ SQLSetConnectAttr(handle->con, SQL_LOGIN_TIMEOUT, (SQLPOINTER *) 10, 0);
+ }
+
+ return SWITCH_ODBC_SUCCESS;
+}
+
static int db_is_up(switch_odbc_handle_t *handle)
{
int ret = 0;
switch_odbc_status_t recon = 0;
char *err_str = NULL;
SQLCHAR sql[255] = "";
- int max_tries = 120;
+ int max_tries = DEFAULT_ODBC_RETRIES;
int code = 0;
SQLRETURN rc;
SQLSMALLINT nresultcols;
+ if (handle) {
+ max_tries = handle->num_retries;
+ if (max_tries < 1)
+ max_tries = DEFAULT_ODBC_RETRIES;
+ }
+
top:
if (!handle) {
error:
err_str = switch_odbc_handle_get_error(handle, stmt);
+
+ /* Make sure to free the handle before we try to reconnect */
+ if (stmt) {
+ SQLFreeHandle(SQL_HANDLE_STMT, stmt);
+ stmt = NULL;
+ }
+
recon = switch_odbc_handle_connect(handle);
max_tries--;
goto done;
}
- if (stmt) {
- SQLFreeHandle(SQL_HANDLE_STMT, stmt);
- stmt = NULL;
- }
-
switch_safe_free(err_str);
switch_yield(1000000);
goto top;
SQLSMALLINT valueLength = 0;
int i = 0;
- if (handle->env == SQL_NULL_HANDLE) {
- result = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &handle->env);
+ init_odbc_handles(handle, SWITCH_FALSE); /* Init ODBC handles, if they are already initialized, don't do it again */
- if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error AllocHandle\n");
- return SWITCH_ODBC_FAIL;
- }
-
- result = SQLSetEnvAttr(handle->env, SQL_ATTR_ODBC_VERSION, (void *) SQL_OV_ODBC3, 0);
-
- if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error SetEnv\n");
- SQLFreeHandle(SQL_HANDLE_ENV, handle->env);
- return SWITCH_ODBC_FAIL;
- }
-
- result = SQLAllocHandle(SQL_HANDLE_DBC, handle->env, &handle->con);
-
- if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error AllocHDB %d\n", result);
- SQLFreeHandle(SQL_HANDLE_ENV, handle->env);
- return SWITCH_ODBC_FAIL;
- }
- SQLSetConnectAttr(handle->con, SQL_LOGIN_TIMEOUT, (SQLPOINTER *) 10, 0);
- }
if (handle->state == SWITCH_ODBC_STATE_CONNECTED) {
switch_odbc_handle_disconnect(handle);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Re-connecting %s\n", handle->dsn);
SQLGetDiagRec(SQL_HANDLE_DBC, handle->con, 1, stat, &err, msg, 100, &mlen);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error SQLConnect=%d errno=%d %s\n", result, (int) err, msg);
}
- SQLFreeHandle(SQL_HANDLE_ENV, handle->env);
+
+ /* Deallocate handles again, more chanses to succeed when reconnecting */
+ init_odbc_handles(handle, SWITCH_TRUE); /* Reinit ODBC handles */
return SWITCH_ODBC_FAIL;
}
}
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
+ stmt = NULL; /* Make sure we don't try to free this handle again */
if (!err_cnt) {
return SWITCH_ODBC_SUCCESS;
if (handle) {
switch_odbc_handle_disconnect(handle);
- SQLFreeHandle(SQL_HANDLE_DBC, handle->con);
- SQLFreeHandle(SQL_HANDLE_ENV, handle->env);
+ if (handle->env != SQL_NULL_HANDLE) {
+ SQLFreeHandle(SQL_HANDLE_DBC, handle->con);
+ SQLFreeHandle(SQL_HANDLE_ENV, handle->env);
+ }
switch_safe_free(handle->dsn);
switch_safe_free(handle->username);
switch_safe_free(handle->password);