[asterisk-commits] murf: branch murf/datastructs r87019 - in /team/murf/datastructs: funcs/ incl...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Oct 24 17:46:37 CDT 2007


Author: murf
Date: Wed Oct 24 17:46:37 2007
New Revision: 87019

URL: http://svn.digium.com/view/asterisk?view=rev&rev=87019
Log:
Found a bug, involving using a possibly null pointer without checking (I was doing it everywhere but in one spot). The rest is pulling applying the modulus (hash table size) to the key hash values, out of the hashing funcs. I see that ast_obj2 did this, and it suddenly struck me today (duh, why didnt I think of this a long time ago?) that if I let the table code apply the modulus, then the hash function will not change its values after table resizings, and the hash values can be safely cached. Many thanks to Luigi & Marta for this inspiration. Never worried about cacheing before.

Modified:
    team/murf/datastructs/funcs/func_hashtab.c
    team/murf/datastructs/funcs/func_strings.c
    team/murf/datastructs/include/asterisk/hashtab.h
    team/murf/datastructs/main/hashtab.c

Modified: team/murf/datastructs/funcs/func_hashtab.c
URL: http://svn.digium.com/view/asterisk/team/murf/datastructs/funcs/func_hashtab.c?view=diff&rev=87019&r1=87018&r2=87019
==============================================================================
--- team/murf/datastructs/funcs/func_hashtab.c (original)
+++ team/murf/datastructs/funcs/func_hashtab.c Wed Oct 24 17:46:37 2007
@@ -108,16 +108,16 @@
 	return ast_hashtab_compare_strings(ae->key, be->key);
 }
 
-static int hashtab_hash_string(const void *obj, int modulus)
+static int hashtab_hash_string(const void *obj)
 {
 	const struct ht_element *o = obj;
-	return ast_hashtab_hash_string(o->key, modulus);
-}
-
-static int hashtab_hash_string_nocase(const void *obj, int modulus)
+	return ast_hashtab_hash_string(o->key);
+}
+
+static int hashtab_hash_string_nocase(const void *obj)
 {
 	const struct ht_element *o = obj;
-	return ast_hashtab_hash_string_nocase(o->key, modulus);
+	return ast_hashtab_hash_string_nocase(o->key);
 }
 
 static int function_hashtab_access_read(struct ast_channel *chan, const char *cmd,
@@ -240,7 +240,7 @@
 	int (*comparefunc)(const void *a, const void *b);
 	int (*resizefunc)(struct ast_hashtab *);
 	int (*newsizefunc)(struct ast_hashtab *tab);
-	int (*hashfunc)(const void *obj, int modulus);
+	int (*hashfunc)(const void *obj);
 	AST_STANDARD_APP_ARGS(args, parse);
 	
 	if (!ast_strlen_zero(args.options))

Modified: team/murf/datastructs/funcs/func_strings.c
URL: http://svn.digium.com/view/asterisk/team/murf/datastructs/funcs/func_strings.c?view=diff&rev=87019&r1=87018&r2=87019
==============================================================================
--- team/murf/datastructs/funcs/func_strings.c (original)
+++ team/murf/datastructs/funcs/func_strings.c Wed Oct 24 17:46:37 2007
@@ -200,9 +200,9 @@
 	return ast_hashtab_newsize_java(tab);
 }
 
-static int func_HASH_HASH(const void *obj, int modulus)
-{
-	return ast_hashtab_hash_string(obj, modulus); /* the standard, case-sensitive hash */
+static int func_HASH_HASH(const void *obj)
+{
+	return ast_hashtab_hash_string(obj); /* the standard, case-sensitive hash */
 }
 
 static void destroy_hashvar(void *vobj)

Modified: team/murf/datastructs/include/asterisk/hashtab.h
URL: http://svn.digium.com/view/asterisk/team/murf/datastructs/include/asterisk/hashtab.h?view=diff&rev=87019&r1=87018&r2=87019
==============================================================================
--- team/murf/datastructs/include/asterisk/hashtab.h (original)
+++ team/murf/datastructs/include/asterisk/hashtab.h Wed Oct 24 17:46:37 2007
@@ -83,8 +83,8 @@
 													 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) (const void *obj);         /* a hash func ptr for this table. Given a raw ptr to an obj, 
+													 it calcs a hash.*/
 	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 */
@@ -136,19 +136,19 @@
 int ast_hashtab_newsize_none(struct ast_hashtab *tab); /* always return current size -- no resizing */
 
 
-int ast_hashtab_hash_string(const void *obj, int modulus); /* hashes a string to a number, mod is applied so it in the range 0 to mod-1 */
-
-
-int ast_hashtab_hash_string_nocase(const void *obj, int modulus);  /* upcases each char before using them for a hash */
-
-
-int ast_hashtab_hash_string_sax(const void *obj, int modulus); /* from Josh */
-
-
-int ast_hashtab_hash_int(const int num, int modulus);  /* right now, both these funcs are just result = num%modulus; */
-
-
-int ast_hashtab_hash_short(const short num, int modulus);
+int ast_hashtab_hash_string(const void *obj); /* hashes a string to a number, mod is applied so it in the range 0 to mod-1 */
+
+
+int ast_hashtab_hash_string_nocase(const void *obj);  /* upcases each char before using them for a hash */
+
+
+int ast_hashtab_hash_string_sax(const void *obj); /* from Josh */
+
+
+int ast_hashtab_hash_int(const int num);  /* right now, both these funcs are just result = num%modulus; */
+
+
+int ast_hashtab_hash_short(const short num);
 
 
 struct ast_hashtab * ast_hashtab_create(int initial_buckets,
@@ -157,7 +157,7 @@
 										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 (*hash)(const void *obj),     /* a func to do the hashing */
 					int do_locking );                        /* use locks to guarantee safety of iterators/insertion/deletion */
 
 
@@ -188,7 +188,12 @@
 	/* lookup this object in the hash table. return a ptr if found, or NULL if not */
 void * ast_hashtab_lookup(struct ast_hashtab *tab, const void *obj);
 
-	/* same as the above lookup, but sets h to the index if the lookup fails */
+    /* if you know the hash val for the object, then use this and avoid the recalc
+	   of the hash (the modulus (table_size) is not applied) */
+void * ast_hashtab_lookup_with_hash(struct ast_hashtab *tab, const void *obj, int hashval);
+
+	/* same as the above lookup, but sets h to the key hash value if the lookup fails -- this has the modulus 
+       applied, and will not be useful for long term storage if the table is resizable */
 void * ast_hashtab_lookup_bucket(struct ast_hashtab *tab, const void *obj, int *h);
 
 	/* returns key stats for the table */

Modified: team/murf/datastructs/main/hashtab.c
URL: http://svn.digium.com/view/asterisk/team/murf/datastructs/main/hashtab.c?view=diff&rev=87019&r1=87018&r2=87019
==============================================================================
--- team/murf/datastructs/main/hashtab.c (original)
+++ team/murf/datastructs/main/hashtab.c Wed Oct 24 17:46:37 2007
@@ -153,7 +153,7 @@
 	return tab->hash_tab_size;
 }
 
-int ast_hashtab_hash_string(const void *obj, int modulus)
+int ast_hashtab_hash_string(const void *obj)
 {
 	unsigned char *str = (unsigned char*)obj;
 	unsigned int total;
@@ -168,10 +168,10 @@
 		
 		total += ((unsigned int)(*str));
 	}
-	return (total % modulus);
-}
-
-int ast_hashtab_hash_string_sax(const void *obj, int modulus) /* from Josh */
+	return total;
+}
+
+int ast_hashtab_hash_string_sax(const void *obj) /* from Josh */
 {
 	unsigned char *str = (unsigned char*)obj;
 	unsigned int total = 0, c = 0;
@@ -179,10 +179,10 @@
 	while ((c = *str++))
 		total ^= ( total << 5 ) + ( total >> 2 ) + ( total << 10) + c;
 
-	return (total % modulus);
-}
-
-int ast_hashtab_hash_string_nocase(const void *obj, int modulus)
+	return total;
+}
+
+int ast_hashtab_hash_string_nocase(const void *obj)
 {
 	unsigned char *str = (unsigned char*)obj;
 	unsigned int total;
@@ -203,25 +203,25 @@
 		
 		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)
+	return total;
+}
+
+int ast_hashtab_hash_int(const int x)
+{
+	return x;
+}
+
+int ast_hashtab_hash_short(const short x)
 {
 	/* hmmmm.... modulus is best < 65535 !! */
-	return (x % modulus);
+	return x;
 }
 
 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 (*hash)(const void *obj), /* a func to do the hashing */
 										int do_locking ) /* use locks to guarantee safety of iterators/insertion/deletion -- real simpleminded right now */
 {
 	struct ast_hashtab *ht = ast_calloc(1,sizeof(struct ast_hashtab));
@@ -395,7 +395,7 @@
 	}
 	if (tab->do_locking)
 		ast_rwlock_wrlock(&tab->lock);
-	h = (*tab->hash)(obj, tab->hash_tab_size);
+	h = ((*tab->hash)(obj)) % tab->hash_tab_size;
 	for (c=0,b=tab->array[h];b;b=b->next) {
 		c++;
 	}
@@ -443,7 +443,8 @@
 	b->next = tab->array[h];
 	b->prev = NULL;
 	tab->array[h] = b;
-	b->next->prev = b;
+	if (b->next)
+		b->next->prev = b;
 	tlist_add_head(&(tab->tlist), b);
 	tab->hash_tab_elements++;
 	if ((*tab->resize)(tab))
@@ -481,7 +482,7 @@
 	
 	if (tab->do_locking)
 		ast_rwlock_rdlock(&tab->lock);
-	h = (*tab->hash)(obj, tab->hash_tab_size);
+	h = ((*tab->hash)(obj)) % tab->hash_tab_size;
 	for (b=tab->array[h]; b; b=b->next) {
 		if ((*tab->compare)(obj,b->object) == 0) {
 			ret = b->object;
@@ -496,6 +497,32 @@
 	return 0;
 }
 
+void * ast_hashtab_lookup_with_hash(struct ast_hashtab *tab, const void *obj, int hashval)
+{
+	/* lookup this object in the hash table. return a ptr if found, or NULL if not */
+	int h;
+	const void *ret;
+	struct ast_hashtab_bucket *b;
+	if (!tab || !obj)
+		return 0;
+	
+	if (tab->do_locking)
+		ast_rwlock_rdlock(&tab->lock);
+	h = hashval % tab->hash_tab_size;
+	for (b=tab->array[h]; b; b=b->next) {
+		if ((*tab->compare)(obj,b->object) == 0) {
+			ret = b->object;
+			if (tab->do_locking)
+				ast_rwlock_unlock(&tab->lock);
+			return (void*)ret; /* I can't touch obj in this func, but the outside world is welcome to */
+		}
+	}
+	if (tab->do_locking)
+		ast_rwlock_unlock(&tab->lock);
+
+	return 0;
+}
+
 void * ast_hashtab_lookup_bucket(struct ast_hashtab *tab, const void *obj, int *bucket)
 {
 	/* lookup this object in the hash table. return a ptr if found, or NULL if not */
@@ -504,7 +531,7 @@
 	if (!tab || !obj)
 		return 0;
 	
-	h = (*tab->hash)(obj, tab->hash_tab_size);
+	h = ((*tab->hash)(obj)) % tab->hash_tab_size;
 	for (b=tab->array[h]; b; b=b->next) {
 		if ((*tab->compare)(obj,b->object) == 0) {
 			if (tab->do_locking)
@@ -574,7 +601,7 @@
 	{
 		b->prev = 0;
 		bn = b->tnext;
-		h = (*tab->hash)(b->object, tab->hash_tab_size);
+		h = ((*tab->hash)(b->object)) % tab->hash_tab_size;
 		b->next = tab->array[h];
 		if (b->next)
 			b->next->prev = b;
@@ -695,7 +722,7 @@
 		return 0;
 	if (tab->do_locking)
 		ast_rwlock_wrlock(&tab->lock);
-	h = (*tab->hash)(obj, tab->hash_tab_size);
+	h = ((*tab->hash)(obj)) % tab->hash_tab_size;
 	for (b=tab->array[h]; b; b=b->next)
 	{
 		void *obj2;
@@ -723,7 +750,7 @@
 
 	if (!tab || !obj)
 		return 0;
-	h = (*tab->hash)(obj, tab->hash_tab_size);
+	h = ((*tab->hash)(obj)) % tab->hash_tab_size;
 	for (b=tab->array[h]; b; b=b->next)
 	{
 		void *obj2;
@@ -755,7 +782,7 @@
 	if (tab->do_locking)
 		ast_rwlock_wrlock(&tab->lock);
 
-	h = (*tab->hash)(obj, tab->hash_tab_size);
+	h = ((*tab->hash)(obj)) % tab->hash_tab_size;
 	for (b=tab->array[h]; b; b=b->next)
 	{
 		const void *obj2;
@@ -787,7 +814,7 @@
 	if (!tab || !obj)
 		return 0;
  
-	h = (*tab->hash)(obj, tab->hash_tab_size);
+	h = ((*tab->hash)(obj)) % tab->hash_tab_size;
 	for (b=tab->array[h]; b; b=b->next)
 	{
 		const void *obj2;




More information about the asterisk-commits mailing list