[asterisk-commits] murf: branch murf/fast-ast r47188 - /team/murf/fast-ast/main/

asterisk-commits at lists.digium.com asterisk-commits at lists.digium.com
Fri Nov 3 21:47:46 MST 2006


Author: murf
Date: Fri Nov  3 22:47:45 2006
New Revision: 47188

URL: http://svn.digium.com/view/asterisk?rev=47188&view=rev
Log:
added my own hash and string tables, a test program, and modified pbx.c to use the hashtab instead of the threaded rb trees. There. now it's independantly testable.

Added:
    team/murf/fast-ast/main/hashtab.c   (with props)
    team/murf/fast-ast/main/hashtab.h   (with props)
    team/murf/fast-ast/main/stringtab.c   (with props)
    team/murf/fast-ast/main/stringtab.h   (with props)
    team/murf/fast-ast/main/test-hashtab.c   (with props)
Modified:
    team/murf/fast-ast/main/Makefile
    team/murf/fast-ast/main/manager.c
    team/murf/fast-ast/main/pbx.c

Modified: team/murf/fast-ast/main/Makefile
URL: http://svn.digium.com/view/asterisk/team/murf/fast-ast/main/Makefile?rev=47188&r1=47187&r2=47188&view=diff
==============================================================================
--- team/murf/fast-ast/main/Makefile (original)
+++ team/murf/fast-ast/main/Makefile Fri Nov  3 22:47:45 2006
@@ -26,7 +26,7 @@
 	utils.o plc.o jitterbuf.o dnsmgr.o devicestate.o \
 	netsock.o slinfactory.o ast_expr2.o ast_expr2f.o \
 	cryptostub.o sha1.o http.o fixedjitterbuf.o abstract_jb.o \
-	strcompat.o trb.o
+	strcompat.o trb.o stringtab.o hashtab.o
 
 # we need to link in the objects statically, not as a library, because
 # otherwise modules will not have them available if none of the static

Added: team/murf/fast-ast/main/hashtab.c
URL: http://svn.digium.com/view/asterisk/team/murf/fast-ast/main/hashtab.c?rev=47188&view=auto
==============================================================================
--- team/murf/fast-ast/main/hashtab.c (added)
+++ team/murf/fast-ast/main/hashtab.c Fri Nov  3 22:47:45 2006
@@ -1,0 +1,452 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 1999 - 2006, Digium, Inc.
+ *
+ * Steve Murphy <murf at digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <stddef.h>
+
+#include "hashtab.h"
+
+
+/* some standard, default routines for general use */
+
+int ast_hashtab_compare_strings(const void *a, const void *b)
+{
+	return strcmp((char*)a,(char*)b);
+}
+
+int ast_hashtab_compare_strings_nocase(const void *a, const void *b)
+{
+	return strcasecmp((const char*)a,(const char*)b);
+}
+
+int ast_hashtab_compare_ints(const void *a, const void *b)
+{
+	int ai = *((int*)a);
+	int bi = *((int*)b);
+	if (ai < bi)
+		return -1;
+	else if (ai==bi)
+		return 0;
+	else
+		return 1;
+}
+
+int ast_hashtab_compare_shorts(const void *a, const void *b)
+{
+	short as = *((short*)a);
+	short bs = *((short*)b);
+	if (as < bs)
+		return -1;
+	else if (as==bs)
+		return 0;
+	else
+		return 1;
+}
+
+int ast_hashtab_resize_java(struct ast_hashtab *tab)
+{
+	double loadfactor = (double)tab->hash_tab_elements / (double)tab->hash_tab_size;
+	if (loadfactor > 0.75)
+		return 1;
+	return 0;
+}
+
+int ast_hashtab_resize_tight(struct ast_hashtab *tab)
+{
+	double loadfactor = (double)tab->hash_tab_elements / (double)tab->hash_tab_size;
+	if (loadfactor > 1.0)
+		return 1;
+	return 0;
+}
+
+int isPrime(int num)
+{
+	int tnum,limit;
+	    
+	if ((num & 0x1) == 0) /* even number -- not prime */
+		return 0;
+		    
+    	/* Loop through ODD numbers starting with 3 */
+
+	tnum = 3;
+	limit = num;
+	while (tnum < limit)
+	{
+		if ((num%tnum) == 0) {
+			return 0;
+		}
+		/* really, we only need to check sqrt(num) numbers */
+		limit = num / tnum;
+		/* we only check odd numbers */
+		tnum = tnum+2;
+	}
+	/* if we made it thru the loop, the number is a prime */
+	return 1;
+}
+
+int ast_hashtab_newsize_java(struct ast_hashtab *tab)
+{
+	int i = (tab->hash_tab_size<<1); /* multiply by two */
+	while (!isPrime(i))
+		i++;
+	printf("newsize: chose %d\n", i);
+	return i;
+}
+
+int ast_hashtab_newsize_tight(struct ast_hashtab *tab)
+{
+	int i = (tab->hash_tab_size<<1); /* multiply by two */
+	while (!isPrime(i))
+		i++;
+	return i;
+}
+
+int ast_hashtab_hash_string(const void *obj, int modulus)
+{
+	unsigned char *str = (unsigned char*)obj;
+	unsigned int total;
+
+	for (total=0; *str; str++)
+	{
+		unsigned int tmp = total;
+		total <<= 1; /* multiply by 2 */
+		total += tmp; /* multiply by 3 */
+		total <<= 2; /* multiply by 12 */
+		total += tmp; /* multiply by 13 */
+		
+		total += ((unsigned int)(*str));
+	}
+	return (total % modulus);
+}
+
+int ast_hashtab_hash_string_nocase(const void *obj, int modulus)
+{
+	unsigned char *str = (unsigned char*)obj;
+	unsigned int total;
+
+	for (total=0; *str; str++)
+	{
+		unsigned int tmp = total;
+		unsigned int charval = toupper(*str);
+
+		/* hopefully, the following is faster than multiplication by 7 */
+		total <<= 1; /* multiply by 2 */
+		total += tmp; /* multiply by 3 */
+		total <<= 2; /* multiply by 12 */
+		total += tmp; /* multiply by 13 */
+		
+		total += (charval);
+	}
+	return (total % modulus);
+}
+
+int ast_hashtab_hash_int(const int x, int modulus)
+{
+	return (x % modulus);
+}
+
+int ast_hashtab_hash_short(const short x, int modulus)
+{
+	/* hmmmm.... modulus is best < 65535 !! */
+	return (x % modulus);
+}
+
+struct ast_hashtab * ast_hashtab_create(int initial_buckets,
+										int (*compare)(const void *a, const void *b), /* a func to compare two elements in the hash -- cannot be null  */
+										int (*resize)(struct ast_hashtab *), /* a func to decide if the table needs to be resized, a NULL ptr here will cause a default to be used */
+										int (*newsize)(struct ast_hashtab *tab), /* a ptr to func that returns a new size of the array. A NULL will cause a default to be used */
+										int (*hash)(const void *obj, int modulus), /* a func to do the hashing */
+										int do_locking ) /* use locks to guarantee safety of iterators/insertion/deletion */
+{
+	struct ast_hashtab *ht = (struct ast_hashtab *)calloc(1,sizeof(struct ast_hashtab));
+	ht->array = (struct ast_hashtab_bucket **)calloc(initial_buckets,sizeof(struct ast_hashtab_bucket*));
+	while (!isPrime(initial_buckets)) /* make sure this is prime */
+		initial_buckets++;
+	ht->hash_tab_size = initial_buckets;
+	ht->compare = compare;
+	ht->resize = resize;
+	ht->newsize = newsize;
+	ht->hash = hash;
+	ht->do_locking = do_locking;
+	if (!ht->resize)
+		ht->resize = ast_hashtab_resize_java;
+	if (!ht->newsize)
+		ht->newsize = ast_hashtab_newsize_java;
+	return ht;
+}
+
+void ast_hashtab_destroy( struct ast_hashtab *tab)
+{
+	/* this func will free the hash table and all its memory. It
+	   doesn't touch the objects stored in it */
+	if (tab) {
+		
+		if (tab->array) {
+			/* go thru and destroy the buckets */
+			int i;
+			for (i=0;i<tab->hash_tab_size;i++) {
+				struct ast_hashtab_bucket *b = tab->array[i];
+				struct ast_hashtab_bucket *N;
+				while (b) {
+					N = b->next;
+					b->next = 0; /* don't leave dead pointers laying about */
+					free(b);
+					b = N;
+				}
+				tab->array[i] = 0; /* don't leave dead pointers laying about */
+			}
+			
+			free(tab->array);
+		}
+		free(tab);
+	}
+}
+
+int ast_hashtab_insert_immediate(struct ast_hashtab *tab, void *obj)
+{
+	/* normally, you'd insert "safely" by checking to see if the element is
+	   already there; in this case, you must already have checked. If an element
+	   is already in the hashtable, that matches this one, most likely this one
+	   will be found first, but.... */
+
+	/* will force a resize if the resize func returns 1 */
+	/* returns 1 on success, 0 if there's a problem */
+	int h;
+	int c;
+	struct ast_hashtab_bucket *b;
+	
+	if (!tab || !obj)
+		return 0;
+	h = (*tab->hash)(obj, tab->hash_tab_size);
+	for (c=0,b=tab->array[h];b;b=b->next) {
+		c++;
+	}
+	if (c+1 > tab->largest_bucket_size)
+		tab->largest_bucket_size = c+1;
+	b = (struct ast_hashtab_bucket*)malloc(sizeof(struct ast_hashtab_bucket));
+	b->object = obj;
+	b->next = tab->array[h];
+	tab->array[h] = b;
+	tab->hash_tab_elements++;
+	if ((*tab->resize)(tab))
+		ast_hashtab_resize(tab);
+	return 1;
+}
+
+int ast_hashtab_insert_safe(struct ast_hashtab *tab, void *obj)
+{
+	/* check to see if the element is already there; insert only if
+	   it is not there. */
+	/* will force a resize if the resize func returns 1 */
+	/* returns 1 on success, 0 if there's a problem, or it's already there. */
+	if (ast_hashtab_lookup(tab,obj) == 0)
+	{
+		return ast_hashtab_insert_immediate(tab,obj);
+	}
+	return 0;
+}
+
+void * ast_hashtab_lookup(struct ast_hashtab *tab, void *obj)
+{
+	/* lookup this object in the hash table. return a ptr if found, or NULL if not */
+	int h;
+	struct ast_hashtab_bucket *b;
+	if (!tab || !obj)
+		return 0;
+	h = (*tab->hash)(obj, tab->hash_tab_size);
+	for(b=tab->array[h]; b; b=b->next)
+	{
+		if( (*tab->compare)(obj,b->object) == 0 )
+			return b->object;
+	}
+	return 0;
+}
+
+void ast_hashtab_get_stats( struct ast_hashtab *tab, int *biggest_bucket_size, int *resize_count, int *num_objects, int *num_buckets)
+{
+	/* returns key stats for the table */
+	*biggest_bucket_size = tab->largest_bucket_size;
+	*resize_count = tab->resize_count;
+	*num_objects = tab->hash_tab_elements;
+	*num_buckets = tab->hash_tab_size;
+}
+
+void ast_hashtab_resize( struct ast_hashtab *tab)
+{
+	/* this function is called either internally, when the resize func returns 1, or
+	   externally by the user to force a resize of the hash table */
+	int newsize = (*tab->newsize)(tab), i, h,c;
+	struct ast_hashtab_bucket *list = 0, *b,*bn;
+	
+	/* there's two ways to do this: 
+	   1. allocate a new array, and move the elements into it from the old table directly, then
+	      free the old table. faster, requires more mem.
+	   2. relink the buckets into a single long chain; free the old array. Then, allocate the
+          new table, and move the buckets in. slower, minimal mem requirements. 
+	*/
+	for (i=0;i<tab->hash_tab_size;i++) {
+		for (b=tab->array[i]; b; b=bn) {
+			bn = b->next;
+			b->next = list;
+			list = b;
+		}
+		tab->array[i] = 0; /* erase old ptrs */
+	}
+	free(tab->array);
+	tab->array = (struct ast_hashtab_bucket **)calloc(newsize,sizeof(struct ast_hashtab_bucket *));
+	/* now sort the buckets into their rightful new slots */
+	tab->resize_count++;
+	tab->hash_tab_size = newsize;
+	tab->largest_bucket_size = 0;
+
+	for (b=list;b;b=bn)
+	{
+		bn = b->next;
+		h = (*tab->hash)(b->object, tab->hash_tab_size);
+		b->next = tab->array[h];
+		tab->array[h] = b;
+	}
+	list = 0;
+	/* recalc the largest bucket size */
+	for (i=0;i<tab->hash_tab_size;i++) {
+		c=0;
+		for (b=tab->array[i]; b; b=b->next) {
+			c++;
+		}
+		if( c > tab->largest_bucket_size )
+			tab->largest_bucket_size = c;
+	}
+}
+
+struct ast_hashtab_iter *ast_hashtab_start_traversal(struct ast_hashtab *tab)
+{
+	/* returns an iterator */
+	struct ast_hashtab_iter *it = (struct ast_hashtab_iter *)malloc(sizeof(struct ast_hashtab_iter));
+	it->bucket_num = 0;
+	
+	it->curr = tab->array[0];
+	it->tab = tab;
+	return it;
+}
+
+void *ast_hashtab_next(struct ast_hashtab_iter *it)
+{
+	/* returns the next object in the list, advances iter one step */
+	int num;
+
+	
+	if( it->curr && it->curr->next )  /* there's a next in the bucket list */
+	{
+		it->curr = it->curr->next;
+		return it->curr->object;
+	} else if( !it->curr && it->bucket_num == 0 ){ /* first call to this */
+		for(num=it->bucket_num; num<it->tab->hash_tab_size; num++)
+		{
+			if (it->tab->array[num]) {
+				it->bucket_num = num;
+				it->curr = it->tab->array[num];
+				return it->curr->object;
+			} else {
+				continue; /* try the next bucket */
+			}
+			return 0; /* nothing in the whole table! */
+		}
+	} else if (it->curr && !it->curr->next) {  /* end of a bucket chain */
+		it->bucket_num++;
+		for(num=it->bucket_num; num<it->tab->hash_tab_size; num++)
+		{
+			if (it->tab->array[num]) {
+				it->bucket_num = num;
+				it->curr = it->tab->array[num];
+				return it->curr->object;
+			} else {
+				continue; /* try the next bucket */
+			}
+			return 0; /* nothing in the whole table! */
+		}
+		
+	} else if (!it->curr && it->bucket_num != 0 ) { /* call me again, after the list is traversed? */
+		return 0;
+	}
+	
+	return 0;
+}
+
+void *ast_hashtab_remove_object_via_lookup(struct ast_hashtab *tab, void *obj)
+{
+	/* looks up the object; removes the corresponding bucket */
+	int h;
+	struct ast_hashtab_bucket *b,*last;
+
+	if (!tab || !obj)
+		return 0;
+
+	last = 0;
+	h = (*tab->hash)(obj, tab->hash_tab_size);
+	for(b=tab->array[h]; b; b=b->next)
+	{
+		void *obj2;
+		
+		if ((*tab->compare)(obj,b->object) == 0) {
+			if (last)
+				last->next = b->next;
+			else
+				tab->array[h] = b->next;
+			obj2 = b->object;
+			b->object = b->next = 0;
+			free(b); /* free up the hashbucket */
+			return obj2;
+		}
+		last = b;
+	}
+	return 0;
+}
+
+void *ast_hashtab_remove_this_object(struct ast_hashtab *tab, void *obj)
+{
+	/* looks up the object by hash and then comparing pts in bucket list instead of
+	   calling the compare routine; removes the bucket -- a slightly cheaper operation */
+	/* looks up the object; removes the corresponding bucket */
+	int h;
+	struct ast_hashtab_bucket *b,*last;
+
+	if (!tab || !obj)
+		return 0;
+
+	last = 0;
+	h = (*tab->hash)(obj, tab->hash_tab_size);
+	for (b=tab->array[h]; b; b=b->next)
+	{
+		void *obj2;
+		
+		if (obj == b->object) {
+			if (last)
+				last->next = b->next;
+			else
+				tab->array[h] = b->next;
+			obj2 = b->object;
+			b->object = b->next = 0;
+			free(b); /* free up the hashbucket */
+			return obj2;
+		}
+		last = b;
+	}
+	return 0;
+}

Propchange: team/murf/fast-ast/main/hashtab.c
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: team/murf/fast-ast/main/hashtab.c
------------------------------------------------------------------------------
    svn:keywords = Author Id Date Revision

Propchange: team/murf/fast-ast/main/hashtab.c
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: team/murf/fast-ast/main/hashtab.h
URL: http://svn.digium.com/view/asterisk/team/murf/fast-ast/main/hashtab.h?rev=47188&view=auto
==============================================================================
--- team/murf/fast-ast/main/hashtab.h (added)
+++ team/murf/fast-ast/main/hashtab.h Fri Nov  3 22:47:45 2006
@@ -1,0 +1,191 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 1999 - 2006, Digium, Inc.
+ *
+ * Steve Murphy <murf at digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+#ifndef _ASTERISK_HASHTAB_H_
+#define _ASTERISK_HASHTAB_H_
+
+/* generic (perhaps overly so) hashtable implementation */
+
+/* notes:
+
+A hash table is a structure that allows for an exact-match search
+in O(1) (or close to that) time.
+
+The method: given: a set of {key,val} pairs. (at a minimum).
+            given: a hash function, which, given a the key,
+            will return an integer. Ideally, each key in the
+            set will have its own unique associated hash value.
+			This hash number will index into an array. "buckets"
+            are what the elements of this array are called. To
+            handle possible collisions in hash values, buckets can form a list.
+
+The key for a value must be contained in the value, or we won't
+be able to find it in the bucket list.
+
+This implementation is pretty generic, because:
+ 1. The value and key are expected to be in a structure
+    (along with other data, perhaps) and it's address is a "void *".
+ 2. The pointer to a compare function must be passed in at the
+    time of creation, and is stored in the hashtable.
+ 3. The pointer to a resize function, which returns 1 if the
+    hash table is to be grown. A default routine is provided
+    if the pointer is NULL, and uses the java hashtable metric
+    of a 75% load factor.
+ 4. The pointer to a "new size" function, which returns a preferable
+    new size for the hash table bucket array. By default, a function
+    is supplied which roughly doubles the size of the array, is provided.
+    This size should ideally be a prime number.
+ 5. The hashing function pointer must also be supplied. This function
+    must be written by the user to access the keys in the objects being
+    stored. Some helper functions that use a simple "mult by prime, add
+    the next char", sort of string hash, or a simple modulus of the hash
+    table size for ints, is provided; the user can use these simple
+    algorithms to generate a hash, or implement any other algorithms they
+    wish.
+*/
+
+struct ast_hashtab_bucket
+{
+	void *object;                    /* whatever it is we are storing in this table */
+	struct ast_hashtab_bucket *next; /* a simple LL of buckets in hash collision */
+};
+
+struct ast_hashtab
+{
+	struct ast_hashtab_bucket **array;
+	int (*compare) (const void *a, const void *b);            /* a ptr to func that returns int, and take two void* ptrs, compares them, 
+													 rets -1 if a < b; rets 0 if a==b; rets 1 if a>b */
+	int (*newsize) (struct ast_hashtab *tab);     /* a ptr to func that returns int, a new size for hash tab, based on curr_size */
+	int (*resize) (struct ast_hashtab *tab);      /* a function to decide whether this hashtable should be resized now */
+	int (*hash) (const void *obj, int modulus);         /* a hash func ptr for this table. Given a raw ptr to an obj, 
+													 it calcs a hash. The modulus will be the hashtab size */
+	int hash_tab_size;                            /* the size of the bucket array */
+	int hash_tab_elements;                        /* the number of objects currently stored in the table */
+	int largest_bucket_size;                      /* a stat on the health of the table */
+	int resize_count;                             /* a count of the number of times this table has been
+													 resized */
+	int do_locking;                               /* if 1, use locks to guarantee safety of insertions/deletions */
+	/* this spot reserved for the proper lock storage */
+};
+
+struct ast_hashtab_iter              /* an iterator for traversing the buckets */
+{
+	struct ast_hashtab *tab;
+	int bucket_num;
+	struct ast_hashtab_bucket *curr;
+};
+
+
+/* some standard, default routines for general use */
+
+int isPrime(int num); /* this one is handy for sizing the hash table, tells if num is prime or not */
+
+int ast_hashtab_compare_strings(const void *a, const void *b);
+
+
+int ast_hashtab_compare_strings_nocase(const void *a, const void *b);
+
+
+int ast_hashtab_compare_ints(const void *a, const void *b);
+
+
+int ast_hashtab_compare_shorts(const void *a, const void *b);
+
+
+int ast_hashtab_resize_java(struct ast_hashtab *tab);
+
+
+int ast_hashtab_resize_tight(struct ast_hashtab *tab);
+
+
+int ast_hashtab_newsize_java(struct ast_hashtab *tab);
+
+
+int ast_hashtab_newsize_tight(struct ast_hashtab *tab);
+
+
+int ast_hashtab_hash_string(const void *obj, int modulus);
+
+
+int ast_hashtab_hash_string_nocase(const void *obj, int modulus);
+
+
+int ast_hashtab_hash_int(const int num, int modulus);
+
+
+int ast_hashtab_hash_short(const short num, int modulus);
+
+
+struct ast_hashtab * ast_hashtab_create(int initial_buckets,
+					int (*compare)(const void *a, const void *b),        /* a func to compare two elements in the hash -- cannot be null  */
+					int (*resize)(struct ast_hashtab *),     /* a func to decide if the table needs to be resized, 
+										a NULL ptr here will cause a default to be used */
+					int (*newsize)(struct ast_hashtab *tab), /* a ptr to func that returns a new size of the array. 
+										A NULL will cause a default to be used */
+					int (*hash)(const void *obj, int modulus),     /* a func to do the hashing */
+					int do_locking );                        /* use locks to guarantee safety of iterators/insertion/deletion */
+
+
+	/* this func will free the hash table and all its memory. It
+	   doesn't touch the objects stored in it */
+void ast_hashtab_destroy( struct ast_hashtab *tab);
+
+
+	/* normally, you'd insert "safely" by checking to see if the element is
+	   already there; in this case, you must already have checked. If an element
+	   is already in the hashtable, that matches this one, most likely this one
+	   will be found first. */
+	/* will force a resize if the resize func returns 1 */
+	/* returns 1 on success, 0 if there's a problem */
+int ast_hashtab_insert_immediate(struct ast_hashtab *tab, void *obj);
+
+
+	/* check to see if the element is already there; insert only if
+	   it is not there.*/
+	/* will force a resize if the resize func returns 1 */
+	/* returns 1 on success, 0 if there's a problem, or it's already there. */
+int ast_hashtab_insert_safe(struct ast_hashtab *tab, void *obj);
+
+
+	/* lookup this object in the hash table. return a ptr if found, or NULL if not */
+void * ast_hashtab_lookup(struct ast_hashtab *tab, void *obj);
+
+	/* returns key stats for the table */
+void ast_hashtab_get_stats( struct ast_hashtab *tab, int *biggest_bucket_size, int *resize_count, int *num_objects, int *num_buckets);
+
+	/* this function is called either internally, when the resize func returns 1, or
+	   externally by the user to force a resize of the hash table */
+void ast_hashtab_resize( struct ast_hashtab *tab);
+
+
+	/* returns an iterator */
+struct ast_hashtab_iter *ast_hashtab_start_traversal(struct ast_hashtab *tab);
+
+	/* returns the next object in the list, advances iter one step */
+void *ast_hashtab_next(struct ast_hashtab_iter *it);
+
+
+
+	/* looks up the object; removes the corresponding bucket */
+void *ast_hashtab_remove_object_via_lookup(struct ast_hashtab *tab, void *obj);
+
+
+	/* looks up the object by hash and then comparing pts in bucket list instead of
+	   calling the compare routine; removes the bucket */
+void *ast_hashtab_remove_this_object(struct ast_hashtab *tab, void *obj);
+
+#endif

Propchange: team/murf/fast-ast/main/hashtab.h
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: team/murf/fast-ast/main/hashtab.h
------------------------------------------------------------------------------
    svn:keywords = Author Id Date Revision

Propchange: team/murf/fast-ast/main/hashtab.h
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: team/murf/fast-ast/main/manager.c
URL: http://svn.digium.com/view/asterisk/team/murf/fast-ast/main/manager.c?rev=47188&r1=47187&r2=47188&view=diff
==============================================================================
--- team/murf/fast-ast/main/manager.c (original)
+++ team/murf/fast-ast/main/manager.c Fri Nov  3 22:47:45 2006
@@ -1664,6 +1664,7 @@
 	char *async = astman_get_header(m, "Async");
 	char *id = astman_get_header(m, "ActionID");
 	struct ast_variable *vars = astman_get_variables(m);
+	struct ast_channel *chan = NULL;
 	char *tech, *data;
 	char *l = NULL, *n = NULL;
 	int pi = 0;
@@ -1738,17 +1739,26 @@
 			}
 		}
 	} else if (!ast_strlen_zero(app)) {
-        	res = ast_pbx_outgoing_app(tech, AST_FORMAT_SLINEAR, data, to, app, appdata, &reason, 1, l, n, vars, account, NULL);
+        	res = ast_pbx_outgoing_app(tech, AST_FORMAT_SLINEAR, data, to, app, appdata, &reason, 1, l, n, vars, account, &chan);
     	} else {
 		if (exten && context && pi)
-	        	res = ast_pbx_outgoing_exten(tech, AST_FORMAT_SLINEAR, data, to, context, exten, pi, &reason, 1, l, n, vars, account, NULL);
+	        	res = ast_pbx_outgoing_exten(tech, AST_FORMAT_SLINEAR, data, to, context, exten, pi, &reason, 1, l, n, vars, account, &chan);
 		else {
 			astman_send_error(s, m, "Originate with 'Exten' requires 'Context' and 'Priority'");
 			return 0;
 		}
 	}
-	if (!res)
-		astman_send_ack(s, m, "Originate successfully queued");
+	if (!res) {
+		if (chan && chan->uniqueid[0]) {
+			astman_start_ack(s, m);
+			astman_append(s, "Uniqueid: %s\r\n", chan->uniqueid);
+			astman_append(s, "Message: Originate successfully queued\r\n");
+			astman_append(s, "\r\n");
+
+		} else  {
+			astman_send_ack(s, m, "Originate successfully queued");
+		}
+	}
 	else
 		astman_send_error(s, m, "Originate failed");
 	return 0;

Modified: team/murf/fast-ast/main/pbx.c
URL: http://svn.digium.com/view/asterisk/team/murf/fast-ast/main/pbx.c?rev=47188&r1=47187&r2=47188&view=diff
==============================================================================
--- team/murf/fast-ast/main/pbx.c (original)
+++ team/murf/fast-ast/main/pbx.c Fri Nov  3 22:47:45 2006
@@ -61,7 +61,7 @@
 #include "asterisk/app.h"
 #include "asterisk/devicestate.h"
 #include "asterisk/stringfields.h"
-#include "trb.h"
+#include "hashtab.h"
 
 /*!
  * \note I M P O R T A N T :
@@ -138,8 +138,8 @@
 	void *data;			/*!< Data to use (arguments) */
 	void (*datad)(void *);		/*!< Data destructor */
 	struct ast_exten *peer;		/*!< Next higher priority with our extension */
-	struct trb_table *peer_tree;    /*!< Priorities list in tree form -- only on the head of the peer list */
-	struct trb_table *peer_label_tree; /*!< labeled priorities in the peer list -- only on the head of the peer list */
+	struct ast_hashtab *peer_tree;    /*!< Priorities list in tree form -- only on the head of the peer list */
+	struct ast_hashtab *peer_label_tree; /*!< labeled priorities in the peer list -- only on the head of the peer list */
 	const char *registrar;		/*!< Registrar */
 	struct ast_exten *next;		/*!< Extension with a greater ID */
 	char stuff[0];
@@ -199,7 +199,7 @@
 struct ast_context {
 	ast_mutex_t lock; 			/*!< A lock to prevent multiple threads from clobbering the context */
 	struct ast_exten *root;			/*!< The root of the list of extensions */
-	struct trb_table *root_tree;            /*!< The root of the list of extensions in threaded red-black tree form */
+	struct ast_hashtab *root_tree;            /*!< The root of the list of extensions in threaded red-black tree form */
 	struct match_char *pattern_tree;        /*!< A tree to speed up extension pattern matching */
 	struct ast_context *next;		/*!< Link them together */
 	struct ast_include *includes;		/*!< Include other contexts */
@@ -276,49 +276,74 @@
 static int pbx_builtin_sayphonetic(struct ast_channel *, void *);
 int pbx_builtin_setvar(struct ast_channel *, void *);
 static int pbx_builtin_importvar(struct ast_channel *, void *);
-static int trb_compare_contexts(const void *trb_a, const void *trb_b, void *trb_param);
-static int trb_compare_extens(const void *trb_a, const void *trb_b, void *trb_param);
-static int trb_compare_exten_numbers(const void *trb_a, const void *trb_b, void *trb_param);
-static int trb_compare_exten_labels(const void *trb_a, const void *trb_b, void *trb_param);
-void new_find_extension(const char *str, struct scoreboard *score, struct match_char *tree, int length, int spec);
+void new_find_extension(const char *str, struct scoreboard *score, struct match_char *tree, int length, int spec, const char *callerid);
 struct match_char *already_in_tree(struct match_char *current, char *pat);
 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 *create_match_char_tree(struct ast_context *con);
 struct ast_exten *get_canmatch_exten(struct match_char *node);
-
-
-static int trb_compare_contexts(const void *trb_a, const void *trb_b, void *trb_param)
-{
-	struct ast_context *ac = (struct ast_context*)trb_a;
-	struct ast_context *bc = (struct ast_context*)trb_b;
+static int matchcid(const char *cidpattern, const char *callerid);
+static int hashtab_compare_contexts(const void *ah_a, const void *ah_b);
+static int hashtab_compare_extens(const void *ha_a, const void *ah_b);
+static int hashtab_compare_exten_numbers(const void *ah_a, const void *ah_b);
+static int hashtab_compare_exten_labels(const void *ah_a, const void *ah_b);
+static int hashtab_hash_contexts(const void *obj, int mod);
+static int hashtab_hash_extens(const void *obj, int mod);
+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 */
+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);
 }
 
-static int trb_compare_extens(const void *trb_a, const void *trb_b, void *trb_param)
-{
-	struct ast_exten *ac = (struct ast_exten*)trb_a;
-	struct ast_exten *bc = (struct ast_exten*)trb_b;
+static int hashtab_compare_extens(const void *ah_a, const void *ah_b)
+{
+	const struct ast_exten *ac = ah_a;
+	const struct ast_exten *bc = ah_b;
 	return strcmp(ac->exten, bc->exten);
 }
 
-static int trb_compare_exten_numbers(const void *trb_a, const void *trb_b, void *trb_param)
-{
-	struct ast_exten *ac = (struct ast_exten*)trb_a;
-	struct ast_exten *bc = (struct ast_exten*)trb_b;
-	if (ac->priority < bc->priority)
-		return -1;
-	else if (ac->priority == bc->priority)
-		return 0;
-	else
-		return 1;
-}
-
-static int trb_compare_exten_labels(const void *trb_a, const void *trb_b, void *trb_param)
-{
-	struct ast_exten *ac = (struct ast_exten*)trb_a;
-	struct ast_exten *bc = (struct ast_exten*)trb_b;
+static int hashtab_compare_exten_numbers(const void *ah_a, const void *ah_b)
+{
+	const struct ast_exten *ac = ah_a;
+	const struct ast_exten *bc = ah_b;
+	return ac->priority != bc->priority;
+}
+
+static int hashtab_compare_exten_labels(const void *ah_a, const void *ah_b)
+{
+	const struct ast_exten *ac = ah_a;
+	const struct ast_exten *bc = ah_b;
 	return strcmp(ac->label, bc->label);
 }
+
+static int hashtab_hash_contexts(const void *obj, int mod)
+{
+	const struct ast_context *ac = obj;
+	return ast_hashtab_hash_string(ac->name,mod);
+}
+
+static int hashtab_hash_extens(const void *obj, int mod)
+{
+	const struct ast_exten *ac = obj;
+	return ast_hashtab_hash_string(ac->exten,mod);
+}
+
+static int hashtab_hash_priority(const void *obj, int mod)
+{
+	const struct ast_exten *ac = obj;
+	return ast_hashtab_hash_int(ac->priority, mod);
+}
+
+static int hashtab_hash_labels(const void *obj, int mod)
+{
+	const struct ast_exten *ac = obj;
+	return ast_hashtab_hash_string(ac->label,mod);
+}
+
 
 AST_MUTEX_DEFINE_STATIC(globalslock);
 static struct varshead globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
@@ -541,7 +566,7 @@
 };
 
 static struct ast_context *contexts = NULL;
-static struct trb_table *contexts_tree = NULL;
+static struct ast_hashtab *contexts_tree = NULL;
 
 AST_MUTEX_DEFINE_STATIC(conlock); 		/*!< Lock for the ast_context list */
 
@@ -696,8 +721,15 @@
  */
 
 
-static void update_scoreboard(struct scoreboard *board, int length, int spec, struct ast_exten *exten, char last)
-{
+static void update_scoreboard(struct scoreboard *board, int length, int spec, struct ast_exten *exten, char last, const char *callerid)
+{
+	/* wait a minute, here's where we check that matchcid stuff... if they mismatch,
+	 * then there's no use in continuing the rest of the checks! */
+	if (exten->matchcid && !matchcid(exten->cidmatch, callerid))
+		return;       /* matchcid's didn't-- so this isn't a matching candidate */
+	else if (exten->matchcid)
+		length++;    /* if a cid match is made, then that should count at least as an extra matching digit */
+
 	if (length > board->total_length) {
 		board->total_specificity = spec;
 		board->total_length = length;
@@ -721,7 +753,7 @@
 	return 0;
 }
 
-void new_find_extension(const char *str, struct scoreboard *score, struct match_char *tree, int length, int spec)
+void new_find_extension(const char *str, struct scoreboard *score, struct match_char *tree, int length, int spec, const char *callerid)
 {
 	struct match_char *p; /* note minimal stack storage requirements */
 
@@ -729,9 +761,9 @@
 	{
 		if (p->x[0] == 'N' && p->x[1] == 0 && *str >= '2' && *str <= '9' ) {
 			if (p->next_char && *(str+1))
-				new_find_extension(str+1, score, p->next_char, length+1, spec+8);
+				new_find_extension(str+1, score, p->next_char, length+1, spec+8, callerid);
 			else if (p->exten) {
-				update_scoreboard(score, length+1, spec+8, p->exten,0);
+				update_scoreboard(score, length+1, spec+8, p->exten,0,callerid);
 				return;
 			} else if (p->next_char && !*(str+1)) {
 				score->canmatch = 1;
@@ -741,9 +773,9 @@
 			}
 		} else if (p->x[0] == 'Z' && p->x[1] == 0 && *str >= '1' && *str <= '9' ) {
 			if (p->next_char && *(str+1))
-				new_find_extension(str+1, score, p->next_char, length+1, spec+9);
+				new_find_extension(str+1, score, p->next_char, length+1, spec+9, callerid);
 			else if (p->exten) {
-				update_scoreboard(score, length+1, spec+9, p->exten,0);
+				update_scoreboard(score, length+1, spec+9, p->exten,0,callerid);
 				return;
 			} else if (p->next_char && !*(str+1)) {
 				score->canmatch = 1;
@@ -753,9 +785,9 @@
 			}
 		} else if (p->x[0] == 'X' && p->x[1] == 0 && *str >= '0' && *str <= '9' ) {
 			if (p->next_char && *(str+1))
-				new_find_extension(str+1, score, p->next_char, length+1, spec+10);
+				new_find_extension(str+1, score, p->next_char, length+1, spec+10, callerid);
 			else if (p->exten) {
-				update_scoreboard(score, length+1, spec+10, p->exten,0);
+				update_scoreboard(score, length+1, spec+10, p->exten,0,callerid);
 				return;
 			} else if (p->next_char && !*(str+1)) {
 				score->canmatch = 1;
@@ -764,16 +796,16 @@
 				return;
 			}
 		} else if (p->x[0] == '.' && p->x[1] == 0 ) {
-			update_scoreboard(score, length+1, spec+11, p->exten, '.');
+			update_scoreboard(score, length+1, spec+11, p->exten, '.',callerid);
 			return;
 		} else if (p->x[0] == '!' && p->x[1] == 0 ) {
-			update_scoreboard(score, length+1, spec+11, p->exten, '!');
+			update_scoreboard(score, length+1, spec+11, p->exten, '!',callerid);
 			return;
 		} else if (index(p->x, *str)) {
 			if (p->next_char && *(str+1))
-				new_find_extension(str+1, score, p->next_char, length+1, spec+p->specificity);
+				new_find_extension(str+1, score, p->next_char, length+1, spec+p->specificity, callerid);
 			else if (p->exten) {
-				update_scoreboard(score, length+1, spec+p->specificity, p->exten,0);
+				update_scoreboard(score, length+1, spec+p->specificity, p->exten,0,callerid);
 				return;
 			} else if (p->next_char && !*(str+1)) {
 				score->canmatch = 1;
@@ -851,15 +883,15 @@
 
 struct match_char *create_match_char_tree(struct ast_context *con)
 {
-	struct trb_traverser t1;
+	struct ast_hashtab_iter *t1;
 	struct ast_exten *e1;
 	struct match_char *m1,*m2;
 	char buf[256];
 	int already;
 	int specif;
 	
-	trb_t_init(&t1, con->root_tree);
-	while( (e1 = trb_t_next(&t1)) ) {
+	t1 = ast_hashtab_start_traversal(con->root_tree);
+	while( (e1 = ast_hashtab_next(t1)) ) {
 		int pattern = 0;
 		char *s1 = e1->exten;
 		m1 = con->pattern_tree; /* each pattern starts over at the root of the pattern tree */
@@ -1229,7 +1261,7 @@
 {
 	ast_mutex_t lock; 			
 	struct ast_exten *root;		
-	struct trb_table *root_tree;            
+	struct ast_hashtab *root_tree;            
 	struct match_char *pattern_tree;       
 	struct ast_context *next;	
 	struct ast_include *includes;		
@@ -1247,7 +1279,7 @@
 	strncpy(item.name,name,256);
 	ast_mutex_lock(&conlock);
 	if( contexts_tree )
-		tmp = trb_find(contexts_tree,&item);
+		tmp = ast_hashtab_lookup(contexts_tree,&item);
 #ifdef NOTNOW
 	while ( (tmp = ast_walk_contexts(tmp)) ) {
 		if (!name || !strcasecmp(name, tmp->name))
@@ -1329,7 +1361,7 @@
 	else {	/* look in contexts */
 		struct fake_context item;
 		strncpy(item.name,context,256);
-		tmp = trb_find(contexts_tree,&item);
+		tmp = ast_hashtab_lookup(contexts_tree,&item);
 #ifdef NOTNOW
 		tmp = NULL;
 		while ((tmp = ast_walk_contexts(tmp)) ) {
@@ -1350,7 +1382,7 @@
 	score.total_length = 0;
 	if (!tmp->pattern_tree)
 		create_match_char_tree(tmp);
-	new_find_extension(exten, &score, tmp->pattern_tree, 0, 0);
+	new_find_extension(exten, &score, tmp->pattern_tree, 0, 0, callerid);
 	eroot = score.exten;
 
 	if (score.last_char == '!' && action == E_MATCHMORE) {
@@ -1373,9 +1405,9 @@
 		if (action == E_FINDLABEL && label ) {
 			if (q->status < STATUS_NO_LABEL)
 				q->status = STATUS_NO_LABEL;
-			e = trb_find(eroot->peer_label_tree, &pattern);
+			e = ast_hashtab_lookup(eroot->peer_label_tree, &pattern);
 		} else {
-			e = trb_find(eroot->peer_tree, &pattern);
+			e = ast_hashtab_lookup(eroot->peer_tree, &pattern);
 		}
 		if (e) {	/* found a valid match */
 			q->status = STATUS_SUCCESS;
@@ -1406,9 +1438,9 @@
 		if (action == E_FINDLABEL && label ) {
 			if (q->status < STATUS_NO_LABEL)
 				q->status = STATUS_NO_LABEL;
-			e = trb_find(eroot->peer_label_tree, &pattern);
+			e = ast_hashtab_lookup(eroot->peer_label_tree, &pattern);
 		} else {
-			e = trb_find(eroot->peer_tree, &pattern);
+			e = ast_hashtab_lookup(eroot->peer_tree, &pattern);
 		}
 #ifdef NOTNOW
 		while ( (e = ast_walk_extension_priorities(eroot, e)) ) {
@@ -3016,7 +3048,7 @@
 	struct fake_context item;
 	strncpy(item.name, context, 256);
 	ast_lock_contexts();
-	c = trb_find(contexts_tree,&item);
+	c = ast_hashtab_lookup(contexts_tree,&item);
 #ifdef NOTNOW
 
 	while ( (c = ast_walk_contexts(c)) ) {
@@ -3244,7 +3276,7 @@
 	struct fake_context item;
 	strncpy(item.name,context,256);
 	ast_lock_contexts();
-	c = trb_find(contexts_tree,&item);
+	c = ast_hashtab_lookup(contexts_tree,&item);
 	if (c)
 		ret = 0;
 
@@ -3281,7 +3313,7 @@
 
 	ast_lock_contexts();
 
-	c = trb_find(contexts_tree,&item);
+	c = ast_hashtab_lookup(contexts_tree,&item);
 	if (c)
 		ret = 0;
 #ifdef NOTNOW
@@ -4267,7 +4299,12 @@
 		ast_mutex_lock(&conlock);
 		local_contexts = &contexts;
 		if (!contexts_tree)
-			contexts_tree = trb_create(trb_compare_contexts, NULL, NULL);
+			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;
 
@@ -4293,7 +4330,7 @@
 		tmp->includes = NULL;
 		tmp->ignorepats = NULL;
 		*local_contexts = tmp;
-		trb_insert(contexts_tree, tmp); /*put this context into the tree */
+		ast_hashtab_insert_safe(contexts_tree, tmp); /*put this context into the tree */
 		if (option_debug)
 			ast_log(LOG_DEBUG, "Registered context '%s'\n", tmp->name);
 		if (option_verbose > 2)
@@ -5086,9 +5123,9 @@
 			break;
 	}
 	if (!e) {	/* go at the end, and ep is surely set because the list is not empty */
-		trb_insert(eh->peer_tree, tmp);
+		ast_hashtab_insert_safe(eh->peer_tree, tmp);
 		if (tmp->label)
-			trb_insert(eh->peer_label_tree, tmp);
+			ast_hashtab_insert_safe(eh->peer_label_tree, tmp);
 		ep->peer = tmp;
 		return 0;	/* success */
 	}
@@ -5107,39 +5144,39 @@
 		tmp->next = e->next;	/* not meaningful if we are not first in the peer list */
 		tmp->peer = e->peer;	/* always meaningful */
 		if (ep) {			/* We're in the peer list, just insert ourselves */
-			trb_delete(eh->peer_tree,e);
+			ast_hashtab_remove_object_via_lookup(eh->peer_tree,e);

[... 716 lines stripped ...]


More information about the asterisk-commits mailing list