FS-2960
This commit is contained in:
parent
3f1a7dc5b5
commit
29daaa07b0
|
@ -34,6 +34,8 @@
|
|||
|
||||
#include <switch.h>
|
||||
|
||||
#define DEFAULT_ODBC_RETRIES 120
|
||||
|
||||
SWITCH_BEGIN_EXTERN_C struct switch_odbc_handle;
|
||||
typedef void *switch_odbc_statement_handle_t;
|
||||
|
||||
|
@ -50,6 +52,7 @@ typedef enum {
|
|||
} switch_odbc_status_t;
|
||||
|
||||
SWITCH_DECLARE(switch_odbc_handle_t *) switch_odbc_handle_new(const char *dsn, const char *username, const char *password);
|
||||
SWITCH_DECLARE(void) switch_odbc_set_num_retries(switch_odbc_handle_t *handle, int num_retries);
|
||||
SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_handle_disconnect(switch_odbc_handle_t *handle);
|
||||
SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_handle_connect(switch_odbc_handle_t *handle);
|
||||
SWITCH_DECLARE(void) switch_odbc_handle_destroy(switch_odbc_handle_t **handlep);
|
||||
|
|
|
@ -57,6 +57,7 @@ struct switch_odbc_handle {
|
|||
char odbc_driver[256];
|
||||
BOOL is_firebird;
|
||||
int affected_rows;
|
||||
int num_retries;
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -90,6 +91,7 @@ SWITCH_DECLARE(switch_odbc_handle_t *) switch_odbc_handle_new(const char *dsn, c
|
|||
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;
|
||||
|
||||
|
@ -104,6 +106,15 @@ SWITCH_DECLARE(switch_odbc_handle_t *) switch_odbc_handle_new(const char *dsn, c
|
|||
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
|
||||
|
@ -133,6 +144,53 @@ SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_handle_disconnect(switch_odbc_h
|
|||
|
||||
|
||||
#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;
|
||||
|
@ -143,12 +201,18 @@ static int db_is_up(switch_odbc_handle_t *handle)
|
|||
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) {
|
||||
|
@ -199,6 +263,13 @@ static int db_is_up(switch_odbc_handle_t *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--;
|
||||
|
@ -228,11 +299,6 @@ static int db_is_up(switch_odbc_handle_t *handle)
|
|||
goto done;
|
||||
}
|
||||
|
||||
if (stmt) {
|
||||
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
|
||||
stmt = NULL;
|
||||
}
|
||||
|
||||
switch_safe_free(err_str);
|
||||
switch_yield(1000000);
|
||||
goto top;
|
||||
|
@ -274,31 +340,8 @@ SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_handle_connect(switch_odbc_hand
|
|||
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);
|
||||
|
@ -325,7 +368,9 @@ SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_handle_connect(switch_odbc_hand
|
|||
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;
|
||||
}
|
||||
|
||||
|
@ -554,6 +599,7 @@ SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_handle_callback_exec_detailed(c
|
|||
}
|
||||
|
||||
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;
|
||||
|
@ -593,8 +639,10 @@ SWITCH_DECLARE(void) switch_odbc_handle_destroy(switch_odbc_handle_t **handlep)
|
|||
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);
|
||||
|
|
Loading…
Reference in New Issue