[Varnish] #268: Make 304 and Last-Modified work with ESI
Varnish
varnish-bugs at projects.linpro.no
Thu Jul 3 01:39:51 CEST 2008
#268: Make 304 and Last-Modified work with ESI
-------------------------+--------------------------------------------------
Reporter: sky | Owner: phk
Type: enhancement | Status: new
Priority: normal | Milestone:
Component: varnishd | Version: trunk
Severity: normal | Keywords:
-------------------------+--------------------------------------------------
This keeps track of a last_modified for a objheader which is set to the
most recent last_modified, if that is set then we use that instead of our
top-level.
If we get an IMS and we don't have the cached value we return 200,
otherwise we return according to normal rules. There is a race here if a
fragment gets updated then IMS won't pick it up. However a normal GET will
pick it up, update the cached value and any future IMS will be correct. It
is assumed based on my requests that this is a sufficiently small window
it is fine. Longer term solutions should be looked at.
{{{
===================================================================
--- bin/varnishd/cache.h (revision 2877)
+++ bin/varnishd/cache.h (working copy)
@@ -296,6 +296,9 @@
char *hash;
unsigned hashlen;
VTAILQ_HEAD(, sess) waitinglist;
+
+ /* cached value for ESI */
+ double last_modified_cached;
};
/* -------------------------------------------------------------------*/
@@ -371,6 +374,10 @@
unsigned ihashptr;
unsigned lhashptr;
const char **hashptr;
+
+ /* used during ESI processing to figure out the real LM */
+ double last_modified_cached;
+
};
/* -------------------------------------------------------------------
Index: bin/varnishd/cache_response.c
===================================================================
--- bin/varnishd/cache_response.c (revision 2877)
+++ bin/varnishd/cache_response.c (working copy)
@@ -56,8 +56,17 @@
http_PrintfHeader(sp->wrk, sp->fd, sp->http, "Date: %s", lm);
http_SetHeader(sp->wrk, sp->fd, sp->http, "Via: 1.1 varnish");
http_PrintfHeader(sp->wrk, sp->fd, sp->http, "X-Varnish: %u",
sp->xid);
- TIM_format(sp->obj->last_modified, lm);
+
+ /* Check to do the right thing with regards to ESI */
+ if(!VTAILQ_EMPTY(&sp->obj->esibits)) {
+ TIM_format(sp->obj->objhead->last_modified_cached, lm);
+ } else {
+ TIM_format(sp->obj->last_modified, lm);
+ }
+
http_PrintfHeader(sp->wrk, sp->fd, sp->http, "Last-Modified: %s",
lm);
+
+
http_PrintfHeader(sp->wrk, sp->fd, sp->http, "Connection: %s",
sp->doclose ? "close" : "keep-alive");
sp->wantbody = 0;
@@ -70,13 +79,24 @@
{
char *p;
double ims;
+ double last_modified = 0;
- if (sp->obj->last_modified > 0 &&
+ /* Check to do the right thing with regards to ESI */
+ if(!VTAILQ_EMPTY(&sp->obj->esibits)) {
+ last_modified = sp->obj->objhead->last_modified_cached;
+ } else {
+ last_modified = sp->obj->last_modified;
+ }
+
+
+ if (last_modified > 0 &&
http_GetHdr(sp->http, H_If_Modified_Since, &p)) {
+
+
ims = TIM_parse(p);
if (ims > sp->t_req) /* [RFC2616 14.25] */
return (0);
- if (sp->obj->last_modified > ims) {
+ if (last_modified > ims) {
return (0);
}
res_do_304(sp);
@@ -134,16 +154,54 @@
CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
WRK_Reset(sp->wrk, &sp->fd);
- if (sp->esis == 0)
- sp->wrk->acct.hdrbytes += http_Write(sp->wrk, sp->http,
1);
if (sp->wantbody && !VTAILQ_EMPTY(&sp->obj->esibits)) {
+
+ /* slight duplicate code path to below
+ but we need to mangle headers a bit */
+
+
+ if(sp->obj->last_modified <
sp->obj->objhead->last_modified_cached) {
+ char lm[64];
+ http_Unset(sp->http, H_Last_Modified);
+ TIM_format(sp->obj->objhead->last_modified_cached,
lm);
+ http_PrintfHeader(sp->wrk, sp->fd, sp->http,
"Last-Modified: %s", lm);
+
+ }
+
+ if (sp->esis == 0)
+ sp->wrk->acct.hdrbytes += http_Write(sp->wrk,
sp->http, 1);
+
ESI_Deliver(sp);
+
+
+
+
+ /* do i really need this mutex?
+ we have a ref to the object
+ */
+ if (sp->esis == 0) {
+ if (sp->obj->last_modified >
sp->last_modified_cached)
+ sp->last_modified_cached =
sp->obj->last_modified;
+ LOCK(&sp->obj->objhead->mtx);
+ if (sp->last_modified_cached >
sp->obj->objhead->last_modified_cached)
+ sp->obj->objhead->last_modified_cached =
sp->last_modified_cached;
+ UNLOCK(&sp->obj->objhead->mtx);
+ }
} else if (sp->wantbody) {
+
+ if (sp->esis == 0)
+ sp->wrk->acct.hdrbytes += http_Write(sp->wrk,
sp->http, 1);
+
if (sp->esis > 0) {
sprintf(lenbuf, "%x\r\n", sp->obj->len);
sp->wrk->acct.hdrbytes +=
WRK_Write(sp->wrk, lenbuf, -1);
+
+ /* Try and find the latest last-modified */
+ if(sp->obj && sp->obj->last_modified >
sp->last_modified_cached)
+ sp->last_modified_cached =
sp->obj->last_modified;
+
}
VTAILQ_FOREACH(st, &sp->obj->store, list) {
@@ -172,7 +230,11 @@
spassert(u == sp->obj->len);
if (sp->esis > 0)
WRK_Write(sp->wrk, "\r\n", -1);
+ } else {
+ if (sp->esis == 0)
+ sp->wrk->acct.hdrbytes += http_Write(sp->wrk,
sp->http, 1);
}
+
if (WRK_Flush(sp->wrk))
vca_close_session(sp, "remote closed");
}
}}}
--
Ticket URL: <http://varnish.projects.linpro.no/ticket/268>
Varnish <http://varnish.projects.linpro.no/>
The Varnish HTTP Accelerator
More information about the varnish-bugs
mailing list