[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