This commit is contained in:
Anthony Minessale 2011-01-10 11:27:26 -06:00
parent 3f1a7dc5b5
commit 29daaa07b0
2 changed files with 84 additions and 33 deletions

View File

@ -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);

View File

@ -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);