struct workreq workreq;
struct acct acct;
- char *hash_b; /* Start of hash string */
- char *hash_e; /* End of hash string */
+ /* pointers to hash string components */
+ unsigned nhashptr;
+ unsigned ihashptr;
+ unsigned lhashptr;
+ const char **hashptr;
};
struct backend {
/* cache_hash.c */
void HSH_Prealloc(struct sess *sp);
+int HSH_Compare(struct sess *sp, const char *b, const char *e);
+void HSH_Copy(struct sess *sp, char *b, const char *e);
struct object *HSH_Lookup(struct sess *sp);
void HSH_Unbusy(struct object *o);
void HSH_Ref(struct object *o);
cnt_lookup(struct sess *sp)
{
struct object *o;
+ char *p;
+ uintptr_t u;
CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
if (sp->obj == NULL) {
- WS_Reserve(sp->http->ws, 0);
- sp->hash_b = sp->http->ws->f;
- sp->hash_e = sp->hash_b;
+
+ /* Allocate the pointers we need, align properly. */
+ sp->lhashptr = 1; /* space for NUL */
+ sp->ihashptr = 0;
+ sp->nhashptr = sp->vcl->nhashcount * 2;
+ p = WS_Alloc(sp->http->ws,
+ sizeof(const char *) * (sp->nhashptr + 1));
+ u = (uintptr_t)p;
+ u &= sizeof(const char *) - 1;
+ if (u)
+ p += sizeof(const char *) - u;
+ sp->hashptr = (void*)p;
+
VCL_hash_method(sp); /* XXX: no-op for now */
- WS_ReleaseP(sp->http->ws, sp->hash_e);
/* XXX check error */
}
return (1);
}
- WS_Return(sp->http->ws, sp->hash_b, sp->hash_e);
- sp->hash_b = sp->hash_e = NULL;
-
sp->obj = o;
/* If we inserted a new object it's a miss */
}
}
+int
+HSH_Compare(struct sess *sp, const char *b, const char *e)
+{
+ int i;
+ unsigned u, v;
+
+ i = sp->lhashptr - (e - b);
+ if (i)
+ return (i);
+ for (u = 0; u < sp->ihashptr; u += 2) {
+ v = sp->hashptr[u + 1] - sp->hashptr[u];
+ i = memcmp(sp->hashptr[u], b, v);
+ if (i)
+ return (i);
+ b += v;
+ i = '#' - *b++;
+ if (i)
+ return (i);
+ }
+ assert(*b == '\0');
+ b++;
+ assert(b == e);
+ return (0);
+}
+
+void
+HSH_Copy(struct sess *sp, char *b, const char *e)
+{
+ unsigned u, v;
+
+ assert((e - b) >= sp->lhashptr);
+ for (u = 0; u < sp->ihashptr; u += 2) {
+ v = sp->hashptr[u + 1] - sp->hashptr[u];
+ memcpy(b, sp->hashptr[u], v);
+ b += v;
+ *b++ = '#';
+ }
+ *b++ = '\0';
+ assert(b <= e);
+}
+
struct object *
HSH_Lookup(struct sess *sp)
{
LOCK(&oh->mtx);
goto were_back;
}
-VSLR(SLT_Debug, sp->fd, sp->hash_b, sp->hash_e);
- oh = hash->lookup(sp->hash_b, sp->hash_e, w->nobjhead);
+ oh = hash->lookup(sp, w->nobjhead);
CHECK_OBJ_NOTNULL(oh, OBJHEAD_MAGIC);
if (oh == w->nobjhead)
w->nobjhead = NULL;
return (sp->mysockaddr);
}
-/*--------------------------------------------------------------------*/
+/*--------------------------------------------------------------------
+ * Add an element to the array/list of hash bits.
+ */
void
VRT_l_req_hash(struct sess *sp, const char *str)
if (str == NULL)
str = "";
l = strlen(str);
- xxxassert (sp->hash_e + l + 1 <= sp->http->ws->e);
- memcpy(sp->hash_e, str, l);
- sp->hash_e[l] = '#';
- sp->hash_e += l + 1;
+
+ /*
+ * XXX: handle this by bouncing sp->vcl->nhashcount when it fails
+ * XXX: and dispose of this request either by reallocating the
+ * XXX: hashptr (if possible) or restarting/error the request
+ */
+ xxxassert(sp->ihashptr < sp->nhashptr);
+
+ sp->hashptr[sp->ihashptr] = str;
+ sp->hashptr[sp->ihashptr + 1] = str + l;
+ sp->ihashptr += 2;
+ sp->lhashptr += l + 1;
}
/*--------------------------------------------------------------------*/
*/
static struct objhead *
-hcl_lookup(const char *b, const char *e, struct objhead *noh)
+hcl_lookup(struct sess *sp, struct objhead *noh)
{
struct hcl_entry *he, *he2;
struct hcl_hd *hp;
- unsigned u1, digest, kl, r;
+ unsigned u1, digest, r;
+ unsigned u, v;
int i;
CHECK_OBJ_NOTNULL(noh, OBJHEAD_MAGIC);
- digest = crc32_l(b, e - b);
+ digest = ~0U;
+ for (u = 0; u < sp->ihashptr; u += 2) {
+ v = sp->hashptr[u + 1] - sp->hashptr[u];
+ digest = crc32(digest, sp->hashptr[u], v);
+ }
+ digest ^= ~0U;
u1 = digest % hcl_nhash;
hp = &hcl_head[u1];
- kl = e - b;
he2 = NULL;
for (r = 0; r < 2; r++ ) {
LOCK(&hp->mtx);
TAILQ_FOREACH(he, &hp->head, list) {
CHECK_OBJ_NOTNULL(he, HCL_ENTRY_MAGIC);
- if (kl < he->klen)
+ if (sp->lhashptr < he->klen)
continue;
- if (kl > he->klen)
+ if (sp->lhashptr > he->klen)
break;
if (he->digest < digest)
continue;
if (he->digest > digest)
break;
- if (memcmp(he->key, b, kl))
+ i = HSH_Compare(sp, he->key, he->key + he->klen);
+ if (i < 0)
continue;
+ if (i > 0)
+ break;
he->refcnt++;
noh = he->oh;
UNLOCK(&hp->mtx);
}
UNLOCK(&hp->mtx);
- i = sizeof *he2 + kl;
+ i = sizeof *he2 + sp->lhashptr;
he2 = calloc(i, 1);
XXXAN(he2);
he2->magic = HCL_ENTRY_MAGIC;
he2->digest = digest;
he2->hash = u1;
he2->head = hp;
- he2->klen = kl;
+ he2->klen = sp->lhashptr;
noh->hashpriv = he2;
he2->key = (void*)(he2 + 1);
- memcpy(he2->key, b, kl);
+ HSH_Copy(sp, he2->key, he2->key + sp->lhashptr);
}
assert(he2 == NULL); /* FlexeLint */
INCOMPL();
*/
static struct objhead *
-hsl_lookup(const char *b, const char *e, struct objhead *nobj)
+hsl_lookup(struct sess *sp, struct objhead *nobj)
{
struct hsl_entry *he, *he2;
- int i, l;
+ int i;
- l = e - b;
LOCK(&hsl_mutex);
TAILQ_FOREACH(he, &hsl_head, list) {
- if (l > he->keylen)
- continue;
- if (l < he->keylen)
- break;;
- i = memcmp(b, he->key, l);
+ i = HSH_Compare(sp, he->key, he->key + he->keylen);
if (i < 0)
continue;
if (i > 0)
break;
he->refcnt++;
nobj = he->obj;
- nobj->hashpriv = he;
UNLOCK(&hsl_mutex);
return (nobj);
}
UNLOCK(&hsl_mutex);
return (NULL);
}
- he2 = calloc(sizeof *he2 + l, 1);
+ he2 = calloc(sizeof *he2 + sp->lhashptr, 1);
XXXAN(he2);
he2->obj = nobj;
he2->refcnt = 1;
he2->key = (void*)(he2 + 1);
- he2->keylen = l;
- memcpy(he2->key, b, l);
+ he2->keylen = sp->lhashptr;
+ HSH_Copy(sp, he2->key, he2->key + he2->keylen);
nobj->hashpriv = he2;
if (he != NULL)
TAILQ_INSERT_BEFORE(he, he2, list);
* $Id$
*/
+struct sess;
+
typedef int hash_init_f(const char *);
typedef void hash_start_f(void);
-typedef struct objhead *hash_lookup_f(const char *key1, const char *key2, struct objhead *nobj);
+typedef struct objhead *hash_lookup_f(struct sess *sp, struct objhead *nobj);
typedef int hash_deref_f(struct objhead *obj);
struct hash_slinger {