unsigned heap_idx;
unsigned ban_seq;
+ unsigned pass;
+
unsigned response;
unsigned valid;
/* cache_pass.c */
void PassSession(struct worker *w, struct sess *sp);
+void PassBody(struct worker *w, struct sess *sp);
/* cache_pipe.c */
void PipeSession(struct worker *w, struct sess *sp);
{
char *b;
+ (void)w;
if (http_GetHdr(sp->http, "Connection", &b) &&
!strcmp(b, "close")) {
vca_close_session(sp, "Connection header");
if (sp->handling == VCL_RET_LOOKUP)
INCOMPL();
- if (sp->handling == VCL_RET_PASS)
- INCOMPL();
- if (sp->handling == VCL_RET_INSERT_PASS)
- INCOMPL();
+ if (sp->handling == VCL_RET_PASS) {
+ sp->obj->cacheable = 0;
+ HSH_Unbusy(sp->obj);
+ HSH_Deref(sp->obj);
+ sp->obj = NULL;
+ sp->step = STP_PASSBODY;
+ return;
+ }
+ if (sp->handling == VCL_RET_INSERT_PASS) {
+ sp->obj->pass = 1;
+ sp->obj->cacheable = 1;
+ HSH_Unbusy(sp->obj);
+ sp->obj = NULL;
+ sp->step = STP_PASSBODY;
+ return;
+ }
if (sp->handling == VCL_RET_INSERT) {
+ sp->obj->cacheable = 1;
FetchBody(w, sp);
sp->step = STP_DELIVER;
return;
{
VCL_hit_method(sp);
- if (sp->handling == VCL_RET_LOOKUP)
- INCOMPL();
- if (sp->handling == VCL_RET_PASS) {
- PassSession(w, sp);
- sp->step = STP_DONE;
- return;
- }
- if (sp->handling == VCL_RET_ERROR)
- INCOMPL();
+
+ if (sp->handling == VCL_RET_DELIVER && sp->obj->pass)
+ sp->handling = VCL_RET_PASS;
+
if (sp->handling == VCL_RET_DELIVER) {
vca_write_obj(w, sp);
HSH_Deref(sp->obj);
sp->step = STP_DONE;
return;
}
+ if (sp->handling == VCL_RET_PASS) {
+ HSH_Deref(sp->obj);
+ sp->obj = NULL;
+ PassSession(w, sp);
+ sp->step = STP_PASSBODY;
+ return;
+ }
+
+ if (sp->handling == VCL_RET_ERROR)
+ INCOMPL();
+
+ if (sp->handling == VCL_RET_LOOKUP)
+ INCOMPL();
+
INCOMPL();
}
if (sp->obj->busy) {
VSL_stats->cache_miss++;
sp->step = STP_MISS;
- } else {
- VSL_stats->cache_hit++;
- VSL(SLT_Hit, sp->fd, "%u", sp->obj->xid);
- sp->step = STP_HIT;
+ return;
}
+ if (sp->obj->pass) {
+ VSL_stats->cache_hitpass++;
+ VSL(SLT_HitPass, sp->fd, "%u", sp->obj->xid);
+ sp->step = STP_HIT;
+ return;
+ }
+ VSL_stats->cache_hit++;
+ VSL(SLT_Hit, sp->fd, "%u", sp->obj->xid);
+ sp->step = STP_HIT;
}
HSH_Deref(sp->obj);
sp->obj = 0;
PassSession(w, sp);
- sp->step = STP_DONE;
+ sp->step = STP_PASSBODY;
return;
}
if (sp->handling == VCL_RET_LOOKUP)
{
PassSession(w, sp);
- sp->step = STP_DONE; /* XXX */
+ sp->step = STP_PASSBODY;
}
DOT passbody -> DONE
*/
-static void cnt_passbody(struct worker *w, struct sess *sp) { (void)w; (void)sp; INCOMPL(); }
+static void
+cnt_passbody(struct worker *w, struct sess *sp)
+{
+ PassBody(w, sp);
+ sp->step = STP_DONE;
+ return;
+}
/*--------------------------------------------------------------------
for (sp->step = STP_RECV; sp->step != STP_DONE; ) {
switch (sp->step) {
-#define STEP(l,u) case STP_##u: cnt_##l(w, sp); break;
+#define STEP(l,u) \
+ case STP_##u: \
+ VSL(SLT_Debug, sp->fd, "State " #u); \
+ cnt_##l(w, sp); \
+ break;
#include "steps.h"
#undef STEP
default: INCOMPL();
else
VBE_RecycleFd(vc);
- if (sp->obj->cacheable)
- EXP_Insert(sp->obj);
HSH_Unbusy(sp->obj);
+ /* Hold on to the reference count, it's not released until
+ * expiry */
if (!sp->obj->cacheable)
HSH_Deref(sp->obj);
return (0);
HSH_Unbusy(struct object *o)
{
+ if (o->cacheable)
+ EXP_Insert(o);
AZ(pthread_mutex_lock(&o->objhead->mtx));
o->busy = 0;
AZ(pthread_mutex_unlock(&o->objhead->mtx));
/*--------------------------------------------------------------------*/
+
void
-PassSession(struct worker *w, struct sess *sp)
+PassBody(struct worker *w, struct sess *sp)
{
- int i;
struct vbe_conn *vc;
struct http *hp;
char *b;
int cls;
- vc = VBE_GetFd(sp->backend, sp->xid);
+ hp = sp->bkd_http;
+ assert(hp != NULL);
+ vc = sp->vbc;
assert(vc != NULL);
- VSL(SLT_Backend, sp->fd, "%d %s", vc->fd, sp->backend->vcl_name);
-
- http_BuildSbuf(vc->fd, Build_Pass, w->sb, sp->http);
- i = write(vc->fd, sbuf_data(w->sb), sbuf_len(w->sb));
- assert(i == sbuf_len(w->sb));
-
- /* XXX: copy any contents */
-
- /*
- * XXX: It might be cheaper to avoid the event_engine and simply
- * XXX: read(2) the header
- */
- hp = vc->http;
- http_RecvHead(hp, vc->fd, w->eb, NULL, NULL);
- event_base_loop(w->eb, 0);
- http_DissectResponse(hp, vc->fd);
http_BuildSbuf(sp->fd, Build_Reply, w->sb, hp);
vca_write(sp, sbuf_data(w->sb), sbuf_len(w->sb));
else
VBE_RecycleFd(vc);
}
+
+/*--------------------------------------------------------------------*/
+void
+PassSession(struct worker *w, struct sess *sp)
+{
+ int i;
+ struct vbe_conn *vc;
+ struct http *hp;
+
+ vc = VBE_GetFd(sp->backend, sp->xid);
+ assert(vc != NULL);
+ VSL(SLT_Backend, sp->fd, "%d %s", vc->fd, sp->backend->vcl_name);
+
+ http_BuildSbuf(vc->fd, Build_Pass, w->sb, sp->http);
+ i = write(vc->fd, sbuf_data(w->sb), sbuf_len(w->sb));
+ assert(i == sbuf_len(w->sb));
+
+ /* XXX: copy any contents */
+
+ /*
+ * XXX: It might be cheaper to avoid the event_engine and simply
+ * XXX: read(2) the header
+ */
+ hp = vc->http;
+ http_RecvHead(hp, vc->fd, w->eb, NULL, NULL);
+ event_base_loop(w->eb, 0);
+ http_DissectResponse(hp, vc->fd);
+
+ sp->bkd_http = hp;
+ sp->vbc = vc;
+}
SLTM(VCL_return)
SLTM(XID)
SLTM(Hit)
+SLTM(HitPass)
SLTM(ExpBan)
SLTM(ExpPick)
SLTM(ExpKill)
MAC_STAT(client_req, uint64_t, "u", "Client requests received")
MAC_STAT(cache_hit, uint64_t, "u", "Cache hits")
+MAC_STAT(cache_hitpass, uint64_t, "u", "Cache hits for pass")
MAC_STAT(cache_miss, uint64_t, "u", "Cache misses")
MAC_STAT(backend_conn, uint64_t, "u", "Backend connections initiated")