]> err.no Git - varnish/commitdiff
Gently shuffle closer to being able to restart a esi:include on the next
authorphk <phk@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Wed, 24 Oct 2007 14:32:12 +0000 (14:32 +0000)
committerphk <phk@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Wed, 24 Oct 2007 14:32:12 +0000 (14:32 +0000)
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

varnish-cache/bin/varnishd/cache.h
varnish-cache/bin/varnishd/cache_acceptor.c
varnish-cache/bin/varnishd/cache_center.c
varnish-cache/bin/varnishd/cache_httpconn.c
varnish-cache/bin/varnishd/cache_session.c
varnish-cache/bin/varnishd/cache_vrt.c
varnish-cache/bin/varnishd/cache_ws.c
varnish-cache/include/vrt.h
varnish-cache/lib/libvcl/vcc_action.c
varnish-cache/lib/libvcl/vcc_fixed_token.c

index 6707c585e545c5d8b523246f5858c93e53c4c5b8..5f936f3efccd9ce016b253895c515a47fab6fe14 100644 (file)
@@ -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);
index 9c40c707a4770d93ce5677d64621395a25ed951b..bb0eb8799ca0eac7ad11544567f4d56e663d0093 100644 (file)
@@ -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);
                }
index 5fb7b0f9fc498e633188638e8016e190eac3b900..97e72c0bd37be9f0e58dcb762cc36948dc947776 100644 (file)
@@ -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;
index 5f9c0a157cd4e7d55fc14eaf2747200f2d89d7d3..9e1eafe680185fdef1d88c9397ddaa0cc410da9d 100644 (file)
@@ -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;
index 98e5277ca2fd3a7e1614cd8694d5b8ca76779512..ca824017015aa55d0d2f42b3843f00300f1959b5 100644 (file)
@@ -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);
 }
index 2ae6be78e35ed5681a1e0767b37cb50ea64e08c2..798fa215fdd8ee0647baa69ce0a88b9715f812a2 100644 (file)
@@ -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)
 {
index a43e0751d6da6f8e7aca6f1f3a3cd9074f0853b3..684a61402ae8a22b33af52419b358d448858c010 100644 (file)
@@ -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)
 {
index ad4531ba37429e51d565150f61648467ebdd9753..857732e03462e28eba2e07b22614ea1e1eb1b844 100644 (file)
@@ -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 *);
index e930e253647263074c9973b16190b1f7e5f3cbcf..b225ca2faa98cd77506327948ea1f300bdce12b7 100644 (file)
@@ -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"
index 8726484d4331d638d6fdbac1283d5f8dc4e2fc6d..21d68c15ee94676fc863f7c24ea27f696d91e2f8 100644 (file)
@@ -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");