#endif
/* cache_response.c */
+void RES_BuildHttp(struct sess *sp);
void RES_Error(struct sess *sp, int code, const char *reason);
void RES_WriteObj(struct sess *sp);
DOT ]
DOT vcl_deliver [
DOT shape=record
-DOT label="vcl_deliver()|req.\nresp."
+DOT label="vcl_deliver()|resp."
DOT ]
DOT deliver2 [
DOT shape=ellipse
DOT errdeliver [label="ERROR",shape=plaintext]
DOT }
DOT deliver2 -> DONE [style=bold,color=green,weight=4]
+ *
+ * XXX: Ideally we should make the req. available in vcl_deliver() but for
+ * XXX: reasons of economy we don't, since that allows us to reuse the space
+ * XXX: in sp->req for the response.
+ *
+ * XXX: Rather than allocate two http's and workspaces for all sessions to
+ * XXX: address this deficiency, we could make the VCL compiler set a flag
+ * XXX: if req. is used in vcl_deliver(). When the flag is set we would
+ * XXX: take the memory overhead, for instance by borrowing a struct bereq
+ * XXX: or similar.
+ *
+ * XXX: For now, wait until somebody asks for it.
*/
static int
cnt_deliver(struct sess *sp)
{
+ RES_BuildHttp(sp);
+ VCL_deliver_method(sp);
+ if (sp->handling != VCL_RET_DELIVER)
+ INCOMPL();
+
RES_WriteObj(sp);
HSH_Deref(sp->obj);
sp->obj = NULL;
double dh, dp, da;
AZ(sp->obj);
+ AZ(sp->bereq);
sp->backend = NULL;
if (sp->vcl != NULL) {
if (sp->wrk->vcl != NULL)
/*--------------------------------------------------------------------*/
void
-RES_WriteObj(struct sess *sp)
+RES_BuildHttp(struct sess *sp)
{
- struct storage *st;
- unsigned u = 0;
-
CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
- clock_gettime(CLOCK_REALTIME, &sp->t_resp);
if (sp->obj->response == 200 && sp->http->conds && res_do_conds(sp))
return;
http_PrintfHeader(sp->wrk, sp->fd, sp->http,
"X-Varnish: %u %u", sp->xid, sp->obj->xid);
else
- http_PrintfHeader(sp->wrk, sp->fd, sp->http, "X-Varnish: %u", sp->xid);
+ http_PrintfHeader(sp->wrk, sp->fd, sp->http,
+ "X-Varnish: %u", sp->xid);
http_PrintfHeader(sp->wrk, sp->fd, sp->http, "Age: %u",
sp->obj->age + sp->t_resp.tv_sec - sp->obj->entered);
http_SetHeader(sp->wrk, sp->fd, sp->http, "Via: 1.1 varnish");
if (sp->doclose != NULL)
http_SetHeader(sp->wrk, sp->fd, sp->http, "Connection: close");
+}
+
+/*--------------------------------------------------------------------*/
+
+void
+RES_WriteObj(struct sess *sp)
+{
+ struct storage *st;
+ unsigned u = 0;
+
+ CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
+
+ clock_gettime(CLOCK_REALTIME, &sp->t_resp);
WRK_Reset(sp->wrk, &sp->fd);
sp->wrk->acct.hdrbytes += http_Write(sp->wrk, sp->http, 1);
CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
vsb_cat(sb, "void VRT_l_obj_cacheable(struct sess *, unsigned);\n");
vsb_cat(sb, "double VRT_r_obj_ttl(struct sess *);\n");
vsb_cat(sb, "void VRT_l_obj_ttl(struct sess *, double);\n");
+ vsb_cat(sb, "double VRT_r_obj_lastuse(struct sess *);\n");
vsb_cat(sb, "const char * VRT_r_resp_proto(struct sess *);\n");
vsb_cat(sb, "void VRT_l_resp_proto(struct sess *, const char *);\n");
vsb_cat(sb, "int VRT_r_resp_status(struct sess *);\n");
vsb_cat(sb, "void VRT_l_resp_status(struct sess *, int);\n");
vsb_cat(sb, "const char * VRT_r_resp_response(struct sess *);\n");
vsb_cat(sb, "void VRT_l_resp_response(struct sess *, const char *);\n");
+ vsb_cat(sb, "double VRT_r_now(struct sess *);\n");
}
# Connection related parameters
{ client.ip
RO IP
- {recv pipe pass hash miss hit fetch }
+ {recv pipe pass hash miss hit fetch deliver }
}
{ client.bandwidth # Not implemented yet
NO
}
{ server.ip
RO IP
- {recv pipe pass hash miss hit fetch }
+ {recv pipe pass hash miss hit fetch deliver }
}
# Request paramters
# The (possibly) cached object
{ obj.proto
RW STRING
- { hit fetch deliver }
+ { hit fetch }
}
{ obj.status
RW INT
}
{ obj.http.
RW HEADER
- { hit fetch deliver }
+ { hit fetch }
}
{ obj.valid
# The response we send back
{ resp.proto
RW STRING
- { fetch }
+ { deliver }
}
{ resp.status
RW INT
- { fetch }
+ { deliver }
}
{ resp.response
RW STRING
- { fetch }
+ { deliver }
}
{ resp.http.
RW HEADER
- { fetch }
+ { deliver }
}
# Miscellaneous
+ # XXX: I'm not happy about this one. All times should be relative
+ # XXX: or delta times in VCL programs, so this shouldn't be needed /phk
{ now
RO TIME
{recv pipe pass hash miss hit fetch deliver discard timeout}
"VRT_r_client_ip(sp)",
NULL,
V_RO,
- VCL_MET_RECV | VCL_MET_PIPE | VCL_MET_PASS | VCL_MET_HASH | VCL_MET_MISS | VCL_MET_HIT | VCL_MET_FETCH
+ VCL_MET_RECV | VCL_MET_PIPE | VCL_MET_PASS | VCL_MET_HASH | VCL_MET_MISS | VCL_MET_HIT | VCL_MET_FETCH | VCL_MET_DELIVER
},
{ "server.ip", IP, 9,
"VRT_r_server_ip(sp)",
NULL,
V_RO,
- VCL_MET_RECV | VCL_MET_PIPE | VCL_MET_PASS | VCL_MET_HASH | VCL_MET_MISS | VCL_MET_HIT | VCL_MET_FETCH
+ VCL_MET_RECV | VCL_MET_PIPE | VCL_MET_PASS | VCL_MET_HASH | VCL_MET_MISS | VCL_MET_HIT | VCL_MET_FETCH | VCL_MET_DELIVER
},
{ "req.request", STRING, 11,
"VRT_r_req_request(sp)",
"VRT_r_obj_proto(sp)",
"VRT_l_obj_proto(sp, ",
V_RW,
- VCL_MET_HIT | VCL_MET_FETCH | VCL_MET_DELIVER
+ VCL_MET_HIT | VCL_MET_FETCH
},
{ "obj.status", INT, 10,
"VRT_r_obj_status(sp)",
"VRT_r_obj_http_(sp)",
"VRT_l_obj_http_(sp, ",
V_RW,
- VCL_MET_HIT | VCL_MET_FETCH | VCL_MET_DELIVER
+ VCL_MET_HIT | VCL_MET_FETCH
},
{ "obj.valid", BOOL, 9,
"VRT_r_obj_valid(sp)",
"VRT_r_resp_proto(sp)",
"VRT_l_resp_proto(sp, ",
V_RW,
- VCL_MET_FETCH
+ VCL_MET_DELIVER
},
{ "resp.status", INT, 11,
"VRT_r_resp_status(sp)",
"VRT_l_resp_status(sp, ",
V_RW,
- VCL_MET_FETCH
+ VCL_MET_DELIVER
},
{ "resp.response", STRING, 13,
"VRT_r_resp_response(sp)",
"VRT_l_resp_response(sp, ",
V_RW,
- VCL_MET_FETCH
+ VCL_MET_DELIVER
},
{ "resp.http.", HEADER, 10,
"VRT_r_resp_http_(sp)",
"VRT_l_resp_http_(sp, ",
V_RW,
- VCL_MET_FETCH
+ VCL_MET_DELIVER
},
{ "now", TIME, 3,
"VRT_r_now(sp)",