[asterisk-commits] tilghman: branch tilghman/realtime_failover r140668 - in /team/tilghman/realt...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Tue Sep 2 16:50:06 CDT 2008
Author: tilghman
Date: Tue Sep 2 16:50:05 2008
New Revision: 140668
URL: http://svn.digium.com/view/asterisk?view=rev&rev=140668
Log:
Got infrastructure okay, I think
Modified:
team/tilghman/realtime_failover/include/asterisk/res_odbc.h
team/tilghman/realtime_failover/res/res_odbc.c
Modified: team/tilghman/realtime_failover/include/asterisk/res_odbc.h
URL: http://svn.digium.com/view/asterisk/team/tilghman/realtime_failover/include/asterisk/res_odbc.h?view=diff&rev=140668&r1=140667&r2=140668
==============================================================================
--- team/tilghman/realtime_failover/include/asterisk/res_odbc.h (original)
+++ team/tilghman/realtime_failover/include/asterisk/res_odbc.h Tue Sep 2 16:50:05 2008
@@ -50,9 +50,7 @@
AST_LIST_ENTRY(odbc_obj) list;
};
-/*!\brief These aren't used in any API calls, but they are kept in a common
- * location, simply for convenience and to avoid duplication.
- */
+/*!\brief These structures are used for adaptive capabilities */
struct odbc_cache_columns {
char *name;
SQLSMALLINT type;
@@ -96,24 +94,29 @@
/*!
* \brief Retrieves a connected ODBC object
* \param name The name of the ODBC class for which a connection is needed.
- * \param check Whether to ensure that a connection is valid before returning the handle. Usually unnecessary.
+ * \param flags One or more of the following flags:
+ * ODBC_SANITY_CHECK Whether to ensure that a connection is valid before returning the handle. Usually unnecessary.
+ * ODBC_CONNECTED Only return a connected handle. Intended for use with peers which use idlecheck, which are checked periodically for reachability.
* \retval ODBC object
* \retval NULL if there is no connection available with the requested name.
*
* Connection classes may, in fact, contain multiple connection handles. If
* the connection is pooled, then each connection will be dedicated to the
* thread which requests it. Note that all connections should be released
- * when the thread is done by calling odbc_release_obj(), below.
+ * when the thread is done by calling ast_odbc_release_obj(), below.
*/
#ifdef DEBUG_THREADS
-struct odbc_obj *_ast_odbc_request_obj(const char *name, int check, const char *file, const char *function, int lineno);
+struct odbc_obj *_ast_odbc_request_obj(const char *name, int flags, const char *file, const char *function, int lineno);
#define ast_odbc_request_obj(a, b) _ast_odbc_request_obj(a, b, __FILE__, __PRETTY_FUNCTION__, __LINE__)
#else
-struct odbc_obj *ast_odbc_request_obj(const char *name, int check);
+struct odbc_obj *ast_odbc_request_obj(const char *name, int flags);
#endif
+#define ODBC_SANITY_CHECK (1 << 0)
+#define ODBC_CONNECTED (1 << 1)
+
/*!
- * \brief Releases an ODBC object previously allocated by odbc_request_obj()
+ * \brief Releases an ODBC object previously allocated by ast_odbc_request_obj()
* \param obj The ODBC object
*/
void ast_odbc_release_obj(struct odbc_obj *obj);
@@ -158,7 +161,9 @@
* \param table Tablename to describe
* \retval A structure describing the table layout, or NULL, if the table is not found or another error occurs.
* When a structure is returned, the contained columns list will be
- * rdlock'ed, to ensure that it will be retained in memory.
+ * rdlock'ed, to ensure that it will be retained in memory. The information
+ * will be cached until a reload event or when ast_odbc_clear_cache() is called
+ * with the relevant parameters.
*/
struct odbc_cache_tables *ast_odbc_find_table(const char *database, const char *tablename);
@@ -172,6 +177,8 @@
/*!
* \brief Remove a cache entry from memory
+ * This function may be called to clear entries created and cached by the
+ * ast_odbc_find_table() API call.
* \param database Name of an ODBC class (used to ensure like-named tables in different databases are not confused)
* \param table Tablename for which a cached record should be removed
* \retval 0 if the cache entry was removed, or -1 if no matching entry was found.
Modified: team/tilghman/realtime_failover/res/res_odbc.c
URL: http://svn.digium.com/view/asterisk/team/tilghman/realtime_failover/res/res_odbc.c?view=diff&rev=140668&r1=140667&r2=140668
==============================================================================
--- team/tilghman/realtime_failover/res/res_odbc.c (original)
+++ team/tilghman/realtime_failover/res/res_odbc.c Tue Sep 2 16:50:05 2008
@@ -64,6 +64,12 @@
unsigned int limit; /* 1023 wasn't enough for some people */
unsigned int count; /* Running count of pooled connections */
unsigned int idlecheck; /* Recheck the connection if it is idle for this long */
+ unsigned int conntimeout; /* Maximum time the connection process should take */
+ /* When a connection fails, cache that failure for how long? */
+ struct timeval negative_connection_cache;
+ /* When a connection fails, when did that last occur? */
+ struct timeval last_negative_connect;
+ /* List of handles associated with this class */
struct ao2_container *obj_container;
};
@@ -409,7 +415,8 @@
struct ast_variable *v;
char *cat;
const char *dsn, *username, *password, *sanitysql;
- int enabled, pooling, limit, bse;
+ int enabled, pooling, limit, bse, conntimeout;
+ struct timeval ncache;
unsigned int idlecheck;
int preconnect = 0, res = 0;
struct ast_flags config_flags = { 0 };
@@ -469,6 +476,22 @@
sanitysql = v->value;
} else if (!strcasecmp(v->name, "backslash_is_escape")) {
bse = ast_true(v->value);
+ } else if (!strcasecmp(v->name, "connect_timeout")) {
+ if (sscanf(v->value, "%d", &conntimeout) != 1 || conntimeout < 1) {
+ ast_log(LOG_WARNING, "connect_timeout must be a positive integer\n");
+ conntimeout = 10;
+ }
+ } else if (!strcasecmp(v->name, "negative_connection_cache")) {
+ double dncache;
+ if (sscanf(v->value, "%lf", &dncache) != 1 || dncache < 0) {
+ ast_log(LOG_WARNING, "negative_connection_cache must be a non-negative integer\n");
+ /* 5 minutes sounds like a reasonable default */
+ ncache.tv_sec = 300;
+ ncache.tv_usec = 0;
+ } else {
+ ncache.tv_sec = (int)dncache;
+ ncache.tv_usec = (dncache - ncache.tv_sec) * 1000000;
+ }
}
}
@@ -503,6 +526,8 @@
new->backslash_is_escape = bse ? 1 : 0;
new->idlecheck = idlecheck;
+ new->conntimeout = conntimeout;
+ new->negative_connection_cache = ncache;
if (cat)
ast_copy_string(new->name, cat, sizeof(new->name));
@@ -655,9 +680,9 @@
}
#ifdef DEBUG_THREADS
-struct odbc_obj *_ast_odbc_request_obj(const char *name, int check, const char *file, const char *function, int lineno)
+struct odbc_obj *_ast_odbc_request_obj(const char *name, int flags, const char *file, const char *function, int lineno)
#else
-struct odbc_obj *ast_odbc_request_obj(const char *name, int check)
+struct odbc_obj *ast_odbc_request_obj(const char *name, int flags)
#endif
{
struct odbc_obj *obj = NULL;
@@ -687,10 +712,12 @@
ao2_ref(obj, -1);
}
- if (!obj && (class->count < class->limit)) {
+ if (!obj && (class->count < class->limit) &&
+ ast_tvdiff_ms(ast_tvnow(), ast_tvadd(class->last_negative_connect, class->negative_connection_cache)) > 0) {
class->count++;
obj = ao2_alloc(sizeof(*obj), odbc_obj_destructor);
if (!obj) {
+ class->count--;
ao2_ref(class, -1);
return NULL;
}
@@ -735,10 +762,16 @@
}
}
- if (obj && check) {
+ if ((flags & ODBC_CONNECTED) && !obj->up) {
+ /* Check if this connection qualifies for reconnection, with negative connection cache time */
+ if (ast_tvdiff_ms(ast_tvnow(), ast_tvadd(class->last_negative_connect, class->negative_connection_cache)) > 0) {
+ odbc_obj_connect(obj);
+ }
+ } else if (obj && (flags & ODBC_SANITY_CHECK)) {
ast_odbc_sanity_check(obj);
- } else if (obj && obj->parent->idlecheck > 0 && ast_tvdiff_sec(ast_tvnow(), obj->last_used) > obj->parent->idlecheck)
+ } else if (obj && obj->parent->idlecheck > 0 && ast_tvdiff_sec(ast_tvnow(), obj->last_used) > obj->parent->idlecheck) {
odbc_obj_connect(obj);
+ }
#ifdef DEBUG_THREADS
if (obj) {
@@ -796,11 +829,12 @@
if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
ast_log(LOG_WARNING, "res_odbc: Error AllocHDB %d\n", res);
+ obj->last_negative_connect = ast_tvnow();
ast_mutex_unlock(&obj->lock);
return ODBC_FAIL;
}
- SQLSetConnectAttr(obj->con, SQL_LOGIN_TIMEOUT, (SQLPOINTER *) 10, 0);
- SQLSetConnectAttr(obj->con, SQL_ATTR_CONNECTION_TIMEOUT, (SQLPOINTER *) 10, 0);
+ SQLSetConnectAttr(obj->con, SQL_LOGIN_TIMEOUT, (SQLPOINTER *) obj->parent->conntimeout, 0);
+ SQLSetConnectAttr(obj->con, SQL_ATTR_CONNECTION_TIMEOUT, (SQLPOINTER *) obj->parent->conntimeout, 0);
#ifdef NEEDTRACE
SQLSetConnectAttr(obj->con, SQL_ATTR_TRACE, &enable, SQL_IS_INTEGER);
SQLSetConnectAttr(obj->con, SQL_ATTR_TRACEFILE, tracefile, strlen(tracefile));
@@ -820,6 +854,7 @@
if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
SQLGetDiagRec(SQL_HANDLE_DBC, obj->con, 1, state, &err, msg, 100, &mlen);
+ obj->last_negative_connect = ast_tvnow();
ast_mutex_unlock(&obj->lock);
ast_log(LOG_WARNING, "res_odbc: Error SQLConnect=%d errno=%d %s\n", res, (int)err, msg);
return ODBC_FAIL;
More information about the asterisk-commits
mailing list