mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-02 03:02:04 +00:00
res_odbc: cache_size option to limit the cached connections.
Signed-off-by: Jaco Kroon <jaco@uls.co.za> UserNote: New cache_size option for res_odbc to on a per class basis limit the number of cached connections. Please reference the sample configuration for details.
This commit is contained in:
@@ -97,6 +97,18 @@ pre-connect => yes
|
|||||||
; The default remains a stack to be backwards compatible, setting this value to
|
; The default remains a stack to be backwards compatible, setting this value to
|
||||||
; any of rr, roundrobin or queue will result in a round-robin queue being used.
|
; any of rr, roundrobin or queue will result in a round-robin queue being used.
|
||||||
;cache_type => roundrobin
|
;cache_type => roundrobin
|
||||||
|
;
|
||||||
|
; Limit the number of connections to cache. This is separate from
|
||||||
|
; max_connections which is the total number of connections that open, whereas
|
||||||
|
; this value specifies how many idle connections will be stored in the connection
|
||||||
|
; cache. On extremely spiky loads this could be useful to limit the overall
|
||||||
|
; number of connections that's kept open when the spike comes down. The default
|
||||||
|
; is to not limit the cache size (thus effectively limit to max_connections).
|
||||||
|
; When a returned connection would result in the cache size being exceeded, the
|
||||||
|
; longest idle connection in the cache shall be dropped.
|
||||||
|
; Setting this to zero will effectively disable the connection cache, setting to -1
|
||||||
|
; will set this to "infinite" (default).
|
||||||
|
;cache_size => 10
|
||||||
|
|
||||||
[mysql2]
|
[mysql2]
|
||||||
enabled => no
|
enabled => no
|
||||||
|
@@ -101,6 +101,10 @@ struct odbc_class
|
|||||||
char *sql_text;
|
char *sql_text;
|
||||||
/*! Slow query limit (in milliseconds) */
|
/*! Slow query limit (in milliseconds) */
|
||||||
unsigned int slowquerylimit;
|
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;
|
static struct ao2_container *class_container;
|
||||||
@@ -564,6 +568,7 @@ static int load_odbc_config(void)
|
|||||||
struct timeval ncache = { 0, 0 };
|
struct timeval ncache = { 0, 0 };
|
||||||
int preconnect = 0, res = 0, cache_is_queue = 0;
|
int preconnect = 0, res = 0, cache_is_queue = 0;
|
||||||
struct ast_flags config_flags = { 0 };
|
struct ast_flags config_flags = { 0 };
|
||||||
|
unsigned int max_cache_size;
|
||||||
|
|
||||||
struct odbc_class *new;
|
struct odbc_class *new;
|
||||||
|
|
||||||
@@ -591,6 +596,7 @@ static int load_odbc_config(void)
|
|||||||
logging = 0;
|
logging = 0;
|
||||||
slowquerylimit = 5000;
|
slowquerylimit = 5000;
|
||||||
cache_is_queue = 0;
|
cache_is_queue = 0;
|
||||||
|
max_cache_size = UINT_MAX;
|
||||||
for (v = ast_variable_browse(config, cat); v; v = v->next) {
|
for (v = ast_variable_browse(config, cat); v; v = v->next) {
|
||||||
if (!strcasecmp(v->name, "pooling") ||
|
if (!strcasecmp(v->name, "pooling") ||
|
||||||
!strncasecmp(v->name, "share", 5) ||
|
!strncasecmp(v->name, "share", 5) ||
|
||||||
@@ -650,6 +656,12 @@ static int load_odbc_config(void)
|
|||||||
cache_is_queue = !strcasecmp(v->value, "rr") ||
|
cache_is_queue = !strcasecmp(v->value, "rr") ||
|
||||||
!strcasecmp(v->value, "roundrobin") ||
|
!strcasecmp(v->value, "roundrobin") ||
|
||||||
!strcasecmp(v->value, "queue");
|
!strcasecmp(v->value, "queue");
|
||||||
|
} else if (!strcasecmp(v->name, "cache_size")) {
|
||||||
|
if (!strcasecmp(v->value, "-1")) {
|
||||||
|
max_cache_size = UINT_MAX;
|
||||||
|
} else if (sscanf(v->value, "%u", &max_cache_size) != 1) {
|
||||||
|
ast_log(LOG_WARNING, "cache_size must be a non-negative integer or -1 (infinite)\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -679,6 +691,8 @@ static int load_odbc_config(void)
|
|||||||
new->logging = logging;
|
new->logging = logging;
|
||||||
new->slowquerylimit = slowquerylimit;
|
new->slowquerylimit = slowquerylimit;
|
||||||
new->cache_is_queue = cache_is_queue;
|
new->cache_is_queue = cache_is_queue;
|
||||||
|
new->max_cache_size = max_cache_size;
|
||||||
|
new->cur_cache = 0;
|
||||||
|
|
||||||
if (cat)
|
if (cat)
|
||||||
ast_copy_string(new->name, cat, sizeof(new->name));
|
ast_copy_string(new->name, cat, sizeof(new->name));
|
||||||
@@ -766,6 +780,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, " 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 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");
|
ast_cli(a->fd, " Logging: %s\n", class->logging ? "Enabled" : "Disabled");
|
||||||
if (class->logging) {
|
if (class->logging) {
|
||||||
ast_cli(a->fd, " Number of prepares executed: %d\n", class->prepares_executed);
|
ast_cli(a->fd, " Number of prepares executed: %d\n", class->prepares_executed);
|
||||||
@@ -836,6 +852,29 @@ void ast_odbc_release_obj(struct odbc_obj *obj)
|
|||||||
} else {
|
} else {
|
||||||
AST_LIST_INSERT_HEAD(&class->connections, obj, list);
|
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_cond_signal(&class->cond);
|
||||||
ast_mutex_unlock(&class->lock);
|
ast_mutex_unlock(&class->lock);
|
||||||
|
|
||||||
@@ -931,6 +970,9 @@ struct odbc_obj *_ast_odbc_request_obj2(const char *name, struct ast_flags flags
|
|||||||
ast_mutex_lock(&class->lock);
|
ast_mutex_lock(&class->lock);
|
||||||
|
|
||||||
obj = AST_LIST_REMOVE_HEAD(&class->connections, list);
|
obj = AST_LIST_REMOVE_HEAD(&class->connections, list);
|
||||||
|
if (obj) {
|
||||||
|
--class->cur_cache;
|
||||||
|
}
|
||||||
|
|
||||||
ast_mutex_unlock(&class->lock);
|
ast_mutex_unlock(&class->lock);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user