cache_backend.c \
cache_expire.c \
cache_fetch.c \
+ cache_hash.c \
cache_http.c \
cache_main.c \
cache_pool.c \
#include <sys/queue.h>
+#include "vcl_returns.h"
+
+#define VCA_ADDRBUFSIZE 32 /* Sizeof ascii network address */
+
struct event_base;
struct sbuf;
+struct sess;
+struct object;
+struct objhead;
#ifdef EV_TIMEOUT
struct worker {
struct event_base *eb;
struct event e1, e2;
struct sbuf *sb;
+ struct objhead *nobjhead;
struct object *nobj;
};
#else
/* Hashing -----------------------------------------------------------*/
typedef void hash_init_f(void);
-typedef struct object *hash_lookup_f(unsigned char *key, struct object *nobj);
-typedef void hash_deref_f(struct object *obj);
-typedef void hash_purge_f(struct object *obj);
+typedef struct objhead *hash_lookup_f(unsigned char *key, struct objhead *nobj);
+typedef void hash_deref_f(struct objhead *obj);
+typedef void hash_purge_f(struct objhead *obj);
struct hash_slinger {
const char *name;
extern struct hash_slinger hsl_slinger;
-extern struct hash_slinger *hash;
-
/* Storage -----------------------------------------------------------*/
struct storage {
*/
extern struct stevedore *stevedore;
-/* Storage -----------------------------------------------------------*/
-
-struct sess;
-
-#define VCA_ADDRBUFSIZE 32
+/* -------------------------------------------------------------------*/
struct object {
unsigned char hash[16];
unsigned valid;
unsigned cacheable;
+ struct objhead *objhead;
+ pthread_cond_t cv;
+
unsigned busy;
unsigned len;
time_t ttl;
char *header;
+ TAILQ_ENTRY(object) list;
TAILQ_HEAD(, storage) store;
};
-#include "vcl_returns.h"
+struct objhead {
+ unsigned char hash[16];
+ unsigned refcnt;
+
+ pthread_mutex_t mtx;
+ TAILQ_HEAD(,object) objects;
+};
struct sess {
int fd;
/* cache_fetch.c */
int FetchSession(struct worker *w, struct sess *sp);
+/* cache_hash.c */
+struct object *HSH_Lookup(struct worker *w, struct http *h);
+void HSH_Unbusy(struct object *o);
+void HSH_Unref(struct object *o);
+void HSH_Init(void);
+
/* cache_http.c */
typedef void http_callback_f(void *, int good);
struct http;
vca_write_obj(sp, w->sb);
+#if 0
hash->deref(sp->obj);
+#endif
return (0);
}
vca_write_obj(sp, w->sb);
+#if 0
hash->deref(sp->obj);
+#endif
return (0);
}
--- /dev/null
+/*
+ * $Id$
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <md5.h>
+#include <event.h>
+#include <pthread.h>
+
+#include "libvarnish.h"
+#include "cache.h"
+
+static struct hash_slinger *hash;
+
+
+struct object *
+HSH_Lookup(struct worker *w, struct http *h)
+{
+ struct objhead *oh;
+ struct object *o;
+ unsigned char key[16];
+ MD5_CTX ctx;
+ char *b;
+
+ assert(hash != NULL);
+ /* Make sure we have both a new objhead and object if we need them */
+ if (w->nobjhead == NULL) {
+ w->nobjhead = calloc(sizeof *w->nobjhead, 1);
+ assert(w->nobjhead != NULL);
+ TAILQ_INIT(&w->nobjhead->objects);
+ }
+ if (w->nobj == NULL) {
+ w->nobj = calloc(sizeof *w->nobj, 1);
+ assert(w->nobj != NULL);
+ w->nobj->busy = 1;
+ TAILQ_INIT(&w->nobj->store);
+ pthread_cond_init(&w->nobj->cv, NULL);
+ }
+
+ assert(http_GetURL(h, &b));
+ MD5Init(&ctx);
+ MD5Update(&ctx, b, strlen(b));
+ MD5Final(key, &ctx);
+ oh = hash->lookup(key, w->nobjhead);
+ if (oh == w->nobjhead)
+ w->nobjhead = NULL;
+ AZ(pthread_mutex_lock(&oh->mtx));
+ TAILQ_FOREACH(o, &oh->objects, list) {
+ o->refcnt++;
+ if (o->busy)
+ AZ(pthread_cond_wait(&o->cv, &oh->mtx));
+ /* XXX: do Vary: comparison */
+ if (1)
+ break;
+ o->refcnt--;
+ }
+ if (o == NULL) {
+ o = w->nobj;
+ w->nobj = NULL;
+ TAILQ_INSERT_TAIL(&oh->objects, o, list);
+ }
+ AZ(pthread_mutex_unlock(&oh->mtx));
+ return (o);
+}
+
+void
+HSH_Unbusy(struct object *o)
+{
+
+ AZ(pthread_mutex_lock(&o->objhead->mtx));
+ o->busy = 0;
+ AZ(pthread_mutex_unlock(&o->objhead->mtx));
+ AZ(pthread_cond_broadcast(&o->cv));
+}
+
+void
+HSH_Unref(struct object *o)
+{
+
+ AZ(pthread_mutex_lock(&o->objhead->mtx));
+ o->refcnt--;
+ AZ(pthread_mutex_unlock(&o->objhead->mtx));
+}
+
+void
+HSH_Init(void)
+{
+
+ hash = &hsl_slinger;
+ if (hash->init != NULL)
+ hash->init();
+}
static struct event ev_keepalive;
-struct hash_slinger *hash;
struct stevedore *stevedore;
pthread_mutex_t sessmtx;
VCA_Init();
EXP_Init();
+ HSH_Init();
eb = event_init();
assert(eb != NULL);
- hash = &hsl_slinger;
- if (hash->init != NULL)
- hash->init();
-
stevedore = heritage.stevedore;
if (stevedore->open != NULL)
stevedore->open(stevedore);
#include <sys/time.h>
#include <sbuf.h>
#include <event.h>
-#include <md5.h>
#include "libvarnish.h"
#include "shmlog.h"
LookupSession(struct worker *w, struct sess *sp)
{
struct object *o;
- unsigned char key[16];
- MD5_CTX ctx;
- char *b;
-
- /* Make sure worker thread has a fresh object at hand */
- if (w->nobj == NULL) {
- w->nobj = calloc(sizeof *w->nobj, 1);
- assert(w->nobj != NULL);
- w->nobj->busy = 1;
- TAILQ_INIT(&w->nobj->store);
- }
- assert(http_GetURL(sp->http, &b));
- MD5Init(&ctx);
- MD5Update(&ctx, b, strlen(b));
- MD5Final(key, &ctx);
- o = hash->lookup(key, w->nobj);
+ o = HSH_Lookup(w, sp->http);
sp->obj = o;
- if (o != w->nobj && o->ttl > sp->t0) {
- /* XXX: wait while obj->busy */
- VSL(SLT_Debug, 0, "Lookup found %p %s", o, b);
+ if (o->busy)
+ VCL_miss_method(sp);
+ else
VCL_hit_method(sp);
- return (0);
- }
- VSL(SLT_Debug, 0, "Lookup new %p %s", o, b);
- w->nobj = NULL;
- VCL_miss_method(sp);
return (0);
}
struct hsl_entry {
TAILQ_ENTRY(hsl_entry) list;
- struct object *obj;
+ struct objhead *obj;
};
static TAILQ_HEAD(, hsl_entry) hsl_head = TAILQ_HEAD_INITIALIZER(hsl_head);
AZ(pthread_mutex_init(&hsl_mutex, NULL));
}
-static struct object *
-hsl_lookup(unsigned char *key, struct object *nobj)
+static struct objhead *
+hsl_lookup(unsigned char *key, struct objhead *nobj)
{
struct hsl_entry *he, *he2;
int i;
}
static void
-hsl_deref(struct object *obj)
+hsl_deref(struct objhead *obj)
{
AZ(pthread_mutex_lock(&hsl_mutex));
}
static void
-hsl_purge(struct object *obj)
+hsl_purge(struct objhead *obj)
{
struct hsl_entry *he;