Commit 0bb46b22 authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

Implement the cooling period before objhead's are deleted in the

critbit hasher.



git-svn-id: http://www.varnish-cache.org/svn/trunk@3457 d4fa192b-c00b-0410-8231-f00ffab90ce4
parent 2026f147
...@@ -262,7 +262,6 @@ HSH_Lookup(struct sess *sp) ...@@ -262,7 +262,6 @@ HSH_Lookup(struct sess *sp)
HSH_Prealloc(sp); HSH_Prealloc(sp);
if (params->hash_sha256) { if (params->hash_sha256) {
SHA256_Final(sp->wrk->nobjhead->digest, sp->wrk->sha256ctx); SHA256_Final(sp->wrk->nobjhead->digest, sp->wrk->sha256ctx);
sp->wrk->nobjhead->digest_len = 32;
/* WSP(sp, SLT_Debug, "SHA256: <%.32s>", sha256); */ /* WSP(sp, SLT_Debug, "SHA256: <%.32s>", sha256); */
} }
......
...@@ -30,6 +30,8 @@ ...@@ -30,6 +30,8 @@
* A Crit Bit tree based hash * A Crit Bit tree based hash
*/ */
#define PHK 1
#include "config.h" #include "config.h"
#include <pthread.h> #include <pthread.h>
...@@ -42,6 +44,8 @@ ...@@ -42,6 +44,8 @@
static struct lock hcb_mtx; static struct lock hcb_mtx;
static VTAILQ_HEAD(,objhead) laylow = VTAILQ_HEAD_INITIALIZER(laylow);
/********************************************************************** /**********************************************************************
* Table for finding out how many bits two bytes have in common, * Table for finding out how many bits two bytes have in common,
* counting from the MSB towards the LSB. * counting from the MSB towards the LSB.
...@@ -160,7 +164,7 @@ hcb_crit_bit(const struct objhead *oh1, const struct objhead *oh2, struct hcb_y ...@@ -160,7 +164,7 @@ hcb_crit_bit(const struct objhead *oh1, const struct objhead *oh2, struct hcb_y
{ {
unsigned u, r; unsigned u, r;
for (u = 0; u < oh1->digest_len && oh1->digest[u] == oh2->digest[u]; u++) for (u = 0; u < DIGEST_LEN && oh1->digest[u] == oh2->digest[u]; u++)
; ;
r = hcb_bits(oh1->digest[u], oh2->digest[u]); r = hcb_bits(oh1->digest[u], oh2->digest[u]);
y->ptr = u; y->ptr = u;
...@@ -190,7 +194,7 @@ hcb_insert(struct hcb_root *root, struct objhead *oh, int has_lock) ...@@ -190,7 +194,7 @@ hcb_insert(struct hcb_root *root, struct objhead *oh, int has_lock)
while(hcb_is_y(*p)) { while(hcb_is_y(*p)) {
y = hcb_l_y(*p); y = hcb_l_y(*p);
if (y->ptr > oh->digest_len) if (y->ptr > DIGEST_LEN)
s = 0; s = 0;
else else
s = (oh->digest[y->ptr] & y->bitmask) != 0; s = (oh->digest[y->ptr] & y->bitmask) != 0;
...@@ -203,8 +207,7 @@ hcb_insert(struct hcb_root *root, struct objhead *oh, int has_lock) ...@@ -203,8 +207,7 @@ hcb_insert(struct hcb_root *root, struct objhead *oh, int has_lock)
/* We found a node, does it match ? */ /* We found a node, does it match ? */
oh2 = hcb_l_node(*p); oh2 = hcb_l_node(*p);
if (oh2->digest_len == oh->digest_len && if (!memcmp(oh2->digest, oh->digest, DIGEST_LEN))
!memcmp(oh2->digest, oh->digest, oh->digest_len))
return (oh2); return (oh2);
if (!has_lock) if (!has_lock)
...@@ -227,7 +230,7 @@ hcb_insert(struct hcb_root *root, struct objhead *oh, int has_lock) ...@@ -227,7 +230,7 @@ hcb_insert(struct hcb_root *root, struct objhead *oh, int has_lock)
y = hcb_l_y(*p); y = hcb_l_y(*p);
if (y->critbit > y2->critbit) if (y->critbit > y2->critbit)
break; break;
if (y->ptr > oh->digest_len) if (y->ptr > DIGEST_LEN)
s = 0; s = 0;
else else
s = (oh->digest[y->ptr] & y->bitmask) != 0; s = (oh->digest[y->ptr] & y->bitmask) != 0;
...@@ -259,7 +262,7 @@ hcb_delete(struct hcb_root *r, struct objhead *oh) ...@@ -259,7 +262,7 @@ hcb_delete(struct hcb_root *r, struct objhead *oh)
y = NULL; y = NULL;
while(hcb_is_y(*p)) { while(hcb_is_y(*p)) {
y = hcb_l_y(*p); y = hcb_l_y(*p);
if (y->ptr > oh->digest_len) if (y->ptr > DIGEST_LEN)
s = 0; s = 0;
else else
s = (oh->digest[y->ptr] & y->bitmask) != 0; s = (oh->digest[y->ptr] & y->bitmask) != 0;
...@@ -291,7 +294,7 @@ dumptree(uintptr_t p, int indent, FILE *fd) ...@@ -291,7 +294,7 @@ dumptree(uintptr_t p, int indent, FILE *fd)
if (hcb_is_node(p)) { if (hcb_is_node(p)) {
oh = hcb_l_node(p); oh = hcb_l_node(p);
fprintf(fd, "%*.*sN %u %u r%d <%02x%02x%02x...> <%s>\n", fprintf(fd, "%*.*sN %u %u r%d <%02x%02x%02x...> <%s>\n",
indent, indent, "", oh->digest_len, indent / 2, indent, indent, "", DIGEST_LEN, indent / 2,
oh->refcnt, oh->refcnt,
oh->digest[0], oh->digest[1], oh->digest[2], oh->digest[0], oh->digest[1], oh->digest[2],
oh->hash); oh->hash);
...@@ -317,14 +320,51 @@ dump(const struct hcb_root *root, FILE *fd) ...@@ -317,14 +320,51 @@ dump(const struct hcb_root *root, FILE *fd)
} }
/**********************************************************************/
#define COOL_DURATION 15 /* seconds */
static void *
hcb_cleaner(void *priv)
{
struct objhead *oh, *oh2;
struct hcb_y *y;
THR_SetName("hcb_cleaner");
(void)priv;
while (1) {
sleep(1);
Lck_Lock(&hcb_mtx);
VTAILQ_FOREACH_SAFE(oh, &laylow, coollist, oh2) {
if (oh->hash != NULL) {
free(oh->hash);
oh->hash = NULL;
}
y = (void *)&oh->u;
if (y->leaf[0] || y->leaf[1])
continue;
if (++oh->refcnt > COOL_DURATION) {
VTAILQ_REMOVE(&laylow, oh, coollist);
if (PHK)
fprintf(stderr, "OH %p is cold enough\n", oh);
free(oh);
VSL_stats->n_objecthead--;
}
}
Lck_Unlock(&hcb_mtx);
}
}
/**********************************************************************/ /**********************************************************************/
static void static void
hcb_start(void) hcb_start(void)
{ {
struct objhead *oh = NULL; struct objhead *oh = NULL;
pthread_t tp;
(void)oh; (void)oh;
AZ(pthread_create(&tp, NULL, hcb_cleaner, NULL));
assert(params->hash_sha256); assert(params->hash_sha256);
assert(sizeof(struct hcb_y) <= sizeof(oh->u)); assert(sizeof(struct hcb_y) <= sizeof(oh->u));
memset(&hcb_root, 0, sizeof hcb_root); memset(&hcb_root, 0, sizeof hcb_root);
...@@ -336,7 +376,6 @@ static int ...@@ -336,7 +376,6 @@ static int
hcb_deref(struct objhead *oh) hcb_deref(struct objhead *oh)
{ {
int r; int r;
struct hcb_y *y;
r = 1; r = 1;
CHECK_OBJ_NOTNULL(oh, OBJHEAD_MAGIC); CHECK_OBJ_NOTNULL(oh, OBJHEAD_MAGIC);
...@@ -344,16 +383,11 @@ hcb_deref(struct objhead *oh) ...@@ -344,16 +383,11 @@ hcb_deref(struct objhead *oh)
if (--oh->refcnt == 0) { if (--oh->refcnt == 0) {
Lck_Lock(&hcb_mtx); Lck_Lock(&hcb_mtx);
hcb_delete(&hcb_root, oh); hcb_delete(&hcb_root, oh);
y = (void*)&oh->u; VTAILQ_INSERT_TAIL(&laylow, oh, coollist);
if (y->leaf[0] == 0 && y->leaf[1] == 0)
r = 0;
else {
/* XXX: on waiting list */
}
Lck_Unlock(&hcb_mtx); Lck_Unlock(&hcb_mtx);
} }
Lck_Unlock(&oh->mtx); Lck_Unlock(&oh->mtx);
if (0) { if (PHK) {
fprintf(stderr, "%s %d %d <%s>\n", __func__, __LINE__, r, oh->hash); fprintf(stderr, "%s %d %d <%s>\n", __func__, __LINE__, r, oh->hash);
dump(&hcb_root, stderr); dump(&hcb_root, stderr);
} }
...@@ -391,7 +425,7 @@ hcb_lookup(const struct sess *sp, struct objhead *noh) ...@@ -391,7 +425,7 @@ hcb_lookup(const struct sess *sp, struct objhead *noh)
oh = hcb_insert(&hcb_root, noh, 1); oh = hcb_insert(&hcb_root, noh, 1);
if (oh == noh) { if (oh == noh) {
VSL_stats->hcb_insert++; VSL_stats->hcb_insert++;
if (0) { if (PHK) {
fprintf(stderr, "%s %d\n", __func__, __LINE__); fprintf(stderr, "%s %d\n", __func__, __LINE__);
dump(&hcb_root, stderr); dump(&hcb_root, stderr);
} }
...@@ -400,7 +434,7 @@ hcb_lookup(const struct sess *sp, struct objhead *noh) ...@@ -400,7 +434,7 @@ hcb_lookup(const struct sess *sp, struct objhead *noh)
noh->hash = NULL; noh->hash = NULL;
noh->hashlen = 0; noh->hashlen = 0;
VSL_stats->hcb_lock++; VSL_stats->hcb_lock++;
if (0) { if (PHK) {
fprintf(stderr, "%s %d\n", __func__, __LINE__); fprintf(stderr, "%s %d\n", __func__, __LINE__);
dump(&hcb_root, stderr); dump(&hcb_root, stderr);
} }
......
...@@ -64,6 +64,9 @@ void HSH_Prepare(struct sess *sp, unsigned hashcount); ...@@ -64,6 +64,9 @@ void HSH_Prepare(struct sess *sp, unsigned hashcount);
#ifdef VARNISH_CACHE_CHILD #ifdef VARNISH_CACHE_CHILD
#define DIGEST_LEN 32
struct objhead { struct objhead {
unsigned magic; unsigned magic;
#define OBJHEAD_MAGIC 0x1b96615d #define OBJHEAD_MAGIC 0x1b96615d
...@@ -73,9 +76,13 @@ struct objhead { ...@@ -73,9 +76,13 @@ struct objhead {
VTAILQ_HEAD(,object) objects; VTAILQ_HEAD(,object) objects;
char *hash; char *hash;
unsigned hashlen; unsigned hashlen;
unsigned char digest[32]; unsigned char digest[DIGEST_LEN];
unsigned char digest_len; union {
VTAILQ_HEAD(, sess) waitinglist; VTAILQ_HEAD(, sess) __u_waitinglist;
VTAILQ_ENTRY(objhead) __u_coollist;
} __u;
#define waitinglist __u.__u_waitinglist
#define coollist __u.__u_coollist
/*---------------------------------------------------- /*----------------------------------------------------
* The fields below are for the sole private use of * The fields below are for the sole private use of
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment