[experimental-ims] 18edda6 Move the hashing implementations into a subdirectory where VMODs won't see them.

Geoff Simmons geoff at varnish-cache.org
Mon Jan 9 21:52:18 CET 2012


commit 18edda6b2925d86115bd5e2488190f0f91a39d41
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Wed Oct 12 17:08:56 2011 +0000

    Move the hashing implementations into a subdirectory where VMODs
    won't see them.

diff --git a/bin/varnishd/Makefile.am b/bin/varnishd/Makefile.am
index cdec084..499cb6c 100644
--- a/bin/varnishd/Makefile.am
+++ b/bin/varnishd/Makefile.am
@@ -52,9 +52,9 @@ varnishd_SOURCES = \
 	cache_wrk.c \
 	cache_wrw.c \
 	cache_ws.c \
-	hash_classic.c \
-	hash_critbit.c \
-	hash_simple_list.c \
+	hash/hash_classic.c \
+	hash/hash_critbit.c \
+	hash/hash_simple_list.c \
 	mgt_child.c \
 	mgt_cli.c \
 	mgt_param.c \
@@ -84,7 +84,7 @@ noinst_HEADERS = \
 	waiter/cache_waiter.h \
 	common.h \
 	default_vcl.h \
-	hash_slinger.h \
+	hash/hash_slinger.h \
 	heritage.h \
 	mgt.h \
 	mgt_cli.h \
diff --git a/bin/varnishd/cache_ban.c b/bin/varnishd/cache_ban.c
index d556ace..736cbf7 100644
--- a/bin/varnishd/cache_ban.c
+++ b/bin/varnishd/cache_ban.c
@@ -67,7 +67,7 @@
 
 #include "cache.h"
 
-#include "hash_slinger.h"
+#include "hash/hash_slinger.h"
 #include "vcli.h"
 #include "vcli_priv.h"
 #include "vend.h"
diff --git a/bin/varnishd/cache_center.c b/bin/varnishd/cache_center.c
index 1eb249e..0a81925 100644
--- a/bin/varnishd/cache_center.c
+++ b/bin/varnishd/cache_center.c
@@ -64,7 +64,7 @@ DOT acceptor -> start [style=bold,color=green]
 
 #include "cache.h"
 
-#include "hash_slinger.h"
+#include "hash/hash_slinger.h"
 #include "vcl.h"
 #include "vcli_priv.h"
 #include "vsha256.h"
diff --git a/bin/varnishd/cache_cli.c b/bin/varnishd/cache_cli.c
index 01da3f2..30a12e3 100644
--- a/bin/varnishd/cache_cli.c
+++ b/bin/varnishd/cache_cli.c
@@ -41,7 +41,7 @@
 #include "cache.h"
 
 #include "cache_backend.h"		// struct vbc
-#include "hash_slinger.h"		// objhead
+#include "hash/hash_slinger.h"		// struct objhead
 #include "vcli.h"
 #include "vcli_common.h"
 #include "vcli_priv.h"
diff --git a/bin/varnishd/cache_expire.c b/bin/varnishd/cache_expire.c
index f9dcdd1..601025c 100644
--- a/bin/varnishd/cache_expire.c
+++ b/bin/varnishd/cache_expire.c
@@ -56,7 +56,7 @@
 #include "cache.h"
 
 #include "binary_heap.h"
-#include "hash_slinger.h"
+#include "hash/hash_slinger.h"
 #include "vtim.h"
 
 static pthread_t exp_thread;
diff --git a/bin/varnishd/cache_hash.c b/bin/varnishd/cache_hash.c
index 14c5e7c..ecce40d 100644
--- a/bin/varnishd/cache_hash.c
+++ b/bin/varnishd/cache_hash.c
@@ -58,7 +58,7 @@
 
 #include "cache.h"
 
-#include "hash_slinger.h"
+#include "hash/hash_slinger.h"
 #include "vav.h"
 #include "vsha256.h"
 
diff --git a/bin/varnishd/cache_main.c b/bin/varnishd/cache_main.c
index 2d00ee2..8293d38 100644
--- a/bin/varnishd/cache_main.c
+++ b/bin/varnishd/cache_main.c
@@ -35,7 +35,7 @@
 #include "cache.h"
 
 #include "waiter/cache_waiter.h"
-#include "hash_slinger.h"
+#include "hash/hash_slinger.h"
 
 /*--------------------------------------------------------------------
  * Per thread storage for the session currently being processed by
diff --git a/bin/varnishd/cache_pool.c b/bin/varnishd/cache_pool.c
index 55ad333..141a0c7 100644
--- a/bin/varnishd/cache_pool.c
+++ b/bin/varnishd/cache_pool.c
@@ -48,7 +48,6 @@
 #include "cache.h"
 
 #include "waiter/cache_waiter.h"
-#include "hash_slinger.h"
 #include "vtcp.h"
 #include "vtim.h"
 
@@ -262,9 +261,7 @@ Pool_Work_Thread(void *priv, struct worker *w)
 			AZ(w->sp->wrk);
 			THR_SetSession(w->sp);
 			w->sp->wrk = w;
-			CHECK_OBJ_ORNULL(w->nobjhead, OBJHEAD_MAGIC);
 			CNT_Session(w->sp);
-			CHECK_OBJ_ORNULL(w->nobjhead, OBJHEAD_MAGIC);
 			THR_SetSession(NULL);
 			w->sp = NULL;
 
diff --git a/bin/varnishd/cache_vrt.c b/bin/varnishd/cache_vrt.c
index 2302b86..16258ec 100644
--- a/bin/varnishd/cache_vrt.c
+++ b/bin/varnishd/cache_vrt.c
@@ -40,7 +40,7 @@
 #include "cache.h"
 
 #include "cache_backend.h"
-#include "hash_slinger.h"
+#include "hash/hash_slinger.h"
 #include "vav.h"
 #include "vcl.h"
 #include "vrt.h"
diff --git a/bin/varnishd/cache_wrk.c b/bin/varnishd/cache_wrk.c
index 1032691..e416eb9 100644
--- a/bin/varnishd/cache_wrk.c
+++ b/bin/varnishd/cache_wrk.c
@@ -36,7 +36,7 @@
 
 #include "cache.h"
 
-#include "hash_slinger.h"
+#include "hash/hash_slinger.h"
 #include "vsha256.h"
 
 static struct lock		wstat_mtx;
diff --git a/bin/varnishd/hash/hash_classic.c b/bin/varnishd/hash/hash_classic.c
new file mode 100644
index 0000000..6b1d589
--- /dev/null
+++ b/bin/varnishd/hash/hash_classic.c
@@ -0,0 +1,184 @@
+/*-
+ * Copyright (c) 2006 Verdens Gang AS
+ * Copyright (c) 2006-2009 Varnish Software AS
+ * All rights reserved.
+ *
+ * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * A classic bucketed hash
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "cache.h"
+
+#include "hash/hash_slinger.h"
+
+/*--------------------------------------------------------------------*/
+
+struct hcl_hd {
+	unsigned		magic;
+#define HCL_HEAD_MAGIC		0x0f327016
+	VTAILQ_HEAD(, objhead)	head;
+	struct lock		mtx;
+};
+
+static unsigned			hcl_nhash = 16383;
+static struct hcl_hd		*hcl_head;
+
+/*--------------------------------------------------------------------
+ * The ->init method allows the management process to pass arguments
+ */
+
+static void
+hcl_init(int ac, char * const *av)
+{
+	int i;
+	unsigned u;
+
+	if (ac == 0)
+		return;
+	if (ac > 1)
+		ARGV_ERR("(-hclassic) too many arguments\n");
+	i = sscanf(av[0], "%u", &u);
+	if (i <= 0 || u == 0)
+		return;
+	if (u > 2 && !(u & (u - 1))) {
+		fprintf(stderr,
+		    "NOTE:\n"
+		    "\tA power of two number of hash buckets is "
+		    "marginally less efficient\n"
+		    "\twith systematic URLs.  Reducing by one"
+		    " hash bucket.\n");
+		u--;
+	}
+	hcl_nhash = u;
+	fprintf(stderr, "Classic hash: %u buckets\n", hcl_nhash);
+	return;
+}
+
+/*--------------------------------------------------------------------
+ * The ->start method is called during cache process start and allows
+ * initialization to happen before the first lookup.
+ */
+
+static void
+hcl_start(void)
+{
+	unsigned u;
+
+	hcl_head = calloc(sizeof *hcl_head, hcl_nhash);
+	XXXAN(hcl_head);
+
+	for (u = 0; u < hcl_nhash; u++) {
+		VTAILQ_INIT(&hcl_head[u].head);
+		Lck_New(&hcl_head[u].mtx, lck_hcl);
+		hcl_head[u].magic = HCL_HEAD_MAGIC;
+	}
+}
+
+/*--------------------------------------------------------------------
+ * Lookup and possibly insert element.
+ * If nobj != NULL and the lookup does not find key, nobj is inserted.
+ * If nobj == NULL and the lookup does not find key, NULL is returned.
+ * A reference to the returned object is held.
+ * We use a two-pass algorithm to handle inserts as they are quite
+ * rare and collisions even rarer.
+ */
+
+static struct objhead *
+hcl_lookup(const struct sess *sp, struct objhead *noh)
+{
+	struct objhead *oh;
+	struct hcl_hd *hp;
+	unsigned u1, digest;
+	int i;
+
+	CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
+	CHECK_OBJ_NOTNULL(noh, OBJHEAD_MAGIC);
+
+	assert(sizeof noh->digest > sizeof digest);
+	memcpy(&digest, noh->digest, sizeof digest);
+	u1 = digest % hcl_nhash;
+	hp = &hcl_head[u1];
+
+	Lck_Lock(&hp->mtx);
+	VTAILQ_FOREACH(oh, &hp->head, hoh_list) {
+		i = memcmp(oh->digest, noh->digest, sizeof oh->digest);
+		if (i < 0)
+			continue;
+		if (i > 0)
+			break;
+		oh->refcnt++;
+		Lck_Unlock(&hp->mtx);
+		return (oh);
+	}
+
+	if (oh != NULL)
+		VTAILQ_INSERT_BEFORE(oh, noh, hoh_list);
+	else
+		VTAILQ_INSERT_TAIL(&hp->head, noh, hoh_list);
+
+	noh->hoh_head = hp;
+
+	Lck_Unlock(&hp->mtx);
+	return (noh);
+}
+
+/*--------------------------------------------------------------------
+ * Dereference and if no references are left, free.
+ */
+
+static int
+hcl_deref(struct objhead *oh)
+{
+	struct hcl_hd *hp;
+	int ret;
+
+	CHECK_OBJ_NOTNULL(oh, OBJHEAD_MAGIC);
+	CAST_OBJ_NOTNULL(hp, oh->hoh_head, HCL_HEAD_MAGIC);
+	assert(oh->refcnt > 0);
+	Lck_Lock(&hp->mtx);
+	if (--oh->refcnt == 0) {
+		VTAILQ_REMOVE(&hp->head, oh, hoh_list);
+		ret = 0;
+	} else
+		ret = 1;
+	Lck_Unlock(&hp->mtx);
+	return (ret);
+}
+
+/*--------------------------------------------------------------------*/
+
+const struct hash_slinger hcl_slinger = {
+	.magic	=	SLINGER_MAGIC,
+	.name	=	"classic",
+	.init	=	hcl_init,
+	.start	=	hcl_start,
+	.lookup =	hcl_lookup,
+	.deref	=	hcl_deref,
+};
diff --git a/bin/varnishd/hash/hash_critbit.c b/bin/varnishd/hash/hash_critbit.c
new file mode 100644
index 0000000..56cc5c0
--- /dev/null
+++ b/bin/varnishd/hash/hash_critbit.c
@@ -0,0 +1,492 @@
+/*-
+ * Copyright (c) 2008-2010 Varnish Software AS
+ * All rights reserved.
+ *
+ * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * A Crit Bit tree based hash
+ */
+
+// #define PHK
+
+#include "config.h"
+
+#include <stdlib.h>
+
+#include "cache.h"
+
+#include "hash/hash_slinger.h"
+#include "vcli_priv.h"
+#include "vmb.h"
+#include "vtim.h"
+
+static struct lock hcb_mtx;
+
+/*---------------------------------------------------------------------
+ * Table for finding out how many bits two bytes have in common,
+ * counting from the MSB towards the LSB.
+ * ie:
+ *	hcb_bittbl[0x01 ^ 0x22] == 2
+ *	hcb_bittbl[0x10 ^ 0x0b] == 3
+ *
+ */
+
+static unsigned char hcb_bittbl[256];
+
+static unsigned char
+hcb_bits(unsigned char x, unsigned char y)
+{
+	return hcb_bittbl[x ^ y];
+}
+
+static void
+hcb_build_bittbl(void)
+{
+	unsigned char x;
+	unsigned y;
+
+	y = 0;
+	for (x = 0; x < 8; x++)
+		for (; y < (1U << x); y++)
+			hcb_bittbl[y] = 8 - x;
+
+	/* Quick asserts for sanity check */
+	assert(hcb_bits(0x34, 0x34) == 8);
+	assert(hcb_bits(0xaa, 0x55) == 0);
+	assert(hcb_bits(0x01, 0x22) == 2);
+	assert(hcb_bits(0x10, 0x0b) == 3);
+}
+
+/*---------------------------------------------------------------------
+ * For space reasons we overload the two pointers with two different
+ * kinds of of pointers.  We cast them to uintptr_t's and abuse the
+ * low two bits to tell them apart, assuming that Varnish will never
+ * run on machines with less than 32bit alignment.
+ *
+ * Asserts will explode if these assumptions are not met.
+ */
+
+struct hcb_y {
+	unsigned		magic;
+#define HCB_Y_MAGIC		0x125c4bd2
+	unsigned short		critbit;
+	unsigned char		ptr;
+	unsigned char		bitmask;
+	volatile uintptr_t	leaf[2];
+	VSTAILQ_ENTRY(hcb_y)	list;
+};
+
+#define HCB_BIT_NODE		(1<<0)
+#define HCB_BIT_Y		(1<<1)
+
+struct hcb_root {
+	volatile uintptr_t	origo;
+};
+
+static struct hcb_root	hcb_root;
+
+static VSTAILQ_HEAD(, hcb_y)	cool_y = VSTAILQ_HEAD_INITIALIZER(cool_y);
+static VSTAILQ_HEAD(, hcb_y)	dead_y = VSTAILQ_HEAD_INITIALIZER(dead_y);
+static VTAILQ_HEAD(, objhead)	cool_h = VTAILQ_HEAD_INITIALIZER(cool_h);
+static VTAILQ_HEAD(, objhead)	dead_h = VTAILQ_HEAD_INITIALIZER(dead_h);
+
+/*---------------------------------------------------------------------
+ * Pointer accessor functions
+ */
+static int
+hcb_is_node(uintptr_t u)
+{
+
+	return (u & HCB_BIT_NODE);
+}
+
+static int
+hcb_is_y(uintptr_t u)
+{
+
+	return (u & HCB_BIT_Y);
+}
+
+static uintptr_t
+hcb_r_node(struct objhead *n)
+{
+
+	assert(!((uintptr_t)n & (HCB_BIT_NODE|HCB_BIT_Y)));
+	return (HCB_BIT_NODE | (uintptr_t)n);
+}
+
+static struct objhead *
+hcb_l_node(uintptr_t u)
+{
+
+	assert(u & HCB_BIT_NODE);
+	assert(!(u & HCB_BIT_Y));
+	return ((struct objhead *)(u & ~HCB_BIT_NODE));
+}
+
+static uintptr_t
+hcb_r_y(struct hcb_y *y)
+{
+
+	CHECK_OBJ_NOTNULL(y, HCB_Y_MAGIC);
+	assert(!((uintptr_t)y & (HCB_BIT_NODE|HCB_BIT_Y)));
+	return (HCB_BIT_Y | (uintptr_t)y);
+}
+
+static struct hcb_y *
+hcb_l_y(uintptr_t u)
+{
+
+	assert(!(u & HCB_BIT_NODE));
+	assert(u & HCB_BIT_Y);
+	return ((struct hcb_y *)(u & ~HCB_BIT_Y));
+}
+
+/*---------------------------------------------------------------------
+ * Find the "critical" bit that separates these two digests
+ */
+
+static unsigned
+hcb_crit_bit(const struct objhead *oh1, const struct objhead *oh2,
+    struct hcb_y *y)
+{
+	unsigned char u, r;
+
+	CHECK_OBJ_NOTNULL(y, HCB_Y_MAGIC);
+	for (u = 0; u < DIGEST_LEN && oh1->digest[u] == oh2->digest[u]; u++)
+		;
+	assert(u < DIGEST_LEN);
+	r = hcb_bits(oh1->digest[u], oh2->digest[u]);
+	y->ptr = u;
+	y->bitmask = 0x80 >> r;
+	y->critbit = u * 8 + r;
+	return (y->critbit);
+}
+
+/*---------------------------------------------------------------------
+ * Unless we have the lock, we need to be very careful about pointer
+ * references into the tree, we cannot trust things to be the same
+ * in two consequtive memory accesses.
+ */
+
+static struct objhead *
+hcb_insert(struct worker *wrk, struct hcb_root *root, struct objhead *oh, int has_lock)
+{
+	volatile uintptr_t *p;
+	uintptr_t pp;
+	struct hcb_y *y, *y2;
+	struct objhead *oh2;
+	unsigned s, s2;
+
+	p = &root->origo;
+	pp = *p;
+	if (pp == 0) {
+		if (!has_lock)
+			return (NULL);
+		*p = hcb_r_node(oh);
+		return (oh);
+	}
+
+	while(hcb_is_y(pp)) {
+		y = hcb_l_y(pp);
+		CHECK_OBJ_NOTNULL(y, HCB_Y_MAGIC);
+		assert(y->ptr < DIGEST_LEN);
+		s = (oh->digest[y->ptr] & y->bitmask) != 0;
+		assert(s < 2);
+		p = &y->leaf[s];
+		pp = *p;
+	}
+
+	if (pp == 0) {
+		/* We raced hcb_delete and got a NULL pointer */
+		assert(!has_lock);
+		return (NULL);
+	}
+
+	assert(hcb_is_node(pp));
+
+	/* We found a node, does it match ? */
+	oh2 = hcb_l_node(pp);
+	CHECK_OBJ_NOTNULL(oh2, OBJHEAD_MAGIC);
+	if (!memcmp(oh2->digest, oh->digest, DIGEST_LEN))
+		return (oh2);
+
+	if (!has_lock)
+		return (NULL);
+
+	/* Insert */
+
+	CAST_OBJ_NOTNULL(y2, wrk->nhashpriv, HCB_Y_MAGIC);
+	wrk->nhashpriv = NULL;
+	(void)hcb_crit_bit(oh, oh2, y2);
+	s2 = (oh->digest[y2->ptr] & y2->bitmask) != 0;
+	assert(s2 < 2);
+	y2->leaf[s2] = hcb_r_node(oh);
+	s2 = 1-s2;
+
+	p = &root->origo;
+	assert(*p != 0);
+
+	while(hcb_is_y(*p)) {
+		y = hcb_l_y(*p);
+		CHECK_OBJ_NOTNULL(y, HCB_Y_MAGIC);
+		assert(y->critbit != y2->critbit);
+		if (y->critbit > y2->critbit)
+			break;
+		assert(y->ptr < DIGEST_LEN);
+		s = (oh->digest[y->ptr] & y->bitmask) != 0;
+		assert(s < 2);
+		p = &y->leaf[s];
+	}
+	y2->leaf[s2] = *p;
+	VWMB();
+	*p = hcb_r_y(y2);
+	return(oh);
+}
+
+/*--------------------------------------------------------------------*/
+
+static void
+hcb_delete(struct hcb_root *r, struct objhead *oh)
+{
+	struct hcb_y *y;
+	volatile uintptr_t *p;
+	unsigned s;
+
+	if (r->origo == hcb_r_node(oh)) {
+		r->origo = 0;
+		return;
+	}
+	p = &r->origo;
+	assert(hcb_is_y(*p));
+
+	y = NULL;
+	while(1) {
+		assert(hcb_is_y(*p));
+		y = hcb_l_y(*p);
+		assert(y->ptr < DIGEST_LEN);
+		s = (oh->digest[y->ptr] & y->bitmask) != 0;
+		assert(s < 2);
+		if (y->leaf[s] == hcb_r_node(oh)) {
+			*p = y->leaf[1 - s];
+			VSTAILQ_INSERT_TAIL(&cool_y, y, list);
+			return;
+		}
+		p = &y->leaf[s];
+	}
+}
+
+/*--------------------------------------------------------------------*/
+
+static void
+dumptree(struct cli *cli, uintptr_t p, int indent)
+{
+	int i;
+	const struct objhead *oh;
+	const struct hcb_y *y;
+
+	if (p == 0)
+		return;
+	if (hcb_is_node(p)) {
+		oh = hcb_l_node(p);
+		VCLI_Out(cli, "%*.*sN %d r%u <%02x%02x%02x...>\n",
+		    indent, indent, "", indent / 2, oh->refcnt,
+		    oh->digest[0], oh->digest[1], oh->digest[2]);
+		return;
+	}
+	assert(hcb_is_y(p));
+	y = hcb_l_y(p);
+	VCLI_Out(cli, "%*.*sY c %u p %u b %02x i %d\n",
+	    indent, indent, "",
+	    y->critbit, y->ptr, y->bitmask, indent / 2);
+	indent += 2;
+	for (i = 0; i < 2; i++)
+		dumptree(cli, y->leaf[i], indent);
+}
+
+static void
+hcb_dump(struct cli *cli, const char * const *av, void *priv)
+{
+
+	(void)priv;
+	(void)av;
+	VCLI_Out(cli, "HCB dump:\n");
+	dumptree(cli, hcb_root.origo, 0);
+	VCLI_Out(cli, "Coollist:\n");
+}
+
+static struct cli_proto hcb_cmds[] = {
+	{ "hcb.dump", "hcb.dump", "dump HCB tree\n", 0, 0, "d", hcb_dump },
+	{ NULL }
+};
+
+/*--------------------------------------------------------------------*/
+
+static void *
+hcb_cleaner(void *priv)
+{
+	struct hcb_y *y, *y2;
+	struct worker ww;
+	struct objhead *oh, *oh2;
+
+	memset(&ww, 0, sizeof ww);
+	ww.magic = WORKER_MAGIC;
+
+	THR_SetName("hcb_cleaner");
+	(void)priv;
+	while (1) {
+		VSTAILQ_FOREACH_SAFE(y, &dead_y, list, y2) {
+			VSTAILQ_REMOVE_HEAD(&dead_y, list);
+			FREE_OBJ(y);
+		}
+		VTAILQ_FOREACH_SAFE(oh, &dead_h, hoh_list, oh2) {
+			VTAILQ_REMOVE(&dead_h, oh, hoh_list);
+			HSH_DeleteObjHead(&ww, oh);
+		}
+		Lck_Lock(&hcb_mtx);
+		VSTAILQ_CONCAT(&dead_y, &cool_y);
+		VTAILQ_CONCAT(&dead_h, &cool_h, hoh_list);
+		Lck_Unlock(&hcb_mtx);
+		WRK_SumStat(&ww);
+		VTIM_sleep(params->critbit_cooloff);
+	}
+	NEEDLESS_RETURN(NULL);
+}
+
+/*--------------------------------------------------------------------*/
+
+static void
+hcb_start(void)
+{
+	struct objhead *oh = NULL;
+	pthread_t tp;
+
+	(void)oh;
+	CLI_AddFuncs(hcb_cmds);
+	Lck_New(&hcb_mtx, lck_hcb);
+	AZ(pthread_create(&tp, NULL, hcb_cleaner, NULL));
+	memset(&hcb_root, 0, sizeof hcb_root);
+	hcb_build_bittbl();
+}
+
+static int
+hcb_deref(struct objhead *oh)
+{
+	int r;
+
+	r = 1;
+	CHECK_OBJ_NOTNULL(oh, OBJHEAD_MAGIC);
+	Lck_Lock(&oh->mtx);
+	assert(oh->refcnt > 0);
+	oh->refcnt--;
+	if (oh->refcnt == 0) {
+		Lck_Lock(&hcb_mtx);
+		hcb_delete(&hcb_root, oh);
+		VTAILQ_INSERT_TAIL(&cool_h, oh, hoh_list);
+		Lck_Unlock(&hcb_mtx);
+		assert(VTAILQ_EMPTY(&oh->objcs));
+		AZ(oh->waitinglist);
+	}
+	Lck_Unlock(&oh->mtx);
+#ifdef PHK
+	fprintf(stderr, "hcb_defef %d %d <%s>\n", __LINE__, r, oh->hash);
+#endif
+	return (r);
+}
+
+static struct objhead *
+hcb_lookup(const struct sess *sp, struct objhead *noh)
+{
+	struct objhead *oh;
+	struct hcb_y *y;
+	unsigned u;
+	unsigned with_lock;
+
+	(void)sp;
+
+	with_lock = 0;
+	while (1) {
+		if (with_lock) {
+			CAST_OBJ_NOTNULL(y, sp->wrk->nhashpriv, HCB_Y_MAGIC);
+			Lck_Lock(&hcb_mtx);
+			VSC_C_main->hcb_lock++;
+			assert(noh->refcnt == 1);
+			oh = hcb_insert(sp->wrk, &hcb_root, noh, 1);
+			Lck_Unlock(&hcb_mtx);
+		} else {
+			VSC_C_main->hcb_nolock++;
+			oh = hcb_insert(sp->wrk, &hcb_root, noh, 0);
+		}
+
+		if (oh != NULL && oh == noh) {
+			/* Assert that we only muck with the tree with a lock */
+			assert(with_lock);
+			VSC_C_main->hcb_insert++;
+			assert(oh->refcnt > 0);
+			return (oh);
+		}
+
+		if (oh == NULL) {
+			assert(!with_lock);
+			/* Try again, with lock */
+			with_lock = 1;
+			continue;
+		}
+
+		CHECK_OBJ_NOTNULL(noh, OBJHEAD_MAGIC);
+		Lck_Lock(&oh->mtx);
+		/*
+		 * A refcount of zero indicates that the tree changed
+		 * under us, so fall through and try with the lock held.
+		 */
+		u = oh->refcnt;
+		if (u > 0)
+			oh->refcnt++;
+		else
+			with_lock = 1;
+		Lck_Unlock(&oh->mtx);
+		if (u > 0)
+			return (oh);
+	}
+}
+
+static void
+hcb_prep(const struct sess *sp)
+{
+	struct hcb_y *y;
+
+	if (sp->wrk->nhashpriv == NULL) {
+		ALLOC_OBJ(y, HCB_Y_MAGIC);
+		sp->wrk->nhashpriv = y;
+	}
+}
+
+const struct hash_slinger hcb_slinger = {
+	.magic  =	SLINGER_MAGIC,
+	.name   =	"critbit",
+	.start  =	hcb_start,
+	.lookup =	hcb_lookup,
+	.prep =		hcb_prep,
+	.deref  =	hcb_deref,
+};
diff --git a/bin/varnishd/hash/hash_simple_list.c b/bin/varnishd/hash/hash_simple_list.c
new file mode 100644
index 0000000..1a0cae5
--- /dev/null
+++ b/bin/varnishd/hash/hash_simple_list.c
@@ -0,0 +1,118 @@
+/*-
+ * Copyright (c) 2006 Verdens Gang AS
+ * Copyright (c) 2006-2009 Varnish Software AS
+ * All rights reserved.
+ *
+ * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This is the reference hash(/lookup) implementation
+ */
+
+#include "config.h"
+
+#include "cache.h"
+
+#include "hash/hash_slinger.h"
+
+/*--------------------------------------------------------------------*/
+
+static VTAILQ_HEAD(, objhead)	hsl_head = VTAILQ_HEAD_INITIALIZER(hsl_head);
+static struct lock hsl_mtx;
+
+/*--------------------------------------------------------------------
+ * The ->init method is called during process start and allows
+ * initialization to happen before the first lookup.
+ */
+
+static void
+hsl_start(void)
+{
+
+	Lck_New(&hsl_mtx, lck_hsl);
+}
+
+/*--------------------------------------------------------------------
+ * Lookup and possibly insert element.
+ * If nobj != NULL and the lookup does not find key, nobj is inserted.
+ * If nobj == NULL and the lookup does not find key, NULL is returned.
+ * A reference to the returned object is held.
+ */
+
+static struct objhead *
+hsl_lookup(const struct sess *sp, struct objhead *noh)
+{
+	struct objhead *oh;
+	int i;
+
+	CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
+	CHECK_OBJ_NOTNULL(noh, OBJHEAD_MAGIC);
+	Lck_Lock(&hsl_mtx);
+	VTAILQ_FOREACH(oh, &hsl_head, hoh_list) {
+		i = memcmp(oh->digest, noh->digest, sizeof oh->digest);
+		if (i < 0)
+			continue;
+		if (i > 0)
+			break;
+		oh->refcnt++;
+		Lck_Unlock(&hsl_mtx);
+		return (oh);
+	}
+
+	if (oh != NULL)
+		VTAILQ_INSERT_BEFORE(oh, noh, hoh_list);
+	else
+		VTAILQ_INSERT_TAIL(&hsl_head, noh, hoh_list);
+
+	Lck_Unlock(&hsl_mtx);
+	return (noh);
+}
+
+/*--------------------------------------------------------------------
+ * Dereference and if no references are left, free.
+ */
+
+static int
+hsl_deref(struct objhead *oh)
+{
+	int ret;
+
+	Lck_Lock(&hsl_mtx);
+	if (--oh->refcnt == 0) {
+		VTAILQ_REMOVE(&hsl_head, oh, hoh_list);
+		ret = 0;
+	} else
+		ret = 1;
+	Lck_Unlock(&hsl_mtx);
+	return (ret);
+}
+
+/*--------------------------------------------------------------------*/
+
+const struct hash_slinger hsl_slinger = {
+	.magic	=	SLINGER_MAGIC,
+	.name	=	"simple",
+	.start	=	hsl_start,
+	.lookup =	hsl_lookup,
+	.deref	=	hsl_deref,
+};
diff --git a/bin/varnishd/hash/hash_slinger.h b/bin/varnishd/hash/hash_slinger.h
new file mode 100644
index 0000000..2c142cf
--- /dev/null
+++ b/bin/varnishd/hash/hash_slinger.h
@@ -0,0 +1,104 @@
+/*-
+ * Copyright (c) 2006 Verdens Gang AS
+ * Copyright (c) 2006-2010 Varnish Software AS
+ * All rights reserved.
+ *
+ * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+struct sess;
+struct worker;
+struct object;
+
+typedef void hash_init_f(int ac, char * const *av);
+typedef void hash_start_f(void);
+typedef void hash_prep_f(const struct sess *sp);
+typedef struct objhead *
+    hash_lookup_f(const struct sess *sp, struct objhead *nobj);
+typedef int hash_deref_f(struct objhead *obj);
+
+struct hash_slinger {
+	unsigned		magic;
+#define SLINGER_MAGIC		0x1b720cba
+	const char		*name;
+	hash_init_f		*init;
+	hash_start_f		*start;
+	hash_prep_f		*prep;
+	hash_lookup_f		*lookup;
+	hash_deref_f		*deref;
+};
+
+/* cache_hash.c */
+void HSH_Prealloc(const struct sess *sp);
+void HSH_Cleanup(struct worker *w);
+struct objcore *HSH_Lookup(struct sess *sp, struct objhead **poh);
+void HSH_Unbusy(const struct sess *sp);
+void HSH_Ref(struct objcore *o);
+void HSH_Drop(struct sess *sp);
+void HSH_Init(void);
+void HSH_AddString(const struct sess *sp, const char *str);
+struct objcore *HSH_Insert(const struct sess *sp);
+void HSH_Purge(const struct sess *, struct objhead *, double ttl, double grace);
+void HSH_config(const char *h_arg);
+
+#ifdef VARNISH_CACHE_CHILD
+
+struct waitinglist {
+	unsigned		magic;
+#define WAITINGLIST_MAGIC	0x063a477a
+	VTAILQ_HEAD(, sess)	list;
+};
+
+struct objhead {
+	unsigned		magic;
+#define OBJHEAD_MAGIC		0x1b96615d
+
+	int			refcnt;
+	struct lock		mtx;
+	VTAILQ_HEAD(,objcore)	objcs;
+	unsigned char		digest[DIGEST_LEN];
+	struct waitinglist	*waitinglist;
+
+	/*----------------------------------------------------
+	 * The fields below are for the sole private use of
+	 * the hash implementation(s).
+	 */
+	union {
+		struct {
+			VTAILQ_ENTRY(objhead)	u_n_hoh_list;
+			void			*u_n_hoh_head;
+		} n;
+	} _u;
+#define hoh_list _u.n.u_n_hoh_list
+#define hoh_head _u.n.u_n_hoh_head
+};
+
+void HSH_DeleteObjHead(struct worker *w, struct objhead *oh);
+int HSH_Deref(struct worker *w, struct objcore *oc, struct object **o);
+#endif /* VARNISH_CACHE_CHILD */
+
+extern const struct hash_slinger hsl_slinger;
+extern const struct hash_slinger hcl_slinger;
+extern const struct hash_slinger hcb_slinger;
diff --git a/bin/varnishd/hash_classic.c b/bin/varnishd/hash_classic.c
deleted file mode 100644
index fc88757..0000000
--- a/bin/varnishd/hash_classic.c
+++ /dev/null
@@ -1,184 +0,0 @@
-/*-
- * Copyright (c) 2006 Verdens Gang AS
- * Copyright (c) 2006-2009 Varnish Software AS
- * All rights reserved.
- *
- * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * A classic bucketed hash
- */
-
-#include "config.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "cache.h"
-
-#include "hash_slinger.h"
-
-/*--------------------------------------------------------------------*/
-
-struct hcl_hd {
-	unsigned		magic;
-#define HCL_HEAD_MAGIC		0x0f327016
-	VTAILQ_HEAD(, objhead)	head;
-	struct lock		mtx;
-};
-
-static unsigned			hcl_nhash = 16383;
-static struct hcl_hd		*hcl_head;
-
-/*--------------------------------------------------------------------
- * The ->init method allows the management process to pass arguments
- */
-
-static void
-hcl_init(int ac, char * const *av)
-{
-	int i;
-	unsigned u;
-
-	if (ac == 0)
-		return;
-	if (ac > 1)
-		ARGV_ERR("(-hclassic) too many arguments\n");
-	i = sscanf(av[0], "%u", &u);
-	if (i <= 0 || u == 0)
-		return;
-	if (u > 2 && !(u & (u - 1))) {
-		fprintf(stderr,
-		    "NOTE:\n"
-		    "\tA power of two number of hash buckets is "
-		    "marginally less efficient\n"
-		    "\twith systematic URLs.  Reducing by one"
-		    " hash bucket.\n");
-		u--;
-	}
-	hcl_nhash = u;
-	fprintf(stderr, "Classic hash: %u buckets\n", hcl_nhash);
-	return;
-}
-
-/*--------------------------------------------------------------------
- * The ->start method is called during cache process start and allows
- * initialization to happen before the first lookup.
- */
-
-static void
-hcl_start(void)
-{
-	unsigned u;
-
-	hcl_head = calloc(sizeof *hcl_head, hcl_nhash);
-	XXXAN(hcl_head);
-
-	for (u = 0; u < hcl_nhash; u++) {
-		VTAILQ_INIT(&hcl_head[u].head);
-		Lck_New(&hcl_head[u].mtx, lck_hcl);
-		hcl_head[u].magic = HCL_HEAD_MAGIC;
-	}
-}
-
-/*--------------------------------------------------------------------
- * Lookup and possibly insert element.
- * If nobj != NULL and the lookup does not find key, nobj is inserted.
- * If nobj == NULL and the lookup does not find key, NULL is returned.
- * A reference to the returned object is held.
- * We use a two-pass algorithm to handle inserts as they are quite
- * rare and collisions even rarer.
- */
-
-static struct objhead *
-hcl_lookup(const struct sess *sp, struct objhead *noh)
-{
-	struct objhead *oh;
-	struct hcl_hd *hp;
-	unsigned u1, digest;
-	int i;
-
-	CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
-	CHECK_OBJ_NOTNULL(noh, OBJHEAD_MAGIC);
-
-	assert(sizeof noh->digest > sizeof digest);
-	memcpy(&digest, noh->digest, sizeof digest);
-	u1 = digest % hcl_nhash;
-	hp = &hcl_head[u1];
-
-	Lck_Lock(&hp->mtx);
-	VTAILQ_FOREACH(oh, &hp->head, hoh_list) {
-		i = memcmp(oh->digest, noh->digest, sizeof oh->digest);
-		if (i < 0)
-			continue;
-		if (i > 0)
-			break;
-		oh->refcnt++;
-		Lck_Unlock(&hp->mtx);
-		return (oh);
-	}
-
-	if (oh != NULL)
-		VTAILQ_INSERT_BEFORE(oh, noh, hoh_list);
-	else
-		VTAILQ_INSERT_TAIL(&hp->head, noh, hoh_list);
-
-	noh->hoh_head = hp;
-
-	Lck_Unlock(&hp->mtx);
-	return (noh);
-}
-
-/*--------------------------------------------------------------------
- * Dereference and if no references are left, free.
- */
-
-static int
-hcl_deref(struct objhead *oh)
-{
-	struct hcl_hd *hp;
-	int ret;
-
-	CHECK_OBJ_NOTNULL(oh, OBJHEAD_MAGIC);
-	CAST_OBJ_NOTNULL(hp, oh->hoh_head, HCL_HEAD_MAGIC);
-	assert(oh->refcnt > 0);
-	Lck_Lock(&hp->mtx);
-	if (--oh->refcnt == 0) {
-		VTAILQ_REMOVE(&hp->head, oh, hoh_list);
-		ret = 0;
-	} else
-		ret = 1;
-	Lck_Unlock(&hp->mtx);
-	return (ret);
-}
-
-/*--------------------------------------------------------------------*/
-
-const struct hash_slinger hcl_slinger = {
-	.magic	=	SLINGER_MAGIC,
-	.name	=	"classic",
-	.init	=	hcl_init,
-	.start	=	hcl_start,
-	.lookup =	hcl_lookup,
-	.deref	=	hcl_deref,
-};
diff --git a/bin/varnishd/hash_critbit.c b/bin/varnishd/hash_critbit.c
deleted file mode 100644
index 78bda7a..0000000
--- a/bin/varnishd/hash_critbit.c
+++ /dev/null
@@ -1,492 +0,0 @@
-/*-
- * Copyright (c) 2008-2010 Varnish Software AS
- * All rights reserved.
- *
- * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * A Crit Bit tree based hash
- */
-
-// #define PHK
-
-#include "config.h"
-
-#include <stdlib.h>
-
-#include "cache.h"
-
-#include "hash_slinger.h"
-#include "vcli_priv.h"
-#include "vmb.h"
-#include "vtim.h"
-
-static struct lock hcb_mtx;
-
-/*---------------------------------------------------------------------
- * Table for finding out how many bits two bytes have in common,
- * counting from the MSB towards the LSB.
- * ie:
- *	hcb_bittbl[0x01 ^ 0x22] == 2
- *	hcb_bittbl[0x10 ^ 0x0b] == 3
- *
- */
-
-static unsigned char hcb_bittbl[256];
-
-static unsigned char
-hcb_bits(unsigned char x, unsigned char y)
-{
-	return hcb_bittbl[x ^ y];
-}
-
-static void
-hcb_build_bittbl(void)
-{
-	unsigned char x;
-	unsigned y;
-
-	y = 0;
-	for (x = 0; x < 8; x++)
-		for (; y < (1U << x); y++)
-			hcb_bittbl[y] = 8 - x;
-
-	/* Quick asserts for sanity check */
-	assert(hcb_bits(0x34, 0x34) == 8);
-	assert(hcb_bits(0xaa, 0x55) == 0);
-	assert(hcb_bits(0x01, 0x22) == 2);
-	assert(hcb_bits(0x10, 0x0b) == 3);
-}
-
-/*---------------------------------------------------------------------
- * For space reasons we overload the two pointers with two different
- * kinds of of pointers.  We cast them to uintptr_t's and abuse the
- * low two bits to tell them apart, assuming that Varnish will never
- * run on machines with less than 32bit alignment.
- *
- * Asserts will explode if these assumptions are not met.
- */
-
-struct hcb_y {
-	unsigned		magic;
-#define HCB_Y_MAGIC		0x125c4bd2
-	unsigned short		critbit;
-	unsigned char		ptr;
-	unsigned char		bitmask;
-	volatile uintptr_t	leaf[2];
-	VSTAILQ_ENTRY(hcb_y)	list;
-};
-
-#define HCB_BIT_NODE		(1<<0)
-#define HCB_BIT_Y		(1<<1)
-
-struct hcb_root {
-	volatile uintptr_t	origo;
-};
-
-static struct hcb_root	hcb_root;
-
-static VSTAILQ_HEAD(, hcb_y)	cool_y = VSTAILQ_HEAD_INITIALIZER(cool_y);
-static VSTAILQ_HEAD(, hcb_y)	dead_y = VSTAILQ_HEAD_INITIALIZER(dead_y);
-static VTAILQ_HEAD(, objhead)	cool_h = VTAILQ_HEAD_INITIALIZER(cool_h);
-static VTAILQ_HEAD(, objhead)	dead_h = VTAILQ_HEAD_INITIALIZER(dead_h);
-
-/*---------------------------------------------------------------------
- * Pointer accessor functions
- */
-static int
-hcb_is_node(uintptr_t u)
-{
-
-	return (u & HCB_BIT_NODE);
-}
-
-static int
-hcb_is_y(uintptr_t u)
-{
-
-	return (u & HCB_BIT_Y);
-}
-
-static uintptr_t
-hcb_r_node(struct objhead *n)
-{
-
-	assert(!((uintptr_t)n & (HCB_BIT_NODE|HCB_BIT_Y)));
-	return (HCB_BIT_NODE | (uintptr_t)n);
-}
-
-static struct objhead *
-hcb_l_node(uintptr_t u)
-{
-
-	assert(u & HCB_BIT_NODE);
-	assert(!(u & HCB_BIT_Y));
-	return ((struct objhead *)(u & ~HCB_BIT_NODE));
-}
-
-static uintptr_t
-hcb_r_y(struct hcb_y *y)
-{
-
-	CHECK_OBJ_NOTNULL(y, HCB_Y_MAGIC);
-	assert(!((uintptr_t)y & (HCB_BIT_NODE|HCB_BIT_Y)));
-	return (HCB_BIT_Y | (uintptr_t)y);
-}
-
-static struct hcb_y *
-hcb_l_y(uintptr_t u)
-{
-
-	assert(!(u & HCB_BIT_NODE));
-	assert(u & HCB_BIT_Y);
-	return ((struct hcb_y *)(u & ~HCB_BIT_Y));
-}
-
-/*---------------------------------------------------------------------
- * Find the "critical" bit that separates these two digests
- */
-
-static unsigned
-hcb_crit_bit(const struct objhead *oh1, const struct objhead *oh2,
-    struct hcb_y *y)
-{
-	unsigned char u, r;
-
-	CHECK_OBJ_NOTNULL(y, HCB_Y_MAGIC);
-	for (u = 0; u < DIGEST_LEN && oh1->digest[u] == oh2->digest[u]; u++)
-		;
-	assert(u < DIGEST_LEN);
-	r = hcb_bits(oh1->digest[u], oh2->digest[u]);
-	y->ptr = u;
-	y->bitmask = 0x80 >> r;
-	y->critbit = u * 8 + r;
-	return (y->critbit);
-}
-
-/*---------------------------------------------------------------------
- * Unless we have the lock, we need to be very careful about pointer
- * references into the tree, we cannot trust things to be the same
- * in two consequtive memory accesses.
- */
-
-static struct objhead *
-hcb_insert(struct worker *wrk, struct hcb_root *root, struct objhead *oh, int has_lock)
-{
-	volatile uintptr_t *p;
-	uintptr_t pp;
-	struct hcb_y *y, *y2;
-	struct objhead *oh2;
-	unsigned s, s2;
-
-	p = &root->origo;
-	pp = *p;
-	if (pp == 0) {
-		if (!has_lock)
-			return (NULL);
-		*p = hcb_r_node(oh);
-		return (oh);
-	}
-
-	while(hcb_is_y(pp)) {
-		y = hcb_l_y(pp);
-		CHECK_OBJ_NOTNULL(y, HCB_Y_MAGIC);
-		assert(y->ptr < DIGEST_LEN);
-		s = (oh->digest[y->ptr] & y->bitmask) != 0;
-		assert(s < 2);
-		p = &y->leaf[s];
-		pp = *p;
-	}
-
-	if (pp == 0) {
-		/* We raced hcb_delete and got a NULL pointer */
-		assert(!has_lock);
-		return (NULL);
-	}
-
-	assert(hcb_is_node(pp));
-
-	/* We found a node, does it match ? */
-	oh2 = hcb_l_node(pp);
-	CHECK_OBJ_NOTNULL(oh2, OBJHEAD_MAGIC);
-	if (!memcmp(oh2->digest, oh->digest, DIGEST_LEN))
-		return (oh2);
-
-	if (!has_lock)
-		return (NULL);
-
-	/* Insert */
-
-	CAST_OBJ_NOTNULL(y2, wrk->nhashpriv, HCB_Y_MAGIC);
-	wrk->nhashpriv = NULL;
-	(void)hcb_crit_bit(oh, oh2, y2);
-	s2 = (oh->digest[y2->ptr] & y2->bitmask) != 0;
-	assert(s2 < 2);
-	y2->leaf[s2] = hcb_r_node(oh);
-	s2 = 1-s2;
-
-	p = &root->origo;
-	assert(*p != 0);
-
-	while(hcb_is_y(*p)) {
-		y = hcb_l_y(*p);
-		CHECK_OBJ_NOTNULL(y, HCB_Y_MAGIC);
-		assert(y->critbit != y2->critbit);
-		if (y->critbit > y2->critbit)
-			break;
-		assert(y->ptr < DIGEST_LEN);
-		s = (oh->digest[y->ptr] & y->bitmask) != 0;
-		assert(s < 2);
-		p = &y->leaf[s];
-	}
-	y2->leaf[s2] = *p;
-	VWMB();
-	*p = hcb_r_y(y2);
-	return(oh);
-}
-
-/*--------------------------------------------------------------------*/
-
-static void
-hcb_delete(struct hcb_root *r, struct objhead *oh)
-{
-	struct hcb_y *y;
-	volatile uintptr_t *p;
-	unsigned s;
-
-	if (r->origo == hcb_r_node(oh)) {
-		r->origo = 0;
-		return;
-	}
-	p = &r->origo;
-	assert(hcb_is_y(*p));
-
-	y = NULL;
-	while(1) {
-		assert(hcb_is_y(*p));
-		y = hcb_l_y(*p);
-		assert(y->ptr < DIGEST_LEN);
-		s = (oh->digest[y->ptr] & y->bitmask) != 0;
-		assert(s < 2);
-		if (y->leaf[s] == hcb_r_node(oh)) {
-			*p = y->leaf[1 - s];
-			VSTAILQ_INSERT_TAIL(&cool_y, y, list);
-			return;
-		}
-		p = &y->leaf[s];
-	}
-}
-
-/*--------------------------------------------------------------------*/
-
-static void
-dumptree(struct cli *cli, uintptr_t p, int indent)
-{
-	int i;
-	const struct objhead *oh;
-	const struct hcb_y *y;
-
-	if (p == 0)
-		return;
-	if (hcb_is_node(p)) {
-		oh = hcb_l_node(p);
-		VCLI_Out(cli, "%*.*sN %d r%u <%02x%02x%02x...>\n",
-		    indent, indent, "", indent / 2, oh->refcnt,
-		    oh->digest[0], oh->digest[1], oh->digest[2]);
-		return;
-	}
-	assert(hcb_is_y(p));
-	y = hcb_l_y(p);
-	VCLI_Out(cli, "%*.*sY c %u p %u b %02x i %d\n",
-	    indent, indent, "",
-	    y->critbit, y->ptr, y->bitmask, indent / 2);
-	indent += 2;
-	for (i = 0; i < 2; i++)
-		dumptree(cli, y->leaf[i], indent);
-}
-
-static void
-hcb_dump(struct cli *cli, const char * const *av, void *priv)
-{
-
-	(void)priv;
-	(void)av;
-	VCLI_Out(cli, "HCB dump:\n");
-	dumptree(cli, hcb_root.origo, 0);
-	VCLI_Out(cli, "Coollist:\n");
-}
-
-static struct cli_proto hcb_cmds[] = {
-	{ "hcb.dump", "hcb.dump", "dump HCB tree\n", 0, 0, "d", hcb_dump },
-	{ NULL }
-};
-
-/*--------------------------------------------------------------------*/
-
-static void *
-hcb_cleaner(void *priv)
-{
-	struct hcb_y *y, *y2;
-	struct worker ww;
-	struct objhead *oh, *oh2;
-
-	memset(&ww, 0, sizeof ww);
-	ww.magic = WORKER_MAGIC;
-
-	THR_SetName("hcb_cleaner");
-	(void)priv;
-	while (1) {
-		VSTAILQ_FOREACH_SAFE(y, &dead_y, list, y2) {
-			VSTAILQ_REMOVE_HEAD(&dead_y, list);
-			FREE_OBJ(y);
-		}
-		VTAILQ_FOREACH_SAFE(oh, &dead_h, hoh_list, oh2) {
-			VTAILQ_REMOVE(&dead_h, oh, hoh_list);
-			HSH_DeleteObjHead(&ww, oh);
-		}
-		Lck_Lock(&hcb_mtx);
-		VSTAILQ_CONCAT(&dead_y, &cool_y);
-		VTAILQ_CONCAT(&dead_h, &cool_h, hoh_list);
-		Lck_Unlock(&hcb_mtx);
-		WRK_SumStat(&ww);
-		VTIM_sleep(params->critbit_cooloff);
-	}
-	NEEDLESS_RETURN(NULL);
-}
-
-/*--------------------------------------------------------------------*/
-
-static void
-hcb_start(void)
-{
-	struct objhead *oh = NULL;
-	pthread_t tp;
-
-	(void)oh;
-	CLI_AddFuncs(hcb_cmds);
-	Lck_New(&hcb_mtx, lck_hcb);
-	AZ(pthread_create(&tp, NULL, hcb_cleaner, NULL));
-	memset(&hcb_root, 0, sizeof hcb_root);
-	hcb_build_bittbl();
-}
-
-static int
-hcb_deref(struct objhead *oh)
-{
-	int r;
-
-	r = 1;
-	CHECK_OBJ_NOTNULL(oh, OBJHEAD_MAGIC);
-	Lck_Lock(&oh->mtx);
-	assert(oh->refcnt > 0);
-	oh->refcnt--;
-	if (oh->refcnt == 0) {
-		Lck_Lock(&hcb_mtx);
-		hcb_delete(&hcb_root, oh);
-		VTAILQ_INSERT_TAIL(&cool_h, oh, hoh_list);
-		Lck_Unlock(&hcb_mtx);
-		assert(VTAILQ_EMPTY(&oh->objcs));
-		AZ(oh->waitinglist);
-	}
-	Lck_Unlock(&oh->mtx);
-#ifdef PHK
-	fprintf(stderr, "hcb_defef %d %d <%s>\n", __LINE__, r, oh->hash);
-#endif
-	return (r);
-}
-
-static struct objhead *
-hcb_lookup(const struct sess *sp, struct objhead *noh)
-{
-	struct objhead *oh;
-	struct hcb_y *y;
-	unsigned u;
-	unsigned with_lock;
-
-	(void)sp;
-
-	with_lock = 0;
-	while (1) {
-		if (with_lock) {
-			CAST_OBJ_NOTNULL(y, sp->wrk->nhashpriv, HCB_Y_MAGIC);
-			Lck_Lock(&hcb_mtx);
-			VSC_C_main->hcb_lock++;
-			assert(noh->refcnt == 1);
-			oh = hcb_insert(sp->wrk, &hcb_root, noh, 1);
-			Lck_Unlock(&hcb_mtx);
-		} else {
-			VSC_C_main->hcb_nolock++;
-			oh = hcb_insert(sp->wrk, &hcb_root, noh, 0);
-		}
-
-		if (oh != NULL && oh == noh) {
-			/* Assert that we only muck with the tree with a lock */
-			assert(with_lock);
-			VSC_C_main->hcb_insert++;
-			assert(oh->refcnt > 0);
-			return (oh);
-		}
-
-		if (oh == NULL) {
-			assert(!with_lock);
-			/* Try again, with lock */
-			with_lock = 1;
-			continue;
-		}
-
-		CHECK_OBJ_NOTNULL(noh, OBJHEAD_MAGIC);
-		Lck_Lock(&oh->mtx);
-		/*
-		 * A refcount of zero indicates that the tree changed
-		 * under us, so fall through and try with the lock held.
-		 */
-		u = oh->refcnt;
-		if (u > 0)
-			oh->refcnt++;
-		else
-			with_lock = 1;
-		Lck_Unlock(&oh->mtx);
-		if (u > 0)
-			return (oh);
-	}
-}
-
-static void
-hcb_prep(const struct sess *sp)
-{
-	struct hcb_y *y;
-
-	if (sp->wrk->nhashpriv == NULL) {
-		ALLOC_OBJ(y, HCB_Y_MAGIC);
-		sp->wrk->nhashpriv = y;
-	}
-}
-
-const struct hash_slinger hcb_slinger = {
-	.magic  =	SLINGER_MAGIC,
-	.name   =	"critbit",
-	.start  =	hcb_start,
-	.lookup =	hcb_lookup,
-	.prep =		hcb_prep,
-	.deref  =	hcb_deref,
-};
diff --git a/bin/varnishd/hash_simple_list.c b/bin/varnishd/hash_simple_list.c
deleted file mode 100644
index c1c17da..0000000
--- a/bin/varnishd/hash_simple_list.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/*-
- * Copyright (c) 2006 Verdens Gang AS
- * Copyright (c) 2006-2009 Varnish Software AS
- * All rights reserved.
- *
- * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * This is the reference hash(/lookup) implementation
- */
-
-#include "config.h"
-
-#include "cache.h"
-
-#include "hash_slinger.h"
-
-/*--------------------------------------------------------------------*/
-
-static VTAILQ_HEAD(, objhead)	hsl_head = VTAILQ_HEAD_INITIALIZER(hsl_head);
-static struct lock hsl_mtx;
-
-/*--------------------------------------------------------------------
- * The ->init method is called during process start and allows
- * initialization to happen before the first lookup.
- */
-
-static void
-hsl_start(void)
-{
-
-	Lck_New(&hsl_mtx, lck_hsl);
-}
-
-/*--------------------------------------------------------------------
- * Lookup and possibly insert element.
- * If nobj != NULL and the lookup does not find key, nobj is inserted.
- * If nobj == NULL and the lookup does not find key, NULL is returned.
- * A reference to the returned object is held.
- */
-
-static struct objhead *
-hsl_lookup(const struct sess *sp, struct objhead *noh)
-{
-	struct objhead *oh;
-	int i;
-
-	CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
-	CHECK_OBJ_NOTNULL(noh, OBJHEAD_MAGIC);
-	Lck_Lock(&hsl_mtx);
-	VTAILQ_FOREACH(oh, &hsl_head, hoh_list) {
-		i = memcmp(oh->digest, noh->digest, sizeof oh->digest);
-		if (i < 0)
-			continue;
-		if (i > 0)
-			break;
-		oh->refcnt++;
-		Lck_Unlock(&hsl_mtx);
-		return (oh);
-	}
-
-	if (oh != NULL)
-		VTAILQ_INSERT_BEFORE(oh, noh, hoh_list);
-	else
-		VTAILQ_INSERT_TAIL(&hsl_head, noh, hoh_list);
-
-	Lck_Unlock(&hsl_mtx);
-	return (noh);
-}
-
-/*--------------------------------------------------------------------
- * Dereference and if no references are left, free.
- */
-
-static int
-hsl_deref(struct objhead *oh)
-{
-	int ret;
-
-	Lck_Lock(&hsl_mtx);
-	if (--oh->refcnt == 0) {
-		VTAILQ_REMOVE(&hsl_head, oh, hoh_list);
-		ret = 0;
-	} else
-		ret = 1;
-	Lck_Unlock(&hsl_mtx);
-	return (ret);
-}
-
-/*--------------------------------------------------------------------*/
-
-const struct hash_slinger hsl_slinger = {
-	.magic	=	SLINGER_MAGIC,
-	.name	=	"simple",
-	.start	=	hsl_start,
-	.lookup =	hsl_lookup,
-	.deref	=	hsl_deref,
-};
diff --git a/bin/varnishd/hash_slinger.h b/bin/varnishd/hash_slinger.h
deleted file mode 100644
index 2c142cf..0000000
--- a/bin/varnishd/hash_slinger.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/*-
- * Copyright (c) 2006 Verdens Gang AS
- * Copyright (c) 2006-2010 Varnish Software AS
- * All rights reserved.
- *
- * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- */
-
-struct sess;
-struct worker;
-struct object;
-
-typedef void hash_init_f(int ac, char * const *av);
-typedef void hash_start_f(void);
-typedef void hash_prep_f(const struct sess *sp);
-typedef struct objhead *
-    hash_lookup_f(const struct sess *sp, struct objhead *nobj);
-typedef int hash_deref_f(struct objhead *obj);
-
-struct hash_slinger {
-	unsigned		magic;
-#define SLINGER_MAGIC		0x1b720cba
-	const char		*name;
-	hash_init_f		*init;
-	hash_start_f		*start;
-	hash_prep_f		*prep;
-	hash_lookup_f		*lookup;
-	hash_deref_f		*deref;
-};
-
-/* cache_hash.c */
-void HSH_Prealloc(const struct sess *sp);
-void HSH_Cleanup(struct worker *w);
-struct objcore *HSH_Lookup(struct sess *sp, struct objhead **poh);
-void HSH_Unbusy(const struct sess *sp);
-void HSH_Ref(struct objcore *o);
-void HSH_Drop(struct sess *sp);
-void HSH_Init(void);
-void HSH_AddString(const struct sess *sp, const char *str);
-struct objcore *HSH_Insert(const struct sess *sp);
-void HSH_Purge(const struct sess *, struct objhead *, double ttl, double grace);
-void HSH_config(const char *h_arg);
-
-#ifdef VARNISH_CACHE_CHILD
-
-struct waitinglist {
-	unsigned		magic;
-#define WAITINGLIST_MAGIC	0x063a477a
-	VTAILQ_HEAD(, sess)	list;
-};
-
-struct objhead {
-	unsigned		magic;
-#define OBJHEAD_MAGIC		0x1b96615d
-
-	int			refcnt;
-	struct lock		mtx;
-	VTAILQ_HEAD(,objcore)	objcs;
-	unsigned char		digest[DIGEST_LEN];
-	struct waitinglist	*waitinglist;
-
-	/*----------------------------------------------------
-	 * The fields below are for the sole private use of
-	 * the hash implementation(s).
-	 */
-	union {
-		struct {
-			VTAILQ_ENTRY(objhead)	u_n_hoh_list;
-			void			*u_n_hoh_head;
-		} n;
-	} _u;
-#define hoh_list _u.n.u_n_hoh_list
-#define hoh_head _u.n.u_n_hoh_head
-};
-
-void HSH_DeleteObjHead(struct worker *w, struct objhead *oh);
-int HSH_Deref(struct worker *w, struct objcore *oc, struct object **o);
-#endif /* VARNISH_CACHE_CHILD */
-
-extern const struct hash_slinger hsl_slinger;
-extern const struct hash_slinger hcl_slinger;
-extern const struct hash_slinger hcb_slinger;
diff --git a/bin/varnishd/storage/storage_persistent.c b/bin/varnishd/storage/storage_persistent.c
index 84aef5c..02d244e 100644
--- a/bin/varnishd/storage/storage_persistent.c
+++ b/bin/varnishd/storage/storage_persistent.c
@@ -46,7 +46,7 @@
 #include "cache.h"
 #include "storage/storage.h"
 
-#include "hash_slinger.h"
+#include "hash/hash_slinger.h"
 #include "vcli.h"
 #include "vcli_priv.h"
 #include "vend.h"
diff --git a/bin/varnishd/storage/storage_persistent_silo.c b/bin/varnishd/storage/storage_persistent_silo.c
index 5393546..27f0c98 100644
--- a/bin/varnishd/storage/storage_persistent_silo.c
+++ b/bin/varnishd/storage/storage_persistent_silo.c
@@ -40,7 +40,7 @@
 #include "cache.h"
 #include "storage/storage.h"
 
-#include "hash_slinger.h"
+#include "hash/hash_slinger.h"
 #include "vsha256.h"
 #include "vtim.h"
 
diff --git a/bin/varnishd/varnishd.c b/bin/varnishd/varnishd.c
index 7fe72aa..e0654a3 100644
--- a/bin/varnishd/varnishd.c
+++ b/bin/varnishd/varnishd.c
@@ -45,7 +45,7 @@
 
 #include "mgt.h"
 
-#include "hash_slinger.h"
+#include "hash/hash_slinger.h"
 #include "heritage.h"
 #include "vav.h"
 #include "vcli.h"



More information about the varnish-commit mailing list