svn commit: r202149 - user/luigi/ipfw3-head/sys/netinet/ipfw

Luigi Rizzo luigi at FreeBSD.org
Tue Jan 12 10:13:10 UTC 2010


Author: luigi
Date: Tue Jan 12 10:13:09 2010
New Revision: 202149
URL: http://svn.freebsd.org/changeset/base/202149

Log:
  add removal code, fix some bugs

Modified:
  user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.c
  user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.h

Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.c
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.c	Tue Jan 12 10:06:32 2010	(r202148)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.c	Tue Jan 12 10:13:09 2010	(r202149)
@@ -292,9 +292,15 @@ heap_free(struct dn_heap *h)
 }
 
 /*
- * hash table
-*/
+ * hash table support.
+ */
 
+/*
+ * Initialize, allocating bucket pointers inline.
+ * Recycle previous record if possible.
+ * If the 'new' function is not supplied, we assume that the
+ * key passed to ht_find is the same object to be stored in.
+ */
 struct dn_ht *
 dn_ht_init(struct dn_ht *ht, int buckets, int ofs,
         int (*h)(void *, uintptr_t arg),
@@ -336,19 +342,19 @@ dn_ht_init(struct dn_ht *ht, int buckets
 
 /* lookup and optionally create element */
 void *
-dn_ht_find(struct dn_ht *ht, void *obj, int create)
+dn_ht_find(struct dn_ht *ht, void *key, int create)
 {
 	int i;
 	void *p;
 
-	i = (ht->buckets == 1) ? 0 : ht->hash(obj, ht->arg) % ht->buckets;
+	i = (ht->buckets == 1) ? 0 : ht->hash(key, ht->arg) % ht->buckets;
 	// log(1, "find %p in bucket %d\n", obj, i);
 	for (p = ht->ht[i]; p; p = *(void **)((char *)p + ht->ofs)) {
-		if (ht->match(p, obj, ht->arg))
+		if (ht->match(p, key, ht->arg))
 			break;
 	}
 	if (p == NULL && create) {
-		p = ht->new(obj, ht->arg);
+		p = ht->new ? ht->new(key, ht->arg) : key;
 		if (p) {
 			ht->entries++;
 			*(void **)((char *)p + ht->ofs) = ht->ht[i];
@@ -381,6 +387,29 @@ dn_ht_scan(struct dn_ht *ht, int (*fn)(v
 	return found;
 }
 
+/*
+ * remove obj from the table, using key to find the slot.
+ * Returns obj if found, NULL if not found
+ */
+void *
+dn_ht_remove(struct dn_ht *ht, void *obj, void *key)
+{
+	int i;
+	void **pp, *p;
+
+	i = (ht->buckets == 1) ? 0 : ht->hash(obj, ht->arg) % ht->buckets;
+	// log(1, "find %p in bucket %d\n", obj, i);
+	for (pp = &ht->ht[i]; (p = *pp); pp = (void **)((char *)p + ht->ofs)) {
+		if (p != obj)
+			continue;
+		/* link in the next element */
+		*pp = *(void **)((char *)p + ht->ofs);
+		*(void **)((char *)p + ht->ofs) = NULL;
+		ht->entries--;
+		return obj;
+	}
+	return NULL;	/* failed */
+}
 
 #ifndef _KERNEL
 /*
@@ -393,10 +422,23 @@ struct x {
 	char buf[0];
 };
 
-int hfn(void *_x, uintptr_t arg)
+int hfn1(void *_x, uintptr_t arg)
 {
-	char *p = _x;
-	return p[0];
+	return *(char *)_x;
+}
+int matchfn1(void *_x, void *_obj, uintptr_t arg)
+{
+	return (strcmp(((struct x *)_x)->buf, _obj) == 0);
+}
+
+int hfn2(void *_x, uintptr_t arg)
+{
+	return ((struct x *)_x)->buf[0];
+}
+int matchfn2(void *_x, void *_obj, uintptr_t arg)
+{
+	return (strcmp(((struct x *)_x)->buf,
+			((struct x *)_obj)->buf) == 0);
 }
 
 void *newfn(void *_x, uintptr_t arg)
@@ -409,12 +451,6 @@ void *newfn(void *_x, uintptr_t arg)
 	return p;
 }
 
-int matchfn(void *_x, void *_obj, uintptr_t arg)
-{
-	struct x *x = _x;
-	return (strcmp(x->buf, _obj) == 0);
-}
-
 char *strings[] = {
 	"undici", "unico", "doppio", "devoto",
 	"uno", "due", "tre", "quattro", "cinque", "sei",
@@ -433,17 +469,28 @@ static void
 test_hash()
 {
 	char **p;
-	struct dn_ht *h = dn_ht_init(NULL, 10, 0, hfn, matchfn, newfn,
-		0);
+	struct dn_ht *h;
+	void *x = NULL;
+
+	/* first, find and allocate */
+	h = dn_ht_init(NULL, 10, 0, hfn1, matchfn1, newfn, 0);
 
 	for (p = strings; *p; p++) {
 		dn_ht_find(h, *p, 1);
 	}
 	dn_ht_scan(h, doprint, 0);
+	printf("/* second -- find without allocate */\n");
+	h = dn_ht_init(NULL, 10, 0, hfn2, matchfn2, NULL, 0);
 	for (p = strings; *p; p++) {
-//		dn_ht_scan(h, doprint, HEAP_SCAN_DEL);
-		dn_ht_find(h, *p, 1);
+		void **y = newfn(*p, 0);
+		if (x == NULL)
+			x = y;
+		dn_ht_find(h, y, 1);
 	}
+	dn_ht_scan(h, doprint, 0);
+	printf("remove %p gives %p\n", x, dn_ht_remove(h, x, x));
+	printf("remove %p gives %p\n", x, dn_ht_remove(h, x, x));
+	dn_ht_scan(h, doprint, 0);
 }
 
 int

Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.h
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.h	Tue Jan 12 10:06:32 2010	(r202148)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.h	Tue Jan 12 10:13:09 2010	(r202149)
@@ -98,11 +98,12 @@ struct dn_ht {
 struct dn_ht *dn_ht_init(struct dn_ht *, int buckets, int ofs, 
         int (*h)(void *, uintptr_t arg),
         int (*match)(void *, void *, uintptr_t arg),
-	void *(*new)(void *, uintptr_t arg),
+        void *(*new)(void *, uintptr_t arg),
 	uintptr_t arg);
 
 /* lookup and optionally create element */
-void *dn_ht_find(struct dn_ht *, void *obj, int create);
+void *dn_ht_find(struct dn_ht *, void *key, int create);
+void *dn_ht_remove(struct dn_ht *, void *obj, void *key);
 
 enum {
         DN_HT_SCAN_DEL = 1,


More information about the svn-src-user mailing list