[svn-commits] tilghman: trunk r266238 - in /trunk: CHANGES pbx/pbx_realtime.c
SVN commits to the Digium repositories
svn-commits at lists.digium.com
Thu May 27 14:25:19 CDT 2010
Author: tilghman
Date: Thu May 27 14:25:16 2010
New Revision: 266238
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=266238
Log:
Cache query results for one second.
Queries from the PBX core come in 3's. Caching avoids the additional
performance penalty from those two additional queries hitting the database.
(closes issue #16521)
Reported by: tilghman
Patches:
20091229__issue16521.diff.txt uploaded by tilghman (license 14)
Tested by: Hubguru, tilghman
Modified:
trunk/CHANGES
trunk/pbx/pbx_realtime.c
Modified: trunk/CHANGES
URL: http://svnview.digium.com/svn/asterisk/trunk/CHANGES?view=diff&rev=266238&r1=266237&r2=266238
==============================================================================
--- trunk/CHANGES (original)
+++ trunk/CHANGES Thu May 27 14:25:16 2010
@@ -446,6 +446,8 @@
of dynamic parkinglots.
* chan_dahdi now supports reporting alarms over AMI either by channel or span via
the reportalarms config option.
+ * The Realtime dialplan switch now caches entries for 1 second. This provides a
+ significant increase in performance (about 3X) for installations using this switchtype.
CLI Changes
-----------
Modified: trunk/pbx/pbx_realtime.c
URL: http://svnview.digium.com/svn/asterisk/trunk/pbx/pbx_realtime.c?view=diff&rev=266238&r1=266237&r2=266238
==============================================================================
--- trunk/pbx/pbx_realtime.c (original)
+++ trunk/pbx/pbx_realtime.c Thu May 27 14:25:16 2010
@@ -26,6 +26,8 @@
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include <signal.h>
#include "asterisk/file.h"
#include "asterisk/logger.h"
@@ -47,6 +49,7 @@
#include "asterisk/crypto.h"
#include "asterisk/astdb.h"
#include "asterisk/app.h"
+#include "asterisk/astobj2.h"
#define MODE_MATCH 0
#define MODE_MATCHMORE 1
@@ -61,6 +64,80 @@
AST_APP_OPTIONS(switch_opts, {
AST_APP_OPTION('p', OPTION_PATTERNS_DISABLED),
});
+
+struct cache_entry {
+ struct timeval when;
+ struct ast_variable *var;
+ int priority;
+ char *context;
+ char exten[2];
+};
+
+struct ao2_container *cache;
+pthread_t cleanup_thread = 0;
+
+static int cache_hash(const void *obj, const int flags)
+{
+ const struct cache_entry *e = obj;
+ return ast_str_case_hash(e->exten) + e->priority;
+}
+
+static int cache_cmp(void *obj, void *arg, int flags)
+{
+ struct cache_entry *e = obj, *f = arg;
+ return e->priority != f->priority ? 0 :
+ strcmp(e->exten, f->exten) ? 0 :
+ strcmp(e->context, f->context) ? 0 :
+ CMP_MATCH;
+}
+
+static struct ast_variable *dup_vars(struct ast_variable *v)
+{
+ struct ast_variable *new, *list = NULL;
+ for (; v; v = v->next) {
+ if (!(new = ast_variable_new(v->name, v->value, v->file))) {
+ ast_variables_destroy(list);
+ return NULL;
+ }
+ /* Reversed list in cache, but when we duplicate out of the cache,
+ * it's back to correct order. */
+ new->next = list;
+ list = new;
+ }
+ return list;
+}
+
+static void free_entry(void *obj)
+{
+ struct cache_entry *e = obj;
+ ast_variables_destroy(e->var);
+}
+
+static int purge_old_fn(void *obj, void *arg, int flags)
+{
+ struct cache_entry *e = obj;
+ struct timeval *now = arg;
+ return ast_tvdiff_ms(*now, e->when) >= 1000 ? CMP_MATCH : 0;
+}
+
+static void *cleanup(void *unused)
+{
+ struct timespec forever = { 999999999, 0 }, one_second = { 1, 0 };
+ struct timeval now;
+
+ for (;;) {
+ pthread_testcancel();
+ if (ao2_container_count(cache) == 0) {
+ nanosleep(&forever, NULL);
+ }
+ pthread_testcancel();
+ now = ast_tvnow();
+ ao2_callback(cache, OBJ_MULTIPLE | OBJ_UNLINK | OBJ_NODATA, purge_old_fn, &now);
+ pthread_testcancel();
+ nanosleep(&one_second, NULL);
+ }
+}
+
/* Realtime switch looks up extensions in the supplied realtime table.
@@ -141,6 +218,11 @@
char *table;
struct ast_variable *var=NULL;
struct ast_flags flags = { 0, };
+ struct cache_entry *ce;
+ struct {
+ struct cache_entry ce;
+ char exten[AST_MAX_EXTENSION];
+ } cache_search = { { .priority = priority, .context = (char *) context }, };
char *buf = ast_strdupa(data);
if (buf) {
/* "Realtime" prefix is stripped off in the parent engine. The
@@ -158,7 +240,36 @@
if (!ast_strlen_zero(opts)) {
ast_app_parse_options(switch_opts, &flags, NULL, opts);
}
- var = realtime_switch_common(table, ctx, exten, priority, mode, flags);
+ ast_copy_string(cache_search.exten, exten, sizeof(cache_search.exten));
+ if (mode == MODE_MATCH && (ce = ao2_find(cache, &cache_search, OBJ_POINTER))) {
+ var = dup_vars(ce->var);
+ ao2_ref(ce, -1);
+ } else {
+ var = realtime_switch_common(table, ctx, exten, priority, mode, flags);
+ do {
+ struct ast_variable *new;
+ /* Only cache matches */
+ if (mode != MODE_MATCH) {
+ break;
+ }
+ if (!(new = dup_vars(var))) {
+ break;
+ }
+ if (!(ce = ao2_alloc(sizeof(*ce) + strlen(exten) + strlen(context), free_entry))) {
+ ast_variables_destroy(new);
+ break;
+ }
+ ce->context = ce->exten + strlen(exten) + 1;
+ strcpy(ce->exten, exten); /* SAFE */
+ strcpy(ce->context, context); /* SAFE */
+ ce->priority = priority;
+ ce->var = new;
+ ce->when = ast_tvnow();
+ ao2_link(cache, ce);
+ pthread_kill(cleanup_thread, SIGURG);
+ ao2_ref(ce, -1);
+ } while (0);
+ }
}
return var;
}
@@ -283,11 +394,24 @@
static int unload_module(void)
{
ast_unregister_switch(&realtime_switch);
+ pthread_cancel(cleanup_thread);
+ pthread_kill(cleanup_thread, SIGURG);
+ pthread_join(cleanup_thread, NULL);
+ /* Destroy all remaining entries */
+ ao2_ref(cache, -1);
return 0;
}
static int load_module(void)
{
+ if (!(cache = ao2_container_alloc(573, cache_hash, cache_cmp))) {
+ return AST_MODULE_LOAD_FAILURE;
+ }
+
+ if (ast_pthread_create(&cleanup_thread, NULL, cleanup, NULL)) {
+ return AST_MODULE_LOAD_FAILURE;
+ }
+
if (ast_register_switch(&realtime_switch))
return AST_MODULE_LOAD_FAILURE;
return AST_MODULE_LOAD_SUCCESS;
More information about the svn-commits
mailing list