Index: configs/res_odbc.conf.sample =================================================================== --- configs/res_odbc.conf.sample (revision 47524) +++ configs/res_odbc.conf.sample (working copy) @@ -15,6 +15,10 @@ ;username => myuser ;password => mypass pre-connect => yes +; What should we execute to ensure that our connection is still alive? The +; statement should return a non-zero value in the first field of its first +; record. The default is "select 1". +;sanitysql => select 1 [mysql2] @@ -35,7 +39,7 @@ username => oscar password => thegrouch pre-connect => yes +sanitysql => select count(*) from systables - Index: res/res_odbc.c =================================================================== --- res/res_odbc.c (revision 47524) +++ res/res_odbc.c (working copy) @@ -60,6 +60,7 @@ char dsn[80]; char username[80]; char password[80]; + char sanitysql[256]; SQLHENV env; unsigned int haspool:1; /* Boolean - TDS databases need this */ unsigned int limit:10; /* Gives a limit of 1023 maximum */ @@ -109,22 +110,18 @@ ast_log(LOG_WARNING, "SQL Execute error %d! Attempting a reconnect...\n", res); SQLFreeHandle(SQL_HANDLE_STMT, stmt); + stmt = NULL; obj->up = 0; /* * While this isn't the best way to try to correct an error, this won't automatically * fail when the statement handle invalidates. */ - /* XXX Actually, it might, if we're using a non-pooled connection. Possible race here. XXX */ - odbc_obj_disconnect(obj); - odbc_obj_connect(obj); + ast_odbc_sanity_check(obj); continue; } break; - } else { - ast_log(LOG_WARNING, "SQL Prepare failed. Attempting a reconnect...\n"); - odbc_obj_disconnect(obj); - odbc_obj_connect(obj); - } + } else if (attempt == 0) + ast_odbc_sanity_check(obj); } return stmt; @@ -178,6 +175,9 @@ SQLHSTMT stmt; int res = 0; + if (obj->parent->sanitysql) + test_sql = obj->parent->sanitysql; + if (obj->up) { res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt); if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { @@ -209,7 +209,7 @@ static char *cfg = "res_odbc.conf"; struct ast_config *config; struct ast_variable *v; - char *cat, *dsn, *username, *password; + char *cat, *dsn, *username, *password, *sanitysql; int enabled, pooling, limit; int connect = 0, res = 0; @@ -228,7 +228,7 @@ } } else { /* Reset all to defaults for each class of odbc connections */ - dsn = username = password = NULL; + dsn = username = password = sanitysql = NULL; enabled = 1; connect = 0; pooling = 0; @@ -257,6 +257,8 @@ username = v->value; } else if (!strcasecmp(v->name, "password")) { password = v->value; + } else if (!strcasecmp(v->name, "sanitysql")) { + sanitysql = v->value; } } @@ -276,6 +278,8 @@ ast_copy_string(new->username, username, sizeof(new->username)); if (password) ast_copy_string(new->password, password, sizeof(new->password)); + if (sanitysql) + ast_copy_string(new->sanitysql, sanitysql, sizeof(new->sanitysql)); SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &new->env); res = SQLSetEnvAttr(new->env, SQL_ATTR_ODBC_VERSION, (void *) SQL_OV_ODBC3, 0); @@ -523,7 +527,7 @@ static char *cfg = "res_odbc.conf"; struct ast_config *config; struct ast_variable *v; - char *cat, *dsn, *username, *password; + char *cat, *dsn, *username, *password, *sanitysql; int enabled, pooling, limit; int connect = 0, res = 0; @@ -546,7 +550,7 @@ } } else { /* Reset all to defaults for each class of odbc connections */ - dsn = username = password = NULL; + dsn = username = password = sanitysql = NULL; enabled = 1; connect = 0; pooling = 0; @@ -574,6 +578,8 @@ username = v->value; } else if (!strcasecmp(v->name, "password")) { password = v->value; + } else if (!strcasecmp(v->name, "sanitysql")) { + sanitysql = v->value; } } @@ -605,6 +611,8 @@ ast_copy_string(new->username, username, sizeof(new->username)); if (password) ast_copy_string(new->password, password, sizeof(new->password)); + if (sanitysql) + ast_copy_string(new->sanitysql, sanitysql, sizeof(new->sanitysql)); if (!class) { SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &new->env);