From: phk Date: Wed, 24 Oct 2007 14:32:12 +0000 (+0000) Subject: Gently shuffle closer to being able to restart a esi:include on the next X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c5f15fa50d46727e2719f3e77c03f7bcbbadc238;p=varnish Gently shuffle closer to being able to restart a esi:include on the next element: Add two checkpoints for the sessions workspace. The first checkpoint is after the session fixed data, and move the client address and port to workspace to see that this works. The second checkpoint is after the, as received unadultered by VCL http request. Grab a copy of the http request matching this. Implement rollback as an optional feature of restart in VCL. Move various workspace initialization and resetting operations to more suitable locations in the program flow. I don't know if this is really usable, but now it's possible to do: backend b1 { set backend.host = "backend1"; set backend.port = "80"; } backend b2 { set backend.host = "backend2"; set backend.port = "80"; } sub vcl_recv { set req.backend = b1; remove req.http.cookie; if (req.restarts == 0) { set req.url = "foobar.html"; } else { set req.backend = b2; } } sub vcl_fetch { if (obj.status != 200) { restart rollback; } } And have it first look for "foobar.html" on one backend, and failing that, try to give the user what they asked for from the other backend. git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@2167 d4fa192b-c00b-0410-8231-f00ffab90ce4 --- diff --git a/varnish-cache/bin/varnishd/cache.h b/varnish-cache/bin/varnishd/cache.h index 6707c585..5f936f3e 100644 --- a/varnish-cache/bin/varnishd/cache.h +++ b/varnish-cache/bin/varnishd/cache.h @@ -288,14 +288,18 @@ struct sess { struct sockaddr *mysockaddr; /* formatted ascii client address */ - char addr[TCP_ADDRBUFSIZE]; - char port[TCP_PORTBUFSIZE]; + char *addr; + char *port; struct srcaddr *srcaddr; /* HTTP request */ const char *doclose; struct http *http; + struct http *http0; + struct ws ws[1]; + char *ws_ses; /* WS above session data */ + char *ws_req; /* WS above request data */ struct http_conn htc[1]; @@ -583,9 +587,10 @@ unsigned WS_Reserve(struct ws *ws, unsigned bytes); void WS_Release(struct ws *ws, unsigned bytes); void WS_ReleaseP(struct ws *ws, char *ptr); void WS_Assert(const struct ws *ws); -void WS_Reset(struct ws *ws); +void WS_Reset(struct ws *ws, char *p); char *WS_Alloc(struct ws *ws, unsigned bytes); char *WS_Dup(struct ws *ws, const char *); +char *WS_Snapshot(struct ws *ws); /* rfc2616.c */ int RFC2616_cache_policy(const struct sess *sp, const struct http *hp); diff --git a/varnish-cache/bin/varnishd/cache_acceptor.c b/varnish-cache/bin/varnishd/cache_acceptor.c index 9c40c707..bb0eb879 100644 --- a/varnish-cache/bin/varnishd/cache_acceptor.c +++ b/varnish-cache/bin/varnishd/cache_acceptor.c @@ -107,9 +107,14 @@ sock_test(int fd) void VCA_Prep(struct sess *sp) { + char addr[TCP_ADDRBUFSIZE]; + char port[TCP_PORTBUFSIZE]; + TCP_name(sp->sockaddr, sp->sockaddrlen, - sp->addr, sizeof sp->addr, sp->port, sizeof sp->port); + addr, sizeof addr, port, sizeof port); + sp->addr = WS_Dup(sp->ws, addr); + sp->port = WS_Dup(sp->ws, port); VSL(SLT_SessionOpen, sp->fd, "%s %s", sp->addr, sp->port); sp->acct.first = sp->t_open; if (need_test) @@ -195,7 +200,6 @@ vca_acct(void *arg) sp->id = i; sp->t_open = now; - HTC_Init(sp->htc, sp->ws, sp->fd); sp->step = STP_FIRST; WRK_QueueSession(sp); } diff --git a/varnish-cache/bin/varnishd/cache_center.c b/varnish-cache/bin/varnishd/cache_center.c index 5fb7b0f9..97e72c0b 100644 --- a/varnish-cache/bin/varnishd/cache_center.c +++ b/varnish-cache/bin/varnishd/cache_center.c @@ -221,6 +221,9 @@ cnt_done(struct sess *sp) return (1); } + /* Reset the workspace to the session-watermark */ + WS_Reset(sp->ws, sp->ws_ses); + i = HTC_Reinit(sp->htc); if (i == 1) { VSL_stats->sess_pipeline++; @@ -368,12 +371,19 @@ cnt_first(struct sess *sp) assert(sp->xid == 0); VCA_Prep(sp); + + /* Record the session watermark */ + sp->ws_ses = WS_Snapshot(sp->ws); + + /* Receive a HTTP protocol request */ + HTC_Init(sp->htc, sp->ws, sp->fd); sp->wrk->used = sp->t_open; sp->wrk->acct.sess++; SES_RefSrcAddr(sp); do i = HTC_Rx(sp->htc); while (i == 0); + switch (i) { case 1: sp->step = STP_RECV; @@ -734,7 +744,15 @@ cnt_recv(struct sess *sp) sp->vcl = sp->wrk->vcl; sp->wrk->vcl = NULL; + http_Setup(sp->http, sp->ws); done = http_DissectRequest(sp); + + /* Catch request snapshot */ + sp->ws_req = WS_Snapshot(sp->ws); + + /* Catch original request, before modification */ + *sp->http0 = *sp->http; + if (done != 0) { RES_Error(sp, done, NULL); /* XXX: STP_ERROR ? */ sp->step = STP_DONE; diff --git a/varnish-cache/bin/varnishd/cache_httpconn.c b/varnish-cache/bin/varnishd/cache_httpconn.c index 5f9c0a15..9e1eafe6 100644 --- a/varnish-cache/bin/varnishd/cache_httpconn.c +++ b/varnish-cache/bin/varnishd/cache_httpconn.c @@ -86,7 +86,6 @@ HTC_Init(struct http_conn *htc, struct ws *ws, int fd) htc->magic = HTTP_CONN_MAGIC; htc->ws = ws; htc->fd = fd; - WS_Reset(htc->ws); WS_Reserve(htc->ws, (htc->ws->e - htc->ws->s) / 2); htc->rxbuf.b = ws->f; htc->rxbuf.e = ws->f; @@ -107,7 +106,6 @@ HTC_Reinit(struct http_conn *htc) int i; CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC); - WS_Reset(htc->ws); WS_Reserve(htc->ws, (htc->ws->e - htc->ws->s) / 2); htc->rxbuf.b = htc->ws->f; htc->rxbuf.e = htc->ws->f; diff --git a/varnish-cache/bin/varnishd/cache_session.c b/varnish-cache/bin/varnishd/cache_session.c index 98e5277c..ca824017 100644 --- a/varnish-cache/bin/varnishd/cache_session.c +++ b/varnish-cache/bin/varnishd/cache_session.c @@ -65,7 +65,7 @@ struct sessmem { #define SESSMEM_MAGIC 0x555859c5 struct sess sess; - struct http http; + struct http http[2]; unsigned workspace; VTAILQ_ENTRY(sessmem) list; struct sockaddr_storage sockaddr[2]; @@ -319,8 +319,8 @@ SES_New(const struct sockaddr *addr, unsigned len) } WS_Init(sp->ws, (void *)(sm + 1), sm->workspace); - sp->http = &sm->http; - http_Setup(sp->http, sp->ws); + sp->http = &sm->http[0]; + sp->http0 = &sm->http[1]; return (sp); } diff --git a/varnish-cache/bin/varnishd/cache_vrt.c b/varnish-cache/bin/varnishd/cache_vrt.c index 2ae6be78..798fa215 100644 --- a/varnish-cache/bin/varnishd/cache_vrt.c +++ b/varnish-cache/bin/varnishd/cache_vrt.c @@ -509,6 +509,16 @@ VRT_int_string(const struct sess *sp, int num) /*--------------------------------------------------------------------*/ +void +VRT_Rollback(struct sess *sp) +{ + + *sp->http = *sp->http0; + WS_Reset(sp->ws, sp->ws_req); +} + +/*--------------------------------------------------------------------*/ + void VRT_purge(const char *regexp, int hash) { diff --git a/varnish-cache/bin/varnishd/cache_ws.c b/varnish-cache/bin/varnishd/cache_ws.c index a43e0751..684a6140 100644 --- a/varnish-cache/bin/varnishd/cache_ws.c +++ b/varnish-cache/bin/varnishd/cache_ws.c @@ -74,12 +74,18 @@ WS_Init(struct ws *ws, void *space, unsigned len) } void -WS_Reset(struct ws *ws) +WS_Reset(struct ws *ws, char *p) { WS_Assert(ws); assert(ws->r == NULL); - ws->f = ws->s; + if (p == NULL) + ws->f = ws->s; + else { + assert(p >= ws->s); + assert(p < ws->e); + ws->f = p; + } } char * @@ -109,6 +115,14 @@ WS_Dup(struct ws *ws, const char *s) return (p); } +char * +WS_Snapshot(struct ws *ws) +{ + + assert(ws->r == NULL); + return (ws->f); +} + unsigned WS_Reserve(struct ws *ws, unsigned bytes) { diff --git a/varnish-cache/include/vrt.h b/varnish-cache/include/vrt.h index ad4531ba..857732e0 100644 --- a/varnish-cache/include/vrt.h +++ b/varnish-cache/include/vrt.h @@ -114,7 +114,7 @@ void VRT_handling(struct sess *sp, unsigned hand); int VRT_strcmp(const char *s1, const char *s2); void VRT_ESI(struct sess *sp); - +void VRT_Rollback(struct sess *sp); /* Backend related */ void VRT_init_simple_backend(struct backend **, const struct vrt_simple_backend *); diff --git a/varnish-cache/lib/libvcl/vcc_action.c b/varnish-cache/lib/libvcl/vcc_action.c index e930e253..b225ca2f 100644 --- a/varnish-cache/lib/libvcl/vcc_action.c +++ b/varnish-cache/lib/libvcl/vcc_action.c @@ -54,6 +54,25 @@ parse_##l(struct tokenlist *tl) \ /*--------------------------------------------------------------------*/ +static void +parse_restart_real(struct tokenlist *tl) +{ + struct token *t1; + + t1 = VTAILQ_NEXT(tl->t, list); + if (t1->tok == ID && vcc_IdIs(t1, "rollback")) { + Fb(tl, 1, "VRT_Rollback(sp);\n"); + vcc_NextToken(tl); + } else if (t1->tok != ';') { + vsb_printf(tl->sb, "Expected \"rollback\" or semicolon.\n"); + vcc_ErrWhere(tl, t1); + ERRCHK(tl); + } + parse_restart(tl); +} + +/*--------------------------------------------------------------------*/ + static void parse_call(struct tokenlist *tl) { @@ -333,6 +352,7 @@ static struct action_table { const char *name; action_f *func; } action_table[] = { + { "restart", parse_restart_real }, #define VCL_RET_MAC(l, u, b, i) { #l, parse_##l }, #define VCL_RET_MAC_E(l, u, b, i) VCL_RET_MAC(l, u, b, i) #include "vcl_returns.h" diff --git a/varnish-cache/lib/libvcl/vcc_fixed_token.c b/varnish-cache/lib/libvcl/vcc_fixed_token.c index 8726484d..21d68c15 100644 --- a/varnish-cache/lib/libvcl/vcc_fixed_token.c +++ b/varnish-cache/lib/libvcl/vcc_fixed_token.c @@ -493,7 +493,7 @@ vcl_output_lang_h(struct vsb *sb) vsb_cat(sb, "int VRT_strcmp(const char *s1, const char *s2);\n"); vsb_cat(sb, "\n"); vsb_cat(sb, "void VRT_ESI(struct sess *sp);\n"); - vsb_cat(sb, "\n"); + vsb_cat(sb, "void VRT_Rollback(struct sess *sp);\n"); vsb_cat(sb, "\n"); vsb_cat(sb, "/* Backend related */\n"); vsb_cat(sb, "void VRT_init_simple_backend(struct backend **, const struct vrt_simple_backend *);\n");