@ -101,6 +101,10 @@ struct odbc_class
char * sql_text ;
/*! Slow query limit (in milliseconds) */
unsigned int slowquerylimit ;
/*! Maximum number of cached connections, default is maxconnections */
unsigned int max_cache_size ;
/*! Current cached connection count, when cache_size will exceed max_cache_size, longest-idle connection will be dropped from the cache */
unsigned int cur_cache ;
} ;
static struct ao2_container * class_container ;
@ -564,6 +568,7 @@ static int load_odbc_config(void)
struct timeval ncache = { 0 , 0 } ;
int preconnect = 0 , res = 0 , cache_is_queue = 0 ;
struct ast_flags config_flags = { 0 } ;
unsigned int max_cache_size ;
struct odbc_class * new ;
@ -591,6 +596,7 @@ static int load_odbc_config(void)
logging = 0 ;
slowquerylimit = 5000 ;
cache_is_queue = 0 ;
max_cache_size = UINT_MAX ;
for ( v = ast_variable_browse ( config , cat ) ; v ; v = v - > next ) {
if ( ! strcasecmp ( v - > name , " pooling " ) | |
! strncasecmp ( v - > name , " share " , 5 ) | |
@ -650,6 +656,10 @@ static int load_odbc_config(void)
cache_is_queue = ! strcasecmp ( v - > value , " rr " ) | |
! strcasecmp ( v - > value , " roundrobin " ) | |
! strcasecmp ( v - > value , " queue " ) ;
} else if ( ! strcasecmp ( v - > name , " cache_size " ) ) {
if ( sscanf ( v - > value , " %u " , & max_cache_size ) ! = 1 ) {
ast_log ( LOG_WARNING , " cache_size must be a non-negative integer \n " ) ;
}
}
}
@ -679,6 +689,8 @@ static int load_odbc_config(void)
new - > logging = logging ;
new - > slowquerylimit = slowquerylimit ;
new - > cache_is_queue = cache_is_queue ;
new - > max_cache_size = max_cache_size ;
new - > cur_cache = 0 ;
if ( cat )
ast_copy_string ( new - > name , cat , sizeof ( new - > name ) ) ;
@ -766,6 +778,8 @@ static char *handle_cli_odbc_show(struct ast_cli_entry *e, int cmd, struct ast_c
ast_cli ( a - > fd , " Number of active connections: %zd (out of %d) \n " , class - > connection_cnt , class - > maxconnections ) ;
ast_cli ( a - > fd , " Cache Type: %s \n " , class - > cache_is_queue ? " round-robin queue " : " stack (last release, first re-use) " ) ;
ast_cli ( a - > fd , " Cache Usage: %u cached out of %u \n " , class - > cur_cache ,
class - > max_cache_size < class - > maxconnections ? class - > max_cache_size : class - > maxconnections ) ;
ast_cli ( a - > fd , " Logging: %s \n " , class - > logging ? " Enabled " : " Disabled " ) ;
if ( class - > logging ) {
ast_cli ( a - > fd , " Number of prepares executed: %d \n " , class - > prepares_executed ) ;
@ -836,6 +850,28 @@ void ast_odbc_release_obj(struct odbc_obj *obj)
} else {
AST_LIST_INSERT_HEAD ( & class - > connections , obj , list ) ;
}
if ( class - > cur_cache > = class - > max_cache_size ) {
/* cache is full */
if ( class - > cache_is_queue ) {
/* HEAD will be oldest */
obj = AST_LIST_REMOVE_HEAD ( & class - > connections , list ) ;
} else {
/* TAIL will be oldest */
obj = AST_LIST_LAST ( & class - > connections ) ;
AST_LIST_REMOVE ( & class - > connections , obj , list ) ;
}
- - class - > connection_cnt ;
ast_mutex_unlock ( & class - > lock ) ;
ast_debug ( 2 , " ODBC Pool '%s' exceeded cache size, dropping '%p', connection count is %zd (%u cached) \n " ,
class - > name , obj , class - > connection_cnt , class - > cur_cache ) ;
ao2_ref ( obj , - 1 ) ;
ast_mutex_lock ( & class - > lock ) ;
} else
+ + class - > cur_cache ;
ast_cond_signal ( & class - > cond ) ;
ast_mutex_unlock ( & class - > lock ) ;
@ -931,6 +967,8 @@ struct odbc_obj *_ast_odbc_request_obj2(const char *name, struct ast_flags flags
ast_mutex_lock ( & class - > lock ) ;
obj = AST_LIST_REMOVE_HEAD ( & class - > connections , list ) ;
if ( obj )
- - class - > cur_cache ;
ast_mutex_unlock ( & class - > lock ) ;