Commit 4dd41763 authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

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: http://www.varnish-cache.org/svn/trunk/varnish-cache@2167 d4fa192b-c00b-0410-8231-f00ffab90ce4
parent 126d134b
......@@ -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);
......
......@@ -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);
}
......
......@@ -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;
......
......@@ -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;
......
......@@ -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);
}
......
......@@ -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)
{
......
......@@ -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)
{
......
......@@ -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 *);
......
......@@ -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"
......
......@@ -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");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment