[master] 18edda6 Move the hashing implementations into a subdirectory where VMODs won't see them.
Poul-Henning Kamp
phk at varnish-cache.org
Wed Oct 12 19:09:25 CEST 2011
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