[svn-commits] murf: branch murf/fast-ast r47361 - in /team/murf/fast-ast: include/asterisk/...

svn-commits at lists.digium.com svn-commits at lists.digium.com
Thu Nov 9 06:38:43 MST 2006


Author: murf
Date: Thu Nov  9 07:38:43 2006
New Revision: 47361

URL: http://svn.digium.com/view/asterisk?view=rev&rev=47361
Log:
fixed the small prob last night, committing this so I can merge updates

Modified:
    team/murf/fast-ast/include/asterisk/pbx.h
    team/murf/fast-ast/main/pbx.c

Modified: team/murf/fast-ast/include/asterisk/pbx.h
URL: http://svn.digium.com/view/asterisk/team/murf/fast-ast/include/asterisk/pbx.h?view=diff&rev=47361&r1=47360&r2=47361
==============================================================================
--- team/murf/fast-ast/include/asterisk/pbx.h (original)
+++ team/murf/fast-ast/include/asterisk/pbx.h Thu Nov  9 07:38:43 2006
@@ -63,7 +63,7 @@
 struct ast_sw;
 
 /*! \brief Typedef for devicestate and hint callbacks */
-typedef int (*ast_state_cb_type)(char *context, char* id, enum ast_extension_states state, void *data);
+typedef int (*ast_state_cb_type)(const char *context, char* id, enum ast_extension_states state, void *data);
 
 /*! \brief Data structure associated with a custom dialplan function */
 struct ast_custom_function {

Modified: team/murf/fast-ast/main/pbx.c
URL: http://svn.digium.com/view/asterisk/team/murf/fast-ast/main/pbx.c?view=diff&rev=47361&r1=47360&r2=47361
==============================================================================
--- team/murf/fast-ast/main/pbx.c (original)
+++ team/murf/fast-ast/main/pbx.c Thu Nov  9 07:38:43 2006
@@ -62,6 +62,7 @@
 #include "asterisk/devicestate.h"
 #include "asterisk/stringfields.h"
 #include "hashtab.h"
+#include "stringtab.h"
 
 /*!
  * \note I M P O R T A N T :
@@ -72,16 +73,24 @@
  * of priorities, but a constant search time here would be great ;-)
  *
  * A new algorithm to do searching based on a 'compiled' pattern tree is introduced
- * here, and shows a fairly flat (constant) search time, even for as many as
- * 1000 patterns. Still needs some work-- doesn't handle matchcid yet, but
- * that's no big problem, it will not be difficult to add...
+ * here, and shows a fairly flat (constant) search time, even for over
+ * 1000 patterns. Still needs some work-- there are some fine points of the matching
+ * spec about tie-breaking based on the characters in character sets, but this
+ * should be do-able via the weight system currently being used.
  *
  * Also, using a hash table for context/priority name lookup can help prevent
- * the find_extension routines from absorbing exponential cpu cycles. Right now,
- * I'm using red-black balanced binary trees, log(n) search time.
+ * the find_extension routines from absorbing exponential cpu cycles. I've tested
+ * find_extension with red-black trees, which have O(log2(n)) speed.Right now,
+ * I'm using hash tables, which do searches (ideally) in O(1) time.
  *
  * A simple hack to prevent repetitive calls to find_extension when it isn't
  * necessary has been added.
+ * 
+ * A stringtable (where a buffer is provided to "intern" unique strings, which
+ * are accessed via a hashtable. When all strings are in a stringtable, you can
+ * test for string equality by just matching pointers. This could help in storage
+ * and speed. Might be a better alternative than stringfields in those situations
+ * where the strings are searched.
  *
  */
 
@@ -207,7 +216,7 @@
 	const char *registrar;			/*!< Registrar */
 	AST_LIST_HEAD_NOLOCK(, ast_sw) alts;	/*!< Alternative switches */
 	ast_mutex_t macrolock;			/*!< A lock to implement "exclusive" macros - held whilst a call is executing in the macro */
-	char name[0];				/*!< Name of the context */
+	const char *name;				/*!< Name of the context */
 };
 
 
@@ -291,12 +300,13 @@
 static int hashtab_hash_priority(const void *obj, int mod);
 static int hashtab_hash_labels(const void *obj, int mod);
 
-/* labels, contexts are case sensitive  prioritaahhy numbers are ints */
+/* labels, contexts are case sensitive  priority numbers are ints */
 static int hashtab_compare_contexts(const void *ah_a, const void *ah_b)
 {
 	const struct ast_context *ac = ah_a;
 	const struct ast_context *bc = ah_b;
-	return strcmp(ac->name, bc->name);
+	/* assume context names are registered in a string table! */
+	return ac->name != bc->name;
 }
 
 static int hashtab_compare_extens(const void *ah_a, const void *ah_b)
@@ -317,7 +327,7 @@
 {
 	const struct ast_exten *ac = ah_a;
 	const struct ast_exten *bc = ah_b;
-	return strcmp(ac->label, bc->label);
+	return ac->label != bc->label;
 }
 
 static int hashtab_hash_contexts(const void *obj, int mod)
@@ -567,6 +577,8 @@
 
 static struct ast_context *contexts = NULL;
 static struct ast_hashtab *contexts_tree = NULL;
+static struct ast_strtab *pbx_stringtab = NULL;
+
 
 AST_MUTEX_DEFINE_STATIC(conlock); 		/*!< Lock for the ast_context list */
 
@@ -847,7 +859,7 @@
 
 struct match_char *add_pattern_node(struct ast_context *con, struct match_char *current, char *pattern, int is_pattern, int already, int specificity)
 {
-	struct match_char *m = (struct match_char *)calloc(1,sizeof(struct match_char));
+	struct match_char *m = ast_calloc(1,sizeof(struct match_char));
 	m->x = strdup(pattern);
 	m->is_pattern = is_pattern;
 	if (specificity == 1 && is_pattern && pattern[0] == 'N')
@@ -1257,27 +1269,27 @@
 	return extension_match_core(pattern, data, needmore);
 }
 
-struct fake_context /* this struct is purely for matching in the RB tree */
-{
-	ast_mutex_t lock; 			
-	struct ast_exten *root;		
-	struct ast_hashtab *root_tree;            
-	struct match_char *pattern_tree;       
-	struct ast_context *next;	
-	struct ast_include *includes;		
-	struct ast_ignorepat *ignorepats;	
-	const char *registrar;	
-	AST_LIST_HEAD_NOLOCK(, ast_sw) alts;	
-	ast_mutex_t macrolock;		
-	char name[256];		
-};
-
 struct ast_context *ast_context_find(const char *name)
 {
+	const char *context_name;
 	struct ast_context *tmp = NULL;
-	struct fake_context item;
+	struct ast_context item;
+
+	if (!pbx_stringtab)
+		pbx_stringtab = st_create(2000, 2000, 50, 1); /* case-sensitive hash tree */
+
+	context_name = st_lookup(pbx_stringtab, name);
+	if (!context_name)
+		return NULL;
+	
+	item.name = context_name;
+	
+#ifdef NOTNOW
 	strncpy(item.name,name,256);
+	/* the hash tables will lock for themselves on access */
 	ast_mutex_lock(&conlock);
+#endif
+
 	if( contexts_tree )
 		tmp = ast_hashtab_lookup(contexts_tree,&item);
 #ifdef NOTNOW
@@ -1285,8 +1297,8 @@
 		if (!name || !strcasecmp(name, tmp->name))
 			break;
 	}
+	ast_mutex_unlock(&conlock);
 #endif
-	ast_mutex_unlock(&conlock);
 	return tmp;
 }
 
@@ -1315,7 +1327,7 @@
 	int priority;
 #endif
 
-	char *incstack[AST_PBX_MAX_STACK];      /* filled during the search */
+	const char *incstack[AST_PBX_MAX_STACK];      /* filled during the search */
 	int stacklen;                   /* modified during the search */
 	int status;                     /* set on return */
 	struct ast_switch *swo;         /* set on return */
@@ -1336,7 +1348,7 @@
 	struct ast_exten pattern;
 	struct scoreboard score;
 
-	pattern.label = label;
+	pattern.label = st_insert(pbx_stringtab, label);
 	pattern.priority = priority;
 
 	/* Initialize status if appropriate */
@@ -1359,8 +1371,8 @@
 	if (bypass)	/* bypass means we only look there */
 		tmp = bypass;
 	else {	/* look in contexts */
-		struct fake_context item;
-		strncpy(item.name,context,256);
+		struct ast_context item;
+		item.name = st_insert(pbx_stringtab, context);
 		tmp = ast_hashtab_lookup(contexts_tree,&item);
 #ifdef NOTNOW
 		tmp = NULL;
@@ -1493,6 +1505,10 @@
 			return NULL;
 		}
 	}
+
+	/* if we are exceedingly smart, we will just include all the extensions in included contexts in the base
+	   context_match tree, and match in a single pass, and get rid of this code... */
+
 	q->incstack[q->stacklen++] = tmp->name;	/* Setup the stack */
 	/* Now try any includes we have in this context */
 	for (i = tmp->includes; i; i = i->next) {
@@ -2964,7 +2980,10 @@
 {
 	if (e->priority == PRIORITY_HINT)
 		ast_remove_hint(e);
-
+	if (e->peer_tree)
+		ast_hashtab_destroy(e->peer_tree);
+	if (e->peer_label_tree)
+		ast_hashtab_destroy(e->peer_label_tree);
 	if (e->datad)
 		e->datad(e->data);
 	free(e);
@@ -3045,8 +3064,8 @@
 static struct ast_context *find_context_locked(const char *context)
 {
 	struct ast_context *c = NULL;
-	struct fake_context item;
-	strncpy(item.name, context, 256);
+	struct ast_context item;
+	item.name = st_insert(pbx_stringtab, context);
 	ast_lock_contexts();
 	c = ast_hashtab_lookup(contexts_tree,&item);
 #ifdef NOTNOW
@@ -3273,8 +3292,8 @@
 {
 	struct ast_context *c = NULL;
 	int ret = -1;
-	struct fake_context item;
-	strncpy(item.name,context,256);
+	struct ast_context item;
+	item.name = st_insert(pbx_stringtab, context);
 	ast_lock_contexts();
 	c = ast_hashtab_lookup(contexts_tree,&item);
 	if (c)
@@ -3308,8 +3327,8 @@
 {
 	struct ast_context *c = NULL;
 	int ret = -1;
-	struct fake_context item;
-	strncpy(item.name, context, 256);
+	struct ast_context item;
+	item.name = st_insert(pbx_stringtab, context);
 
 	ast_lock_contexts();
 
@@ -4293,21 +4312,36 @@
 static struct ast_context *__ast_context_create(struct ast_context **extcontexts, const char *name, const char *registrar, int existsokay)
 {
 	struct ast_context *tmp, **local_contexts;
+	struct ast_context search;
 	int length = sizeof(struct ast_context) + strlen(name) + 1;
+	const char *context_name;
+
+	if (!contexts_tree)
+		contexts_tree = ast_hashtab_create(17,
+										   hashtab_compare_contexts, 
+										   ast_hashtab_resize_java,
+										   ast_hashtab_newsize_java,
+										   hashtab_hash_contexts,
+										   1);
+	if (!pbx_stringtab)
+		pbx_stringtab = st_create(2000, 2000, 50, 1); /* case-sensitive hash tree */
+
+	context_name = st_insert(pbx_stringtab, name);
+	search.name = context_name;
+	tmp = ast_hashtab_lookup(contexts_tree, &search);
+	
+	if (!existsokay && tmp) {
+		ast_log(LOG_WARNING, "Tried to register context '%s', already in use\n", name);
+		return tmp;
+	}
 
 	if (!extcontexts) {
 		ast_mutex_lock(&conlock);
 		local_contexts = &contexts;
-		if (!contexts_tree)
-			contexts_tree = ast_hashtab_create(17,
-							hashtab_compare_contexts, 
-							ast_hashtab_resize_java,
-							ast_hashtab_newsize_java,
-							hashtab_hash_contexts,
-							1);
 	} else
 		local_contexts = extcontexts;
 
+#ifdef NO_MORE	
 	for (tmp = *local_contexts; tmp; tmp = tmp->next) {
 		if (!strcasecmp(tmp->name, name)) {
 			if (!existsokay) {
@@ -4319,10 +4353,13 @@
 			return tmp;
 		}
 	}
+#endif
+
 	if ((tmp = ast_calloc(1, length))) {
 		ast_mutex_init(&tmp->lock);
 		ast_mutex_init(&tmp->macrolock);
-		strcpy(tmp->name, name);
+		/* strcpy(tmp->name, name); */
+		tmp->name = context_name;
 		tmp->root = NULL;
 		tmp->root_tree = NULL;
 		tmp->registrar = registrar;
@@ -5271,8 +5308,10 @@
 	length = sizeof(struct ast_exten);
 	length += strlen(extension) + 1;
 	length += strlen(application) + 1;
+#ifdef NOMORE
 	if (label)
 		length += strlen(label) + 1;
+#endif
 	if (callerid)
 		length += strlen(callerid) + 1;
 	else
@@ -5284,13 +5323,11 @@
 	if (!(tmp = ast_calloc(1, length)))
 		return -1;
 
+	if (label) {
+		tmp->label = st_insert(pbx_stringtab, label);
+	}
 	/* use p as dst in assignments, as the fields are const char * */
 	p = tmp->stuff;
-	if (label) {
-		tmp->label = p;
-		strcpy(p, label);
-		p += strlen(label) + 1;
-	}
 	tmp->exten = p;
 	p += ext_strncpy(p, extension, strlen(extension) + 1) + 1;
 	tmp->priority = priority;
@@ -5840,6 +5877,8 @@
 		ast_mutex_lock(&tmp->lock);
 		if (option_debug)
 			ast_log(LOG_DEBUG, "delete ctx %s %s\n", tmp->name, tmp->registrar);
+		ast_hashtab_remove_this_object(contexts_tree,tmp);
+		
 		next = tmp->next;
 		if (tmpl)
 			tmpl->next = next;



More information about the svn-commits mailing list