From phk at varnish-cache.org Mon Mar 4 11:03:28 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Mon, 04 Mar 2013 12:03:28 +0100 Subject: [master] 760c4f6 This test needs to wait for s2 also, otherwise the "expect" there may never be reached. Message-ID: commit 760c4f6548b0e854affeccf81266dc2b1714ff04 Author: Poul-Henning Kamp Date: Mon Mar 4 11:02:21 2013 +0000 This test needs to wait for s2 also, otherwise the "expect" there may never be reached. Split out the param settings, so we can see the previous values. diff --git a/bin/varnishtest/tests.disabled/r01252.vtc b/bin/varnishtest/tests.disabled/r01252.vtc index c988da6..14d1d28 100644 --- a/bin/varnishtest/tests.disabled/r01252.vtc +++ b/bin/varnishtest/tests.disabled/r01252.vtc @@ -19,7 +19,7 @@ server s2 { txresp } -start -varnish v1 -arg "-p debug=+waitinglist -p tcp_keepalive_time=1s -p tcp_keepalive_probes=1 -p tcp_keepalive_intvl=1s -p first_byte_timeout=70" -vcl+backend { +varnish v1 -arg "-p debug=+waitinglist" -vcl+backend { sub vcl_recv { if (req.http.x-client == "2") { set req.backend = s2; @@ -27,6 +27,18 @@ varnish v1 -arg "-p debug=+waitinglist -p tcp_keepalive_time=1s -p tcp_keepalive } } -start +varnish v1 -cliok "param.show tcp_keepalive_time" +varnish v1 -cliok "param.set tcp_keepalive_time 1s" + +varnish v1 -cliok "param.show tcp_keepalive_probes" +varnish v1 -cliok "param.set tcp_keepalive_probes 1" + +varnish v1 -cliok "param.show tcp_keepalive_intvl" +varnish v1 -cliok "param.set tcp_keepalive_intvl 1s" + +varnish v1 -cliok "param.show first_byte_timeout" +varnish v1 -cliok "param.set first_byte_timeout 70s" + client c1 { timeout 70 txreq -hdr "X-Client: 1" @@ -42,3 +54,4 @@ client c2 { client c1 -wait client c2 -wait +server s2 -wait From phk at varnish-cache.org Mon Mar 4 13:15:37 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Mon, 04 Mar 2013 14:15:37 +0100 Subject: [master] a71250e Oops, shouldn't have units on that param. Message-ID: commit a71250e72217c4fd9e74080d4792f0cfeb128758 Author: Poul-Henning Kamp Date: Mon Mar 4 11:09:42 2013 +0000 Oops, shouldn't have units on that param. diff --git a/bin/varnishtest/tests.disabled/r01252.vtc b/bin/varnishtest/tests.disabled/r01252.vtc index 14d1d28..e055590 100644 --- a/bin/varnishtest/tests.disabled/r01252.vtc +++ b/bin/varnishtest/tests.disabled/r01252.vtc @@ -37,7 +37,7 @@ varnish v1 -cliok "param.show tcp_keepalive_intvl" varnish v1 -cliok "param.set tcp_keepalive_intvl 1s" varnish v1 -cliok "param.show first_byte_timeout" -varnish v1 -cliok "param.set first_byte_timeout 70s" +varnish v1 -cliok "param.set first_byte_timeout 70" client c1 { timeout 70 From phk at varnish-cache.org Tue Mar 5 07:19:52 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Tue, 05 Mar 2013 08:19:52 +0100 Subject: [master] e91ca73 Rewite the sockopt code to be table-driven. Message-ID: commit e91ca73f801171d78217df2f0bb2dafd3b27579b Author: Poul-Henning Kamp Date: Tue Mar 5 07:19:28 2013 +0000 Rewite the sockopt code to be table-driven. diff --git a/bin/varnishd/cache/cache_acceptor.c b/bin/varnishd/cache/cache_acceptor.c index 43ebe6e..5c8f30a 100644 --- a/bin/varnishd/cache/cache_acceptor.c +++ b/bin/varnishd/cache/cache_acceptor.c @@ -41,6 +41,7 @@ #include "config.h" +#include #include #include #include @@ -54,13 +55,48 @@ #include "vtim.h" static pthread_t VCA_thread; -static struct timeval tv_sndtimeo; -static struct timeval tv_rcvtimeo; static int hack_ready; static double vca_pace = 0.0; static struct lock pace_mtx; /*-------------------------------------------------------------------- + * TCP options we want to control + */ + +static struct tcp_opt { + int level; + int optname; + const char *strname; + socklen_t sz; + void *ptr; + int need; +} tcp_opts[] = { +#define TCPO(lvl, nam, sz) { lvl, nam, #nam, sizeof(sz), 0, 0}, + + TCPO(SOL_SOCKET, SO_LINGER, struct linger) + TCPO(SOL_SOCKET, SO_KEEPALIVE, int) + TCPO(IPPROTO_TCP, TCP_NODELAY, int) + +#ifdef SO_SNDTIMEO_WORKS + TCPO(SOL_SOCKET, SO_SNDTIMEO, struct timeval) +#endif + +#ifdef SO_RCVTIMEO_WORKS + TCPO(SOL_SOCKET, SO_RCVTIMEO, struct timeval) +#endif + +#ifdef HAVE_TCP_KEEP + TCPO(IPPROTO_TCP, TCP_KEEPIDLE, int) + TCPO(IPPROTO_TCP, TCP_KEEPCNT, int) + TCPO(IPPROTO_TCP, TCP_KEEPINTVL, int) +#endif + +#undef TCPO +}; + +static const int n_tcp_opts = sizeof tcp_opts / sizeof tcp_opts[0]; + +/*-------------------------------------------------------------------- * We want to get out of any kind of trouble-hit TCP connections as fast * as absolutely possible, so we set them LINGER enabled with zero timeout, * so that even if there are outstanding write data on the socket, a close(2) @@ -74,22 +110,8 @@ static const struct linger linger = { * We turn on keepalives by default to assist in detecting clients that have * hung up on connections returning from waitinglists */ -static const int keepalive = 1; -static unsigned char need_sndtimeo, need_rcvtimeo, need_linger, need_test, - need_tcpnodelay; -static unsigned char need_keepalive = 0; -#ifdef HAVE_TCP_KEEP -static unsigned char need_ka_time = 0; -static unsigned char need_ka_probes = 0; -static unsigned char need_ka_intvl = 0; -static int ka_time_cur = 0; -static int ka_probes_cur = 0; -static int ka_intvl_cur = 0; -static int ka_time, ka_time_sys; -static int ka_probes, ka_probes_sys; -static int ka_intvl, ka_intvl_sys; -#endif +static unsigned need_test; /*-------------------------------------------------------------------- * Some kernels have bugs/limitations with respect to which options are @@ -97,113 +119,106 @@ static int ka_intvl, ka_intvl_sys; * which, if any, sockopts we have to set on the accepted socket. */ -static void -sock_test(int fd) +static int +vca_tcp_opt_init() { - struct linger lin; - int tka; -#ifdef HAVE_TCP_KEEP - int tka_time, tka_probes, tka_intvl; -#endif + int n, x; + int one = 1; + // int zero = 0; + struct tcp_opt *to; struct timeval tv; - socklen_t l; - int i, tcp_nodelay; - - l = sizeof lin; - i = getsockopt(fd, SOL_SOCKET, SO_LINGER, &lin, &l); - if (i) { - VTCP_Assert(i); - return; - } - assert(l == sizeof lin); - if (memcmp(&lin, &linger, l)) - need_linger = 1; - - l = sizeof tka; - i = getsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &tka, &l); - if (i) { - VTCP_Assert(i); - return; - } - assert(l == sizeof tka); - if (tka != keepalive) - need_keepalive = 1; - -#ifdef HAVE_TCP_KEEP - l = sizeof tka_time; - i = getsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &tka_time, &l); - if (i) { - VTCP_Assert(i); - return; - } - assert(l == sizeof tka_time); - if (tka_time != ka_time_cur) - need_ka_time = 1; - - l = sizeof tka_probes; - i = getsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &tka_probes, &l); - if (i) { - VTCP_Assert(i); - return; - } - assert(l == sizeof tka_probes); - if (tka_probes != ka_probes_cur) - need_ka_probes = 1; - - l = sizeof tka_intvl; - i = getsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &tka_intvl, &l); - if (i) { - VTCP_Assert(i); - return; - } - assert(l == sizeof tka_intvl); - if (tka_intvl != ka_intvl_cur) - need_ka_intvl = 1; -#endif + int chg = 0; + + for (n = 0; n < n_tcp_opts; n++) { + to = &tcp_opts[n]; + if (to->ptr == NULL) + to->ptr = calloc(to->sz, 1); + AN(to->ptr); + if (!strcmp(to->strname, "SO_LINGER")) { + assert(to->sz == sizeof linger); + memcpy(to->ptr, &linger, sizeof linger); + to->need = 1; + } else if (!strcmp(to->strname, "TCP_NODELAY")) { + assert(to->sz == sizeof one); + memcpy(to->ptr, &one, sizeof one); + to->need = 1; + } else if (!strcmp(to->strname, "SO_KEEPALIVE")) { + assert(to->sz == sizeof one); + memcpy(to->ptr, &one, sizeof one); + to->need = 1; +#define NEW_VAL(to, xx) \ + do { \ + assert(to->sz == sizeof xx); \ + if (memcmp(to->ptr, &(xx), sizeof xx)) { \ + memcpy(to->ptr, &(xx), sizeof xx); \ + to->need = 1; \ + chg = 1; \ + need_test = 1; \ + } \ + } while (0) #ifdef SO_SNDTIMEO_WORKS - l = sizeof tv; - i = getsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, &l); - if (i) { - VTCP_Assert(i); - return; - } - assert(l == sizeof tv); - if (memcmp(&tv, &tv_sndtimeo, l)) - need_sndtimeo = 1; -#else - (void)tv; - (void)tv_sndtimeo; - (void)need_sndtimeo; + } else if (!strcmp(to->strname, "SO_SNDTIMEO")) { + tv = VTIM_timeval(cache_param->idle_send_timeout); + NEW_VAL(to, tv); #endif - #ifdef SO_RCVTIMEO_WORKS - l = sizeof tv; - i = getsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, &l); - if (i) { - VTCP_Assert(i); - return; - } - assert(l == sizeof tv); - if (memcmp(&tv, &tv_rcvtimeo, l)) - need_rcvtimeo = 1; -#else - (void)tv; - (void)tv_rcvtimeo; - (void)need_rcvtimeo; + } else if (!strcmp(to->strname, "SO_RCVTIMEO")) { + tv = VTIM_timeval(cache_param->timeout_idle); + NEW_VAL(to, tv); +#endif +#ifdef HAVE_TCP_KEEP + } else if (!strcmp(to->strname, "TCP_KEEPIDLE")) { + x = cache_param->tcp_keepalive_time; + NEW_VAL(to, x); + } else if (!strcmp(to->strname, "TCP_KEEPCNT")) { + x = cache_param->tcp_keepalive_probes; + NEW_VAL(to, x); + } else if (!strcmp(to->strname, "TCP_KEEPINTVL")) { + x = cache_param->tcp_keepalive_intvl; + NEW_VAL(to, x); #endif + } + } + return (chg); +} - l = sizeof tcp_nodelay; - i = getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &tcp_nodelay, &l); - if (i) { - VTCP_Assert(i); - return; +static void +vca_tcp_opt_test(int sock) +{ + int i, n; + struct tcp_opt *to; + socklen_t l; + void *ptr; + + for (n = 0; n < n_tcp_opts; n++) { + to = &tcp_opts[n]; + to->need = 1; + ptr = calloc(to->sz, 1); + AN(ptr); + l = to->sz; + i = getsockopt(sock, to->level, to->optname, ptr, &l); + if (i == 0 && !memcmp(ptr, to->ptr, to->sz)) + to->need = 0; + free(ptr); + if (i && errno != ENOPROTOOPT) + VTCP_Assert(i); } - assert(l == sizeof tcp_nodelay); - if (!tcp_nodelay) - need_tcpnodelay = 1; +} - need_test = 0; +static void +vca_tcp_opt_set(int sock, int force) +{ + int n; + struct tcp_opt *to; + + for (n = 0; n < n_tcp_opts; n++) { + to = &tcp_opts[n]; + if (to->need || force) { + VTCP_Assert(setsockopt(sock, + to->level, to->optname, to->ptr, to->sz)); + } + } } /*-------------------------------------------------------------------- @@ -325,7 +340,6 @@ VCA_SetupSess(struct worker *wrk, struct sess *sp) { struct wrk_accept *wa; const char *retval; - int tcp_nodelay = 1; CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); @@ -340,123 +354,55 @@ VCA_SetupSess(struct worker *wrk, struct sess *sp) wrk->stats.sess_conn++; WS_Release(wrk->aws, 0); - if (need_test) - sock_test(sp->fd); - if (need_linger) - VTCP_Assert(setsockopt(sp->fd, SOL_SOCKET, SO_LINGER, - &linger, sizeof linger)); - if (need_keepalive) - VTCP_Assert(setsockopt(sp->fd, SOL_SOCKET, SO_KEEPALIVE, - &keepalive, sizeof keepalive)); -#ifdef HAVE_TCP_KEEP - AN(ka_time); - if (need_ka_time) - VTCP_Assert(setsockopt(sp->fd, IPPROTO_TCP, TCP_KEEPIDLE, - &ka_time_cur, sizeof ka_time_cur)); - if (need_ka_probes) - VTCP_Assert(setsockopt(sp->fd, IPPROTO_TCP, TCP_KEEPCNT, - &ka_probes_cur, sizeof ka_probes_cur)); - if (need_ka_intvl) - VTCP_Assert(setsockopt(sp->fd, IPPROTO_TCP, TCP_KEEPINTVL, - &ka_intvl_cur, sizeof ka_intvl_cur)); -#endif - -#ifdef SO_SNDTIMEO_WORKS - if (need_sndtimeo) - VTCP_Assert(setsockopt(sp->fd, SOL_SOCKET, SO_SNDTIMEO, - &tv_sndtimeo, sizeof tv_sndtimeo)); -#endif -#ifdef SO_RCVTIMEO_WORKS - if (need_rcvtimeo) - VTCP_Assert(setsockopt(sp->fd, SOL_SOCKET, SO_RCVTIMEO, - &tv_rcvtimeo, sizeof tv_rcvtimeo)); -#endif - if (need_tcpnodelay) - VTCP_Assert(setsockopt(sp->fd, IPPROTO_TCP, TCP_NODELAY, - &tcp_nodelay, sizeof tcp_nodelay)); + if (need_test) { + vca_tcp_opt_test(sp->fd); + need_test = 0; + } + vca_tcp_opt_set(sp->fd, 0); return (retval); } /*--------------------------------------------------------------------*/ +#ifdef HAVE_TCP_KEEP +static void +vca_tcp_keep_probe(int sock, int nam, volatile unsigned *dst) +{ + int i, x; + socklen_t l; + + l = sizeof x; + i = getsockopt(sock, IPPROTO_TCP, nam, &x, &l); + if (i == 0 && x < *dst) + *dst = x; +} +#endif + static void * vca_acct(void *arg) { -#ifdef SO_RCVTIMEO_WORKS - double timeout_idle = 0; -#endif -#ifdef SO_SNDTIMEO_WORKS - double send_timeout = 0; -#endif - int tcp_nodelay = 1; struct listen_sock *ls; double t0, now; int i; -#ifdef HAVE_TCP_KEEP - socklen_t len; -#endif THR_SetName("cache-acceptor"); (void)arg; -#ifdef HAVE_TCP_KEEP - ka_time = cache_param->tcp_keepalive_time; - ka_probes = cache_param->tcp_keepalive_probes; - ka_intvl = cache_param->tcp_keepalive_intvl; -#endif + (void)vca_tcp_opt_init(); VTAILQ_FOREACH(ls, &heritage.socks, list) { if (ls->sock < 0) continue; AZ(listen(ls->sock, cache_param->listen_depth)); - AZ(setsockopt(ls->sock, SOL_SOCKET, SO_LINGER, - &linger, sizeof linger)); - AZ(setsockopt(ls->sock, IPPROTO_TCP, TCP_NODELAY, - &tcp_nodelay, sizeof tcp_nodelay)); - AZ(setsockopt(ls->sock, SOL_SOCKET, SO_KEEPALIVE, - &keepalive, sizeof keepalive)); #ifdef HAVE_TCP_KEEP - if (!ka_time_cur) { - len = sizeof ka_time_sys; - AZ(getsockopt(ls->sock, IPPROTO_TCP, TCP_KEEPIDLE, - &ka_time_sys, &len)); - assert(len == sizeof ka_time_sys); - AN(ka_time_sys); - ka_time_cur = ka_time = - (ka_time_sys < cache_param->tcp_keepalive_time ? - ka_time_sys : cache_param->tcp_keepalive_time); - } - AZ(setsockopt(ls->sock, IPPROTO_TCP, TCP_KEEPIDLE, - &ka_time_cur, sizeof ka_time_cur)); - - if (!ka_probes_cur) { - len = sizeof ka_probes_sys; - AZ(getsockopt(ls->sock, IPPROTO_TCP, TCP_KEEPCNT, - &ka_probes_sys, &len)); - assert(len == sizeof ka_probes_sys); - AN(ka_probes_sys); - ka_probes_cur = ka_probes = - (ka_probes_sys < cache_param->tcp_keepalive_probes ? - ka_probes_sys : - cache_param->tcp_keepalive_probes); - } - AZ(setsockopt(ls->sock, IPPROTO_TCP, TCP_KEEPCNT, - &ka_probes_cur, sizeof ka_probes_cur)); - - if (!ka_intvl_cur) { - len = sizeof ka_intvl_sys; - AZ(getsockopt(ls->sock, IPPROTO_TCP, TCP_KEEPINTVL, - &ka_intvl_sys, &len)); - assert(len == sizeof ka_intvl_sys); - AN(ka_intvl_sys); - ka_intvl_cur = ka_intvl = - (ka_intvl_sys < cache_param->tcp_keepalive_intvl ? - ka_intvl_sys : - cache_param->tcp_keepalive_intvl); - } - AZ(setsockopt(ls->sock, IPPROTO_TCP, TCP_KEEPINTVL, - &ka_intvl_cur, sizeof ka_intvl_cur)); + vca_tcp_keep_probe(ls->sock, + TCP_KEEPIDLE, &cache_param->tcp_keepalive_time); + vca_tcp_keep_probe(ls->sock, + TCP_KEEPCNT, &cache_param->tcp_keepalive_probes); + vca_tcp_keep_probe(ls->sock, + TCP_KEEPINTVL, &cache_param->tcp_keepalive_intvl); #endif + vca_tcp_opt_set(ls->sock, 1); if (cache_param->accept_filter) { i = VTCP_filter_http(ls->sock); if (i) @@ -472,63 +418,13 @@ vca_acct(void *arg) t0 = VTIM_real(); while (1) { (void)sleep(1); -#ifdef HAVE_TCP_KEEP - ka_time = (ka_time_sys < cache_param->tcp_keepalive_time ? - ka_time_sys : cache_param->tcp_keepalive_time); - ka_probes = (ka_probes_sys < cache_param->tcp_keepalive_probes ? - ka_probes_sys : cache_param->tcp_keepalive_probes); - ka_intvl = (ka_intvl_sys < cache_param->tcp_keepalive_intvl ? - ka_intvl_sys : cache_param->tcp_keepalive_intvl); - if (ka_time_cur != ka_time || - ka_probes_cur != ka_probes || - ka_intvl_cur != ka_intvl) { - need_test = 1; - ka_time_cur = ka_time; - ka_probes_cur = ka_probes; - ka_intvl_cur = ka_intvl; - VTAILQ_FOREACH(ls, &heritage.socks, list) { - if (ls->sock < 0) - continue; - AZ(setsockopt(ls->sock, IPPROTO_TCP, - TCP_KEEPIDLE, - &ka_time_cur, sizeof ka_time_cur)); - AZ(setsockopt(ls->sock, IPPROTO_TCP, - TCP_KEEPCNT, - &ka_probes_cur, sizeof ka_probes_cur)); - AZ(setsockopt(ls->sock, IPPROTO_TCP, - TCP_KEEPINTVL, - &ka_intvl_cur, sizeof ka_intvl_cur)); - } - } -#endif -#ifdef SO_SNDTIMEO_WORKS - if (cache_param->idle_send_timeout != send_timeout) { - need_test = 1; - send_timeout = cache_param->idle_send_timeout; - tv_sndtimeo = VTIM_timeval(send_timeout); - VTAILQ_FOREACH(ls, &heritage.socks, list) { - if (ls->sock < 0) - continue; - AZ(setsockopt(ls->sock, SOL_SOCKET, - SO_SNDTIMEO, - &tv_sndtimeo, sizeof tv_sndtimeo)); - } - } -#endif -#ifdef SO_RCVTIMEO_WORKS - if (cache_param->timeout_idle != timeout_idle) { - need_test = 1; - timeout_idle = cache_param->timeout_idle; - tv_rcvtimeo = VTIM_timeval(timeout_idle); + if (vca_tcp_opt_init()) { VTAILQ_FOREACH(ls, &heritage.socks, list) { if (ls->sock < 0) continue; - AZ(setsockopt(ls->sock, SOL_SOCKET, - SO_RCVTIMEO, - &tv_rcvtimeo, sizeof tv_rcvtimeo)); + vca_tcp_opt_set(ls->sock, 1); } } -#endif now = VTIM_real(); VSC_C_main->uptime = (uint64_t)(now - t0); } From martin at varnish-cache.org Tue Mar 5 13:28:27 2013 From: martin at varnish-cache.org (Martin Blix Grydeland) Date: Tue, 05 Mar 2013 14:28:27 +0100 Subject: [master] 640b2e4 Don't wait for s2, as that should block forever on test success. Message-ID: commit 640b2e4e10a82347927bee584aa258f62ccf2375 Author: Martin Blix Grydeland Date: Tue Mar 5 14:22:00 2013 +0100 Don't wait for s2, as that should block forever on test success. Add a delay after setting parameters to allow acceptor thread to pick them up. Add a delay in c1 after receiving result to allow time for any fail causing fetches from s2 diff --git a/bin/varnishtest/tests.disabled/r01252.vtc b/bin/varnishtest/tests.disabled/r01252.vtc index e055590..174ee97 100644 --- a/bin/varnishtest/tests.disabled/r01252.vtc +++ b/bin/varnishtest/tests.disabled/r01252.vtc @@ -2,7 +2,7 @@ varnishtest "#1252 - Drop remote closed connections returning from waitinglists" # This test case is disabled because it will only pass on platforms # where the tcp_keepalive_* runtime arguments are available, and also -# because it requires "-t 75" argument to varnishtest (remote closed +# because it requires "-t 80" argument to varnishtest (remote closed # state will only be detected after FIN timeout has passed (60s)) server s1 { @@ -39,11 +39,14 @@ varnish v1 -cliok "param.set tcp_keepalive_intvl 1s" varnish v1 -cliok "param.show first_byte_timeout" varnish v1 -cliok "param.set first_byte_timeout 70" +delay 2 + client c1 { timeout 70 txreq -hdr "X-Client: 1" rxresp expect resp.status == 503 + delay 2 } -start client c2 { @@ -54,4 +57,3 @@ client c2 { client c1 -wait client c2 -wait -server s2 -wait From phk at varnish-cache.org Wed Mar 6 08:00:44 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Wed, 06 Mar 2013 09:00:44 +0100 Subject: [master] 00dbfb7 Allow for naming arguments in .vcc files Message-ID: commit 00dbfb76f8245be2c6d667e8bd1272e9fe28a9e2 Author: Poul-Henning Kamp Date: Wed Mar 6 08:00:28 2013 +0000 Allow for naming arguments in .vcc files diff --git a/lib/libvcl/vmodtool.py b/lib/libvcl/vmodtool.py index 9447549..4d964cf 100755 --- a/lib/libvcl/vmodtool.py +++ b/lib/libvcl/vmodtool.py @@ -265,6 +265,8 @@ class func(object): fo.write(self.pfx) for a in self.al: fo.write(", " + ctypes[a.typ]) + if a.nam != None: + fo.write(" " + a.nam) fo.write(");\n") def c_typedef(self, modname): @@ -459,6 +461,9 @@ def parse_func(tl, rt_type = None, obj=None): al.append(arg(t.str)) else: raise Exception("ARG? %s" % t.str) + if is_c_name(tl[0].str): + al[-1].nam = tl[0].str + t = tl.pop(0) if tl[0].str == ",": tl.pop(0) elif tl[0].str != ")": diff --git a/lib/libvmod_debug/vmod.vcc b/lib/libvmod_debug/vmod.vcc index 653f168..57d8721 100644 --- a/lib/libvmod_debug/vmod.vcc +++ b/lib/libvmod_debug/vmod.vcc @@ -32,6 +32,6 @@ Function STRING author(ENUM { phk, des, kristian, mithrandir }) Function VOID test_priv_call(PRIV_CALL) Function VOID test_priv_vcl(PRIV_VCL) Object obj(STRING) { - Method STRING .foo(STRING) + Method STRING .foo(STRING why) Method TIME .date() } From phk at varnish-cache.org Wed Mar 6 09:33:39 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Wed, 06 Mar 2013 10:33:39 +0100 Subject: [master] fdbd28d Try to explain the init/fini/locking mechanics. Message-ID: commit fdbd28d4b8d45679ee509a08446f699004392dfd Author: Poul-Henning Kamp Date: Wed Mar 6 09:33:17 2013 +0000 Try to explain the init/fini/locking mechanics. diff --git a/doc/sphinx/reference/vmod.rst b/doc/sphinx/reference/vmod.rst index b9eb22a..88ff800 100644 --- a/doc/sphinx/reference/vmod.rst +++ b/doc/sphinx/reference/vmod.rst @@ -50,7 +50,7 @@ The first line gives the name of the module, nothing special there. The second line specifies an optional "Init" function, which will be called whenever a VCL program which imports this VMOD is loaded. This gives a chance to initialize the module before any of the -functions it implements are called. +functions it implements are called. More on this below. The next three lines specify two functions in the VMOD, along with the types of the arguments, and that is probably where the hardest bit @@ -235,5 +235,43 @@ pointer points to. When a VCL program is discarded, all private pointers are checked to see if both the "priv" and "free" elements are non-NULL, and if they are, the "free" function will be called with the "priv" pointer -as only argument. The "per vcl" pointers is guaranteed to be the -last one inspected. +as only argument. + +The per-call vmod_privs are freed before the per-vcl vmod_priv. + +Init functions +============== + +VMODs can have an "init" method which is called when a VCL +which imports the VMOD is initialized. + +The first argument to the init function is the vmod_priv specific +to this particular VCL, and if necessary, a VCL specific VMOD "fini" +function can be attached to its "free" hook. + +(The second argument is a pointer to the VCL's config structure, +it is not at all obvious what you can use this for in practice, +but we provide it just in case.) + +Please notice that there is no "global" fini method. + +If the VMOD has private global state, which includes any sockets +or files opened, any memory allocated to global or private variables +in the C-code etc, it is the VMODs own responsibility to track how +many VCLs have called init (& fini) and free this global state +when the count reaches zero. + +When to lock, and when not to lock +================================== + +Varnish is heavily multithreaded, so by default VMODs must implement +their own locking to protect shared resources. + +When a VCL is loaded or unloaded, the initializtion and teardown +is run sequentially in a single thread, and there is guaranteed +to be no other activity related to this particular VCL, nor are +there init/fini activity in any other VCL or VMOD at this time. + +That means that the VMOD init, and any object init/fini functions +are already serialized in sensible order, and won't need any locking, +unless they access VMOD specific global state, shared with other VCLs. From phk at varnish-cache.org Wed Mar 6 17:30:41 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Wed, 06 Mar 2013 18:30:41 +0100 Subject: [master] 88624c7 Remove unneeded vmod::fini stuff, the vmod_priv::delete serves that purpose. Message-ID: commit 88624c7c97e4b5b35cbec1b67c1ec4a5ad684e05 Author: Poul-Henning Kamp Date: Wed Mar 6 17:30:04 2013 +0000 Remove unneeded vmod::fini stuff, the vmod_priv::delete serves that purpose. diff --git a/lib/libvcl/vmodtool.py b/lib/libvcl/vmodtool.py index 4d964cf..97fd398 100755 --- a/lib/libvcl/vmodtool.py +++ b/lib/libvcl/vmodtool.py @@ -97,7 +97,6 @@ class vmod(object): raise Exception("Module name '%s' is illegal" % nam) self.nam = nam self.init = None - self.fini = None self.funcs = list() self.objs = list() @@ -108,13 +107,6 @@ class vmod(object): raise Exception("Init name '%s' is illegal" % nam) self.init = nam - def set_fini(self, nam): - if self.fini != None: - raise Exception("Module %s already has Fini" % self.nam) - if not is_c_name(nam): - raise Exception("Fini name '%s' is illegal" % nam) - self.fini = nam - def add_func(self, fn): self.funcs.append(fn) @@ -131,10 +123,6 @@ class vmod(object): fo.write("int " + self.init) fo.write( "(struct vmod_priv *, const struct VCL_conf *);\n") - if self.fini != None: - fo.write("int " + self.fini) - fo.write( - "(struct vmod_priv *, const struct VCL_conf *);\n") fo.write("extern const void * const Vmod_Id;\n") def c_typedefs_(self): @@ -193,8 +181,6 @@ class vmod(object): s += "\n\t/* Init/Fini */\n" if self.init != None: s += "\t" + self.init + ",\n" - if self.fini != None: - s += "\t" + self.fini + ",\n" s += "};" return s @@ -211,8 +197,6 @@ class vmod(object): s += "\n\t/* Init/Fini */\n" if self.init != None: s += "\tvmod_init_f\t*_init;\n" - if self.fini != None: - s += "\tvmod_fini_f\t*_fini;\n" s += '}' return s @@ -229,8 +213,6 @@ class vmod(object): s += "\n\t/* Init/Fini */\n" if self.init != None: s += '\t"INIT\\0Vmod_Func_' + self.nam + '._init",\n' - if self.fini != None: - s += '\t"FINI\\0Vmod_Func_' + self.nam + '._fini",\n' s += "\t0\n" s += "};\n" @@ -512,9 +494,6 @@ while len(tl) > 0: if t.str == "Init": t = tl.pop(0) vmod.set_init(t.str) - elif t.str == "Fini": - t = tl.pop(0) - vmod.set_fini(t.str) elif t.str == "Function": f = parse_func(tl) vmod.add_func(f) From phk at varnish-cache.org Wed Mar 6 19:18:39 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Wed, 06 Mar 2013 20:18:39 +0100 Subject: [master] 4a6430b Fix a bug which prevents multiple objects per vmod Message-ID: commit 4a6430bb61544654bc21e15c16ae921a1b0bb1c6 Author: Poul-Henning Kamp Date: Wed Mar 6 19:18:23 2013 +0000 Fix a bug which prevents multiple objects per vmod diff --git a/lib/libvcl/vmodtool.py b/lib/libvcl/vmodtool.py index 97fd398..7a3b0b1 100755 --- a/lib/libvcl/vmodtool.py +++ b/lib/libvcl/vmodtool.py @@ -321,7 +321,7 @@ class obj(object): fo.write(self.st + ";\n") self.init.c_proto(fo) self.fini.c_proto(fo) - for m in o.methods: + for m in self.methods: m.c_proto(fo) def c_struct(self, modnam): From phk at varnish-cache.org Wed Mar 6 19:22:35 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Wed, 06 Mar 2013 20:22:35 +0100 Subject: [master] 16ae07b Polish some whitespace in the emitted vcc_if.[ch] files Message-ID: commit 16ae07b74d2a25ba0d1170c5a051891b9fbf4691 Author: Poul-Henning Kamp Date: Wed Mar 6 19:22:22 2013 +0000 Polish some whitespace in the emitted vcc_if.[ch] files diff --git a/lib/libvcl/vmodtool.py b/lib/libvcl/vmodtool.py index 7a3b0b1..f20362f 100755 --- a/lib/libvcl/vmodtool.py +++ b/lib/libvcl/vmodtool.py @@ -117,12 +117,15 @@ class vmod(object): def c_proto(self, fo): for o in self.objs: o.c_proto(fo) + fo.write("\n") for f in self.funcs: f.c_proto(fo) if self.init != None: + fo.write("\n") fo.write("int " + self.init) fo.write( "(struct vmod_priv *, const struct VCL_conf *);\n") + fo.write("\n") fo.write("extern const void * const Vmod_Id;\n") def c_typedefs_(self): @@ -130,10 +133,11 @@ class vmod(object): for o in self.objs: for t in o.c_typedefs(self.nam): l.append(t) - l.append("") + l.append("") l.append("/* Functions */") for f in self.funcs: l.append(f.c_typedef(self.nam)) + l.append("") return l def c_typedefs(self, fo): @@ -530,7 +534,6 @@ fc.write("""#include "config.h" """) vmod.c_typedefs(fc) -fc.write("\n") vmod.c_vmod(fc) fc.close() From phk at varnish-cache.org Wed Mar 6 19:58:56 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Wed, 06 Mar 2013 20:58:56 +0100 Subject: [master] e81bdb1 remove vmod.fini crumbs Message-ID: commit e81bdb1c0a29f8c7016efddf64de4ce84fc21f61 Author: Poul-Henning Kamp Date: Wed Mar 6 19:55:16 2013 +0000 remove vmod.fini crumbs diff --git a/lib/libvcl/vcc_vmod.c b/lib/libvcl/vcc_vmod.c index 42fc1b6..874c899 100644 --- a/lib/libvcl/vcc_vmod.c +++ b/lib/libvcl/vcc_vmod.c @@ -172,9 +172,6 @@ vcc_ParseImport(struct vcc *tl) sym = VCC_AddSymbolStr(tl, p, SYM_OBJECT); XXXAN(sym); sym->args = p; - } else if (!strcmp(p, "FINI")) { - p += strlen(p) + 1; - // Nothing yet } else if (!strcmp(p, "INIT")) { p += strlen(p) + 1; Fi(tl, 0, "\t%s(&vmod_priv_%.*s, &VCL_conf);\n", From phk at varnish-cache.org Wed Mar 6 19:58:56 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Wed, 06 Mar 2013 20:58:56 +0100 Subject: [master] 8d9597e Remember to mark VMOD object methods which return VOID as SYM_PROC Message-ID: commit 8d9597e1e7dc2237a02f552ddb2feb63f417780b Author: Poul-Henning Kamp Date: Wed Mar 6 19:55:34 2013 +0000 Remember to mark VMOD object methods which return VOID as SYM_PROC diff --git a/lib/libvcl/vcc_action.c b/lib/libvcl/vcc_action.c index 40b56f8..50e912d 100644 --- a/lib/libvcl/vcc_action.c +++ b/lib/libvcl/vcc_action.c @@ -231,10 +231,16 @@ parse_new(struct vcc *tl) p += strlen(s_obj); bprintf(buf2, "%s%s", sy1->name, p); sy3 = VCC_AddSymbolStr(tl, buf2, SYM_FUNC); + AN(sy3); sy3->eval = vcc_Eval_SymFunc; p += strlen(p) + 1; sy3->cfunc = p; p += strlen(p) + 1; + + /* Functions which return VOID are procedures */ + if (!memcmp(p, "VOID\0", 5)) + sy3->kind = SYM_PROC; + sy3->args = p; sy3->extra = TlDup(tl, buf1); while (p[0] != '\0' || p[1] != '\0') From phk at varnish-cache.org Wed Mar 6 19:58:56 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Wed, 06 Mar 2013 20:58:56 +0100 Subject: [master] 9aab053 Add a proof-of-concept round-robin director as a VMOD object Message-ID: commit 9aab053b96f4373c519bb228988430601357db06 Author: Poul-Henning Kamp Date: Wed Mar 6 19:58:40 2013 +0000 Add a proof-of-concept round-robin director as a VMOD object diff --git a/bin/varnishtest/tests/m00009.vtc b/bin/varnishtest/tests/m00009.vtc new file mode 100644 index 0000000..b81f07e --- /dev/null +++ b/bin/varnishtest/tests/m00009.vtc @@ -0,0 +1,69 @@ +varnishtest "Test vmod.debug round robin director" + + +server s1 { + rxreq + txresp -body "1" +} -start + +server s2 { + rxreq + txresp -body "22" +} -start + + +server s3 { + rxreq + txresp -body "333" +} -start + +server s4 { + rxreq + txresp -body "4444" +} -start + + +varnish v1 -vcl+backend { + + import debug from "${topbuild}/lib/libvmod_debug/.libs/libvmod_debug.so" ; + sub vcl_init { + new rr = debug.rr(); + rr.add_backend(s1); + rr.add_backend(s2); + rr.add_backend(s3); + rr.add_backend(s4); + } + + sub vcl_recv { + set req.backend = rr.select(); + } +} -start + +client c1 { + timeout 3 + txreq -url "/foo1" + rxresp + expect resp.bodylen == 1 + txreq -url "/foo2" + rxresp + expect resp.bodylen == 2 + txreq -url "/foo3" + rxresp + expect resp.bodylen == 3 + txreq -url "/foo4" + rxresp + expect resp.bodylen == 4 +} -run + +server s1 -start +server s2 -start + +client c2 { + timeout 3 + txreq -url "/foo11" + rxresp + expect resp.bodylen == 1 + txreq -url "/foo22" + rxresp + expect resp.bodylen == 2 +} -run diff --git a/lib/libvmod_debug/vmod.vcc b/lib/libvmod_debug/vmod.vcc index 57d8721..97d5f5e 100644 --- a/lib/libvmod_debug/vmod.vcc +++ b/lib/libvmod_debug/vmod.vcc @@ -35,3 +35,8 @@ Object obj(STRING) { Method STRING .foo(STRING why) Method TIME .date() } + +Object rr() { + Method VOID .add_backend(BACKEND) + Method BACKEND .select() +} diff --git a/lib/libvmod_debug/vmod_debug_obj.c b/lib/libvmod_debug/vmod_debug_obj.c index d44e634..3ec94e1 100644 --- a/lib/libvmod_debug/vmod_debug_obj.c +++ b/lib/libvmod_debug/vmod_debug_obj.c @@ -86,3 +86,86 @@ vmod_obj_date(struct req *req, struct vmod_debug_obj *o) assert(o->foobar == 42); return (21.4); } + +/*----------------------------------------------------------------------*/ + +struct vmod_debug_rr_entry { + unsigned magic; +#define VMOD_DEBUG_RR_ENTRY_MAGIC 0xa80970cf + VTAILQ_ENTRY(vmod_debug_rr_entry) list; + VCL_BACKEND be; +}; + +struct vmod_debug_rr { + unsigned magic; +#define VMOD_DEBUG_RR_MAGIC 0x99f4b726 + VTAILQ_HEAD(, vmod_debug_rr_entry) listhead; + pthread_mutex_t mtx; +}; + +VCL_VOID +vmod_rr__init(struct req *req, struct vmod_debug_rr **rrp) +{ + struct vmod_debug_rr *rr; + + (void)req; + + AN(rrp); + AZ(*rrp); + ALLOC_OBJ(rr, VMOD_DEBUG_RR_MAGIC); + AN(rr); + *rrp = rr; + AZ(pthread_mutex_init(&rr->mtx, NULL)); + VTAILQ_INIT(&rr->listhead); +} + +VCL_VOID +vmod_rr__fini(struct req *req, struct vmod_debug_rr **rrp) +{ + struct vmod_debug_rr *rr; + struct vmod_debug_rr_entry *ep; + + (void)req; + + rr = *rrp; + *rrp = NULL; + CHECK_OBJ_NOTNULL(rr, VMOD_DEBUG_RR_MAGIC); + + AZ(pthread_mutex_destroy(&rr->mtx)); + while (!VTAILQ_EMPTY(&rr->listhead)) { + ep = VTAILQ_FIRST(&rr->listhead); + VTAILQ_REMOVE(&rr->listhead, ep, list); + FREE_OBJ(ep); + } + FREE_OBJ(*rrp); +} + +VCL_VOID +vmod_rr_add_backend(struct req *req, struct vmod_debug_rr * rr, VCL_BACKEND be) +{ + struct vmod_debug_rr_entry *ep; + (void)req; + + ALLOC_OBJ(ep, VMOD_DEBUG_RR_ENTRY_MAGIC); + AN(ep); + ep->be = be; + AZ(pthread_mutex_lock(&rr->mtx)); + VTAILQ_INSERT_TAIL(&rr->listhead, ep, list); + AZ(pthread_mutex_unlock(&rr->mtx)); +} + +VCL_BACKEND +vmod_rr_select(struct req *req, struct vmod_debug_rr *rr) +{ + struct vmod_debug_rr_entry *ep; + + (void)req; + + CHECK_OBJ_NOTNULL(rr, VMOD_DEBUG_RR_MAGIC); + AZ(pthread_mutex_lock(&rr->mtx)); + ep = VTAILQ_FIRST(&rr->listhead); + VTAILQ_REMOVE(&rr->listhead, ep, list); + VTAILQ_INSERT_TAIL(&rr->listhead, ep, list); + AZ(pthread_mutex_unlock(&rr->mtx)); + return (ep->be); +} From phk at varnish-cache.org Wed Mar 6 20:53:30 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Wed, 06 Mar 2013 21:53:30 +0100 Subject: [master] 011944d Change the C-symbols a VMOD exports to contain the vmod name, to eliminate any chance of collissions. Message-ID: commit 011944d3575cefb726cc341458a9def4df4fb3cf Author: Poul-Henning Kamp Date: Wed Mar 6 20:52:30 2013 +0000 Change the C-symbols a VMOD exports to contain the vmod name, to eliminate any chance of collissions. Check the ABI. This check may be too strong, but at least its safe. diff --git a/bin/varnishd/cache/cache_vrt_vmod.c b/bin/varnishd/cache/cache_vrt_vmod.c index 93d82f9..3a90a4d 100644 --- a/bin/varnishd/cache/cache_vrt_vmod.c +++ b/bin/varnishd/cache/cache_vrt_vmod.c @@ -32,12 +32,14 @@ #include "config.h" #include +#include #include #include "cache.h" #include "vcli_priv.h" #include "vrt.h" +#include "vmod_abi.h" /*-------------------------------------------------------------------- * Modules stuff @@ -56,7 +58,6 @@ struct vmod { void *hdl; const void *funcs; int funclen; - const void *idptr; }; static VTAILQ_HEAD(,vmod) vmods = VTAILQ_HEAD_INITIALIZER(vmods); @@ -67,6 +68,7 @@ VRT_Vmod_Init(void **hdl, void *ptr, int len, const char *nm, { struct vmod *v; void *x, *y, *z, *w; + char buf[256]; ASSERT_CLI(); @@ -86,10 +88,14 @@ VRT_Vmod_Init(void **hdl, void *ptr, int len, const char *nm, return (1); } - x = dlsym(v->hdl, "Vmod_Name"); - y = dlsym(v->hdl, "Vmod_Len"); - z = dlsym(v->hdl, "Vmod_Func"); - w = dlsym(v->hdl, "Vmod_Id"); + bprintf(buf, "Vmod_%s_Name", nm); + x = dlsym(v->hdl, buf); + bprintf(buf, "Vmod_%s_Len", nm); + y = dlsym(v->hdl, buf); + bprintf(buf, "Vmod_%s_Func", nm); + z = dlsym(v->hdl, buf); + bprintf(buf, "Vmod_%s_ABI", nm); + w = dlsym(v->hdl, buf); if (x == NULL || y == NULL || z == NULL || w == NULL) { VCLI_Out(cli, "Loading VMOD %s from %s:\n", nm, path); VCLI_Out(cli, "VMOD symbols not found\n"); @@ -112,6 +118,18 @@ VRT_Vmod_Init(void **hdl, void *ptr, int len, const char *nm, return (1); } + if (strcmp(w, VMOD_ABI_Version)) { + VCLI_Out(cli, "Loading VMOD %s from %s:\n", nm, path); + VCLI_Out(cli, "VMOD ABI (%s)", w); + VCLI_Out(cli, " incompatible with varnish ABI (%s)\n", + VMOD_ABI_Version); + (void)dlclose(v->hdl); + FREE_OBJ(v); + return (1); + } + + // XXX: Check w for ABI version compatibility + v->funclen = *(const int *)y; v->funcs = z; @@ -120,7 +138,6 @@ VRT_Vmod_Init(void **hdl, void *ptr, int len, const char *nm, VSC_C_main->vmods++; VTAILQ_INSERT_TAIL(&vmods, v, list); - v->idptr = w; } assert(len == v->funclen); diff --git a/bin/varnishd/flint.lnt b/bin/varnishd/flint.lnt index 0d810d2..f12f128 100644 --- a/bin/varnishd/flint.lnt +++ b/bin/varnishd/flint.lnt @@ -56,19 +56,19 @@ -efunc(838, VRT_purge_string) // Stuff in VMODs which is used through dl*(3) functions --esym(754, Vmod_Func*) --esym(765, Vmod_Func) --esym(552, Vmod_Func) --esym(765, Vmod_Len) --esym(714, Vmod_Len) --esym(765, Vmod_Name) --esym(714, Vmod_Name) --esym(765, Vmod_Proto) --esym(714, Vmod_Proto) --esym(765, Vmod_Spec) --esym(714, Vmod_Spec) --esym(765, Vmod_Varnish_ABI) --esym(714, Vmod_Varnish_ABI) +-esym(754, Vmod_*_Func::*) +-esym(765, Vmod_*_Func) +-esym(552, Vmod_*_Func) +-esym(765, Vmod_*_Len) +-esym(714, Vmod_*_Len) +-esym(765, Vmod_*_Name) +-esym(714, Vmod_*_Name) +-esym(765, Vmod_*_Proto) +-esym(714, Vmod_*_Proto) +-esym(765, Vmod_*_Spec) +-esym(714, Vmod_*_Spec) +-esym(765, Vmod_*_ABI) +-esym(714, Vmod_*_ABI) //-sem (pthread_mutex_lock, thread_lock) @@ -159,16 +159,6 @@ -e441 // for clause irregularity: loop variable '___' not found in 2nd for expression -// Vmod instantiation symbols are defined in all vmods - --esym(14, Vmod_Name) --esym(14, Vmod_Func) --esym(14, Vmod_Len) --esym(14, Vmod_Proto) --esym(14, Vmod_Spec) --esym(14, Vmod_Varnish_ABI) --esym(14, Vmod_Id) - // Review all below this line /////////////////////////////////////////////// -e732 // 183 Loss of sign (___) (___ to ___) diff --git a/lib/libvcl/vcc_parse.c b/lib/libvcl/vcc_parse.c index f656cbd..af97241 100644 --- a/lib/libvcl/vcc_parse.c +++ b/lib/libvcl/vcc_parse.c @@ -111,7 +111,6 @@ vcc_IfStmt(struct vcc *tl) ERRCHK(tl); L(tl, vcc_Compound(tl)); ERRCHK(tl); - } else if (vcc_IdIs(tl->t, "elseif") || vcc_IdIs(tl->t, "elsif") || vcc_IdIs(tl->t, "elif")) { diff --git a/lib/libvcl/vcc_vmod.c b/lib/libvcl/vcc_vmod.c index 874c899..23a3171 100644 --- a/lib/libvcl/vcc_vmod.c +++ b/lib/libvcl/vcc_vmod.c @@ -41,6 +41,7 @@ vcc_ParseImport(struct vcc *tl) { void *hdl; char fn[1024]; + char buf[256]; struct token *mod, *t1; const char *modname; const char *proto; @@ -106,8 +107,8 @@ vcc_ParseImport(struct vcc *tl) Fh(tl, 0, "static void *VGC_vmod_%.*s;\n", PF(mod)); Fi(tl, 0, "\tif (VRT_Vmod_Init(&VGC_vmod_%.*s,\n", PF(mod)); - Fi(tl, 0, "\t &Vmod_Func_%.*s,\n", PF(mod)); - Fi(tl, 0, "\t sizeof(Vmod_Func_%.*s),\n", PF(mod)); + Fi(tl, 0, "\t &Vmod_%.*s_Func,\n", PF(mod)); + Fi(tl, 0, "\t sizeof(Vmod_%.*s_Func),\n", PF(mod)); Fi(tl, 0, "\t \"%.*s\",\n", PF(mod)); Fi(tl, 0, "\t "); EncString(tl->fi, fn, NULL, 0); @@ -125,7 +126,8 @@ vcc_ParseImport(struct vcc *tl) return; } - modname = dlsym(hdl, "Vmod_Name"); + bprintf(buf, "Vmod_%.*s_Name", PF(mod)); + modname = dlsym(hdl, buf); if (modname == NULL) { VSB_printf(tl->sb, "Could not load module %.*s\n\t%s\n\t%s\n", PF(mod), fn, "Symbol Vmod_Name not found"); @@ -140,7 +142,8 @@ vcc_ParseImport(struct vcc *tl) return; } - abi = dlsym(hdl, "Vmod_Varnish_ABI"); + bprintf(buf, "Vmod_%.*s_ABI", PF(mod)); + abi = dlsym(hdl, buf); if (abi == NULL || strcmp(abi, VMOD_ABI_Version) != 0) { VSB_printf(tl->sb, "Could not load module %.*s\n\t%s\n", PF(mod), fn); @@ -150,14 +153,16 @@ vcc_ParseImport(struct vcc *tl) return; } - proto = dlsym(hdl, "Vmod_Proto"); + bprintf(buf, "Vmod_%.*s_Proto", PF(mod)); + proto = dlsym(hdl, buf); if (proto == NULL) { VSB_printf(tl->sb, "Could not load module %.*s\n\t%s\n\t%s\n", PF(mod), fn, "Symbol Vmod_Proto not found"); vcc_ErrWhere(tl, mod); return; } - spec = dlsym(hdl, "Vmod_Spec"); + bprintf(buf, "Vmod_%.*s_Spec", PF(mod)); + spec = dlsym(hdl, buf); if (spec == NULL) { VSB_printf(tl->sb, "Could not load module %.*s\n\t%s\n\t%s\n", PF(mod), fn, "Symbol Vmod_Spec not found"); diff --git a/lib/libvcl/vmodtool.py b/lib/libvcl/vmodtool.py index f20362f..0a8bb12 100755 --- a/lib/libvcl/vmodtool.py +++ b/lib/libvcl/vmodtool.py @@ -125,8 +125,8 @@ class vmod(object): fo.write("int " + self.init) fo.write( "(struct vmod_priv *, const struct VCL_conf *);\n") - fo.write("\n") - fo.write("extern const void * const Vmod_Id;\n") + #fo.write("\n") + #fo.write("extern const void * const Vmod_" + self.nam + "_Id;\n") def c_typedefs_(self): l = list() @@ -145,33 +145,36 @@ class vmod(object): fo.write(i + "\n") def c_vmod(self, fo): - fo.write('const char Vmod_Name[] = \"' + self.nam + '";\n') + fo.write('const char Vmod_' + self.nam + '_Name[] =') + fo.write(' \"' + self.nam + '";\n') fo.write("\n") cs = self.c_struct() - fo.write("const " + cs + ' Vmod_Func = ') + fo.write("const " + cs + ' Vmod_' + self.nam + '_Func = ') fo.write(self.c_initializer()) fo.write("\n") fo.write("\n") - fo.write("const int Vmod_Len = sizeof(Vmod_Func);\n") + fo.write("const int Vmod_" + self.nam + '_Len =') + fo.write(" sizeof(Vmod_" + self.nam + "_Func);\n") fo.write("\n") - - fo.write("const char Vmod_Proto[] =\n") + fo.write("const char Vmod_" + self.nam + "_Proto[] =\n") for t in self.c_typedefs_(): fo.write('\t"' + t + '\\n"\n') fo.write('\t"\\n"\n') - for i in (cs + " Vmod_Func_" + self.nam + ';').split("\n"): + for i in (cs + " Vmod_" + self.nam + '_Func;').split("\n"): fo.write('\n\t"' + i + '\\n"') fo.write(";\n\n") fo.write(self.c_strspec()) fo.write("\n") - fo.write('const char Vmod_Varnish_ABI[] = VMOD_ABI_Version;\n') - fo.write("\n") - fo.write('const void * const Vmod_Id = &Vmod_Id;\n') + fo.write('const char Vmod_' + self.nam + '_ABI[] =') + fo.write(' VMOD_ABI_Version;\n') + #fo.write("\n") + #fo.write('const void * const Vmod_' + self.nam + '_Id =') + #fo.write(' &Vmod_' + self.nam + '_Id;\n') def c_initializer(self): s = '{\n' @@ -190,7 +193,7 @@ class vmod(object): return s def c_struct(self): - s = 'struct Vmod_Func_' + self.nam + ' {\n' + s = 'struct Vmod_' + self.nam + '_Func {\n' for o in self.objs: s += o.c_struct(self.nam) @@ -205,7 +208,7 @@ class vmod(object): return s def c_strspec(self): - s = "const char * const Vmod_Spec[] = {\n" + s = "const char * const Vmod_" + self.nam + "_Spec[] = {\n" for o in self.objs: s += o.c_strspec(self.nam) @@ -216,7 +219,7 @@ class vmod(object): s += "\n\t/* Init/Fini */\n" if self.init != None: - s += '\t"INIT\\0Vmod_Func_' + self.nam + '._init",\n' + s += '\t"INIT\\0Vmod_' + self.nam + '_Func._init",\n' s += "\t0\n" s += "};\n" @@ -280,7 +283,7 @@ class func(object): def c_strspec(self, modnam): s = modnam + "." + self.nam s += "\\0" - s += "Vmod_Func_" + modnam + "." + self.cnam + "\\0" + s += "Vmod_" + modnam + "_Func." + self.cnam + "\\0" s += self.retval + "\\0" for a in self.al: s += a.c_strspec() From phk at varnish-cache.org Thu Mar 7 09:19:52 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Thu, 07 Mar 2013 10:19:52 +0100 Subject: [master] 16c8251 Pass the vmod.object::init function the VCL name of the object being created. Message-ID: commit 16c8251dd9b8f6ca4645a4a35608428ce61e4a69 Author: Poul-Henning Kamp Date: Thu Mar 7 08:50:21 2013 +0000 Pass the vmod.object::init function the VCL name of the object being created. Split the demo-rr director into its own file diff --git a/lib/libvcl/vcc_action.c b/lib/libvcl/vcc_action.c index 50e912d..5fdae74 100644 --- a/lib/libvcl/vcc_action.c +++ b/lib/libvcl/vcc_action.c @@ -220,7 +220,7 @@ parse_new(struct vcc *tl) vcc_NextToken(tl); - bprintf(buf1, ", &%s", sy1->name); + bprintf(buf1, ", &%s, \"%s\"", sy1->name, sy1->name); vcc_Eval_Func(tl, s_init, buf1, "ASDF", s_init + strlen(s_init) + 1); Ff(tl, 0, "\t%s((struct req*)0, &%s);\n", s_fini, sy1->name); ExpectErr(tl, ';'); diff --git a/lib/libvcl/vmodtool.py b/lib/libvcl/vmodtool.py index 0a8bb12..ddec683 100755 --- a/lib/libvcl/vmodtool.py +++ b/lib/libvcl/vmodtool.py @@ -300,7 +300,7 @@ class obj(object): def set_modnam(self, modnam): self.st = "struct vmod_" + modnam + "_" + self.nam - self.init.set_pfx(", " + self.st + " **") + self.init.set_pfx(", " + self.st + " **, const char *") self.fini.set_pfx(", " + self.st + " **") for m in self.methods: m.set_pfx(", " + self.st + " *") diff --git a/lib/libvmod_debug/Makefile.am b/lib/libvmod_debug/Makefile.am index 7e2c849..a4f9fb7 100644 --- a/lib/libvmod_debug/Makefile.am +++ b/lib/libvmod_debug/Makefile.am @@ -15,7 +15,8 @@ libvmod_debug_la_LDFLAGS = $(AM_LDFLAGS) -module -export-dynamic -avoid-version libvmod_debug_la_SOURCES = \ vmod_debug.c \ - vmod_debug_obj.c + vmod_debug_obj.c \ + vmod_debug_rr.c nodist_libvmod_debug_la_SOURCES = \ vcc_if.c \ diff --git a/lib/libvmod_debug/vmod_debug_obj.c b/lib/libvmod_debug/vmod_debug_obj.c index 3ec94e1..2b628fa 100644 --- a/lib/libvmod_debug/vmod_debug_obj.c +++ b/lib/libvmod_debug/vmod_debug_obj.c @@ -42,11 +42,13 @@ struct vmod_debug_obj { }; VCL_VOID -vmod_obj__init(struct req *req, struct vmod_debug_obj **op, VCL_STRING s) +vmod_obj__init(struct req *req, struct vmod_debug_obj **op, + const char *vcl_name, VCL_STRING s) { struct vmod_debug_obj *o; (void)req; + (void)vcl_name; (void)s; AN(op); AZ(*op); @@ -86,86 +88,3 @@ vmod_obj_date(struct req *req, struct vmod_debug_obj *o) assert(o->foobar == 42); return (21.4); } - -/*----------------------------------------------------------------------*/ - -struct vmod_debug_rr_entry { - unsigned magic; -#define VMOD_DEBUG_RR_ENTRY_MAGIC 0xa80970cf - VTAILQ_ENTRY(vmod_debug_rr_entry) list; - VCL_BACKEND be; -}; - -struct vmod_debug_rr { - unsigned magic; -#define VMOD_DEBUG_RR_MAGIC 0x99f4b726 - VTAILQ_HEAD(, vmod_debug_rr_entry) listhead; - pthread_mutex_t mtx; -}; - -VCL_VOID -vmod_rr__init(struct req *req, struct vmod_debug_rr **rrp) -{ - struct vmod_debug_rr *rr; - - (void)req; - - AN(rrp); - AZ(*rrp); - ALLOC_OBJ(rr, VMOD_DEBUG_RR_MAGIC); - AN(rr); - *rrp = rr; - AZ(pthread_mutex_init(&rr->mtx, NULL)); - VTAILQ_INIT(&rr->listhead); -} - -VCL_VOID -vmod_rr__fini(struct req *req, struct vmod_debug_rr **rrp) -{ - struct vmod_debug_rr *rr; - struct vmod_debug_rr_entry *ep; - - (void)req; - - rr = *rrp; - *rrp = NULL; - CHECK_OBJ_NOTNULL(rr, VMOD_DEBUG_RR_MAGIC); - - AZ(pthread_mutex_destroy(&rr->mtx)); - while (!VTAILQ_EMPTY(&rr->listhead)) { - ep = VTAILQ_FIRST(&rr->listhead); - VTAILQ_REMOVE(&rr->listhead, ep, list); - FREE_OBJ(ep); - } - FREE_OBJ(*rrp); -} - -VCL_VOID -vmod_rr_add_backend(struct req *req, struct vmod_debug_rr * rr, VCL_BACKEND be) -{ - struct vmod_debug_rr_entry *ep; - (void)req; - - ALLOC_OBJ(ep, VMOD_DEBUG_RR_ENTRY_MAGIC); - AN(ep); - ep->be = be; - AZ(pthread_mutex_lock(&rr->mtx)); - VTAILQ_INSERT_TAIL(&rr->listhead, ep, list); - AZ(pthread_mutex_unlock(&rr->mtx)); -} - -VCL_BACKEND -vmod_rr_select(struct req *req, struct vmod_debug_rr *rr) -{ - struct vmod_debug_rr_entry *ep; - - (void)req; - - CHECK_OBJ_NOTNULL(rr, VMOD_DEBUG_RR_MAGIC); - AZ(pthread_mutex_lock(&rr->mtx)); - ep = VTAILQ_FIRST(&rr->listhead); - VTAILQ_REMOVE(&rr->listhead, ep, list); - VTAILQ_INSERT_TAIL(&rr->listhead, ep, list); - AZ(pthread_mutex_unlock(&rr->mtx)); - return (ep->be); -} diff --git a/lib/libvmod_debug/vmod_debug_rr.c b/lib/libvmod_debug/vmod_debug_rr.c new file mode 100644 index 0000000..186e2a1 --- /dev/null +++ b/lib/libvmod_debug/vmod_debug_rr.c @@ -0,0 +1,118 @@ +/*- + * Copyright (c) 2013 Varnish Software AS + * All rights reserved. + * + * Author: Poul-Henning Kamp + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "config.h" + +#include + +#include "cache/cache.h" + +#include "vrt.h" +#include "vcc_if.h" + +struct vmod_debug_rr_entry { + unsigned magic; +#define VMOD_DEBUG_RR_ENTRY_MAGIC 0xa80970cf + VTAILQ_ENTRY(vmod_debug_rr_entry) list; + VCL_BACKEND be; +}; + +struct vmod_debug_rr { + unsigned magic; +#define VMOD_DEBUG_RR_MAGIC 0x99f4b726 + VTAILQ_HEAD(, vmod_debug_rr_entry) listhead; + pthread_mutex_t mtx; +}; + +VCL_VOID +vmod_rr__init(struct req *req, struct vmod_debug_rr **rrp, const char *vcl_name) +{ + struct vmod_debug_rr *rr; + + (void)req; + (void)vcl_name; + + AN(rrp); + AZ(*rrp); + ALLOC_OBJ(rr, VMOD_DEBUG_RR_MAGIC); + AN(rr); + *rrp = rr; + AZ(pthread_mutex_init(&rr->mtx, NULL)); + VTAILQ_INIT(&rr->listhead); +} + +VCL_VOID +vmod_rr__fini(struct req *req, struct vmod_debug_rr **rrp) +{ + struct vmod_debug_rr *rr; + struct vmod_debug_rr_entry *ep; + + (void)req; + + rr = *rrp; + *rrp = NULL; + CHECK_OBJ_NOTNULL(rr, VMOD_DEBUG_RR_MAGIC); + + AZ(pthread_mutex_destroy(&rr->mtx)); + while (!VTAILQ_EMPTY(&rr->listhead)) { + ep = VTAILQ_FIRST(&rr->listhead); + VTAILQ_REMOVE(&rr->listhead, ep, list); + FREE_OBJ(ep); + } + FREE_OBJ(*rrp); +} + +VCL_VOID +vmod_rr_add_backend(struct req *req, struct vmod_debug_rr * rr, VCL_BACKEND be) +{ + struct vmod_debug_rr_entry *ep; + (void)req; + + ALLOC_OBJ(ep, VMOD_DEBUG_RR_ENTRY_MAGIC); + AN(ep); + ep->be = be; + AZ(pthread_mutex_lock(&rr->mtx)); + VTAILQ_INSERT_TAIL(&rr->listhead, ep, list); + AZ(pthread_mutex_unlock(&rr->mtx)); +} + +VCL_BACKEND +vmod_rr_select(struct req *req, struct vmod_debug_rr *rr) +{ + struct vmod_debug_rr_entry *ep; + + (void)req; + + CHECK_OBJ_NOTNULL(rr, VMOD_DEBUG_RR_MAGIC); + AZ(pthread_mutex_lock(&rr->mtx)); + ep = VTAILQ_FIRST(&rr->listhead); + VTAILQ_REMOVE(&rr->listhead, ep, list); + VTAILQ_INSERT_TAIL(&rr->listhead, ep, list); + AZ(pthread_mutex_unlock(&rr->mtx)); + return (ep->be); +} From phk at varnish-cache.org Thu Mar 7 09:19:52 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Thu, 07 Mar 2013 10:19:52 +0100 Subject: [master] 7be8dd9 Turn the vmod_debug demo-rr-director into a real director, and add a test-case where it is used in stackable fashion. Message-ID: commit 7be8dd9fc8c8e5199715e33aee9137cd6c7acd3e Author: Poul-Henning Kamp Date: Thu Mar 7 09:18:44 2013 +0000 Turn the vmod_debug demo-rr-director into a real director, and add a test-case where it is used in stackable fashion. I should have done it this way from the very start, rather than muck about with director configurations in VCC... diff --git a/bin/varnishtest/tests/m00009.vtc b/bin/varnishtest/tests/m00009.vtc index b81f07e..c56f2ef 100644 --- a/bin/varnishtest/tests/m00009.vtc +++ b/bin/varnishtest/tests/m00009.vtc @@ -35,7 +35,7 @@ varnish v1 -vcl+backend { } sub vcl_recv { - set req.backend = rr.select(); + set req.backend = rr.backend(); } } -start diff --git a/bin/varnishtest/tests/m00010.vtc b/bin/varnishtest/tests/m00010.vtc new file mode 100644 index 0000000..332d16e --- /dev/null +++ b/bin/varnishtest/tests/m00010.vtc @@ -0,0 +1,75 @@ +varnishtest "Test vmod.debug round robin director" + + +server s1 { + rxreq + txresp -body "1" +} -start + +server s2 { + rxreq + txresp -body "22" +} -start + + +server s3 { + rxreq + txresp -body "333" +} -start + +server s4 { + rxreq + txresp -body "4444" +} -start + + +varnish v1 -vcl+backend { + + import debug from "${topbuild}/lib/libvmod_debug/.libs/libvmod_debug.so" ; + sub vcl_init { + new rr1 = debug.rr(); + rr1.add_backend(s1); + rr1.add_backend(s3); + + new rr2 = debug.rr(); + rr2.add_backend(s2); + rr2.add_backend(s4); + + new rr3 = debug.rr(); + rr3.add_backend(rr1.backend()); + rr3.add_backend(rr2.backend()); + } + + sub vcl_recv { + set req.backend = rr3.backend(); + } +} -start + +client c1 { + timeout 3 + txreq -url "/foo1" + rxresp + expect resp.bodylen == 1 + txreq -url "/foo2" + rxresp + expect resp.bodylen == 2 + txreq -url "/foo3" + rxresp + expect resp.bodylen == 3 + txreq -url "/foo4" + rxresp + expect resp.bodylen == 4 +} -run + +server s1 -start +server s2 -start + +client c2 { + timeout 3 + txreq -url "/foo11" + rxresp + expect resp.bodylen == 1 + txreq -url "/foo22" + rxresp + expect resp.bodylen == 2 +} -run diff --git a/lib/libvmod_debug/vmod.vcc b/lib/libvmod_debug/vmod.vcc index 97d5f5e..8451c6c 100644 --- a/lib/libvmod_debug/vmod.vcc +++ b/lib/libvmod_debug/vmod.vcc @@ -38,5 +38,5 @@ Object obj(STRING) { Object rr() { Method VOID .add_backend(BACKEND) - Method BACKEND .select() + Method BACKEND .backend() } diff --git a/lib/libvmod_debug/vmod_debug_rr.c b/lib/libvmod_debug/vmod_debug_rr.c index 186e2a1..a326051 100644 --- a/lib/libvmod_debug/vmod_debug_rr.c +++ b/lib/libvmod_debug/vmod_debug_rr.c @@ -31,6 +31,7 @@ #include #include "cache/cache.h" +#include "cache/cache_backend.h" #include "vrt.h" #include "vcc_if.h" @@ -46,16 +47,58 @@ struct vmod_debug_rr { unsigned magic; #define VMOD_DEBUG_RR_MAGIC 0x99f4b726 VTAILQ_HEAD(, vmod_debug_rr_entry) listhead; + int nbe; pthread_mutex_t mtx; + struct director *dir; }; +static unsigned +vmod_rr_healthy(const struct director *dir, const struct req *req) +{ + struct vmod_debug_rr_entry *ep; + struct vmod_debug_rr *rr; + unsigned retval = 0; + + CAST_OBJ_NOTNULL(rr, dir->priv, VMOD_DEBUG_RR_MAGIC); + AZ(pthread_mutex_lock(&rr->mtx)); + VTAILQ_FOREACH(ep, &rr->listhead, list) { + if (ep->be->healthy(ep->be, req)) { + retval = 1; + break; + } + } + AZ(pthread_mutex_unlock(&rr->mtx)); + return (retval); +} + +static struct vbc * +vmod_rr_getfd(const struct director *dir, struct req *req) +{ + struct vmod_debug_rr_entry *ep = NULL; + struct vmod_debug_rr *rr; + int i; + + CAST_OBJ_NOTNULL(rr, dir->priv, VMOD_DEBUG_RR_MAGIC); + AZ(pthread_mutex_lock(&rr->mtx)); + for (i = 0; i < rr->nbe; i++) { + ep = VTAILQ_FIRST(&rr->listhead); + VTAILQ_REMOVE(&rr->listhead, ep, list); + VTAILQ_INSERT_TAIL(&rr->listhead, ep, list); + if (ep->be->healthy(ep->be, req)) + break; + } + AZ(pthread_mutex_unlock(&rr->mtx)); + if (i == rr->nbe || ep == NULL) + return (NULL); + return (ep->be->getfd(ep->be, req)); +} + VCL_VOID vmod_rr__init(struct req *req, struct vmod_debug_rr **rrp, const char *vcl_name) { struct vmod_debug_rr *rr; (void)req; - (void)vcl_name; AN(rrp); AZ(*rrp); @@ -64,6 +107,12 @@ vmod_rr__init(struct req *req, struct vmod_debug_rr **rrp, const char *vcl_name) *rrp = rr; AZ(pthread_mutex_init(&rr->mtx, NULL)); VTAILQ_INIT(&rr->listhead); + ALLOC_OBJ(rr->dir, DIRECTOR_MAGIC); + AN(rr->dir); + REPLACE(rr->dir->vcl_name, vcl_name); + rr->dir->priv = rr; + rr->dir->healthy = vmod_rr_healthy; + rr->dir->getfd = vmod_rr_getfd; } VCL_VOID @@ -84,7 +133,9 @@ vmod_rr__fini(struct req *req, struct vmod_debug_rr **rrp) VTAILQ_REMOVE(&rr->listhead, ep, list); FREE_OBJ(ep); } - FREE_OBJ(*rrp); + REPLACE(rr->dir->vcl_name, NULL); + FREE_OBJ(rr->dir); + FREE_OBJ(rr); } VCL_VOID @@ -98,21 +149,13 @@ vmod_rr_add_backend(struct req *req, struct vmod_debug_rr * rr, VCL_BACKEND be) ep->be = be; AZ(pthread_mutex_lock(&rr->mtx)); VTAILQ_INSERT_TAIL(&rr->listhead, ep, list); + rr->nbe++; AZ(pthread_mutex_unlock(&rr->mtx)); } -VCL_BACKEND -vmod_rr_select(struct req *req, struct vmod_debug_rr *rr) +VCL_BACKEND __match_proto__() +vmod_rr_backend(struct req *req, struct vmod_debug_rr *rr) { - struct vmod_debug_rr_entry *ep; - (void)req; - - CHECK_OBJ_NOTNULL(rr, VMOD_DEBUG_RR_MAGIC); - AZ(pthread_mutex_lock(&rr->mtx)); - ep = VTAILQ_FIRST(&rr->listhead); - VTAILQ_REMOVE(&rr->listhead, ep, list); - VTAILQ_INSERT_TAIL(&rr->listhead, ep, list); - AZ(pthread_mutex_unlock(&rr->mtx)); - return (ep->be); + return (rr->dir); } From perbu at varnish-cache.org Thu Mar 7 09:36:33 2013 From: perbu at varnish-cache.org (Per Buer) Date: Thu, 07 Mar 2013 10:36:33 +0100 Subject: [master] 93c5e39 header style consistency Message-ID: commit 93c5e395e3c95cd7aee0fe679ef2b0913e978d35 Author: Per Buer Date: Thu Mar 7 10:34:52 2013 +0100 header style consistency diff --git a/doc/sphinx/include/vcl-syntax.rst b/doc/sphinx/include/vcl-syntax.rst deleted file mode 100644 index 441aa06..0000000 --- a/doc/sphinx/include/vcl-syntax.rst +++ /dev/null @@ -1,65 +0,0 @@ -VCL SYNTAX -========== - -The VCL syntax is very simple, and deliberately similar to C and Perl. -Blocks are delimited by curly braces, statements end with semicolons, -and comments may be written as in C, C++ or Perl according to your own -preferences. - -In addition to the C-like assignment (=), comparison (==, !=) and -boolean (!, && and \|\|) operators, VCL supports both regular -expression and ACL matching using the ~ and the !~ operators. - -Basic strings are enclosed in " ... ", and may not contain newlines. - -Long strings are enclosed in {" ... "}. They may contain any -character including ", newline and other control characters except -for the NUL (0x00) character. - -Unlike C and Perl, the backslash (\) character has no special meaning -in strings in VCL, so it can be freely used in regular expressions -without doubling. - -Strings are concatenated using the '+' operator. - -Assignments are introduced with the *set* keyword. There are no -user-defined variables; values can only be assigned to variables -attached to backend, request or document objects. Most of these are -typed, and the values assigned to them must have a compatible unit -suffix. - -You can use the *set* keyword to arbitrary HTTP headers. You can -remove headers with the *remove* or *unset* keywords, which are -synonym. - -You can use the *rollback* keyword to revert any changes to req at -any time. - -The *synthetic* keyword is used to produce a synthetic response -body in vcl_error. It takes a single string as argument. - -You can force a crash of the client process with the *panic* keyword. -*panic* takes a string as argument. - -The ``return(action)`` keyword terminates the subroutine. *action* can be, -depending on context one of - -* deliver -* error -* fetch -* hash -* hit_for_pass -* lookup -* ok -* pass -* pipe -* restart - -Please see the list of subroutines to see what return actions are -available where. - -VCL has if tests, but no loops. - -The contents of another VCL file may be inserted at any point in the -code by using the *include* keyword followed by the name of the other -file as a quoted string. diff --git a/doc/sphinx/index.rst b/doc/sphinx/index.rst index 1cc29c6..b3f734b 100644 --- a/doc/sphinx/index.rst +++ b/doc/sphinx/index.rst @@ -1,6 +1,21 @@ .. Varnish documentation master file, created by sphinx-quickstart on Tue Apr 20 13:02:15 2010. +.. We use the following header indicators + +.. For titles: + +.. H1 +.. %%%%% +.. Title +.. %%%%% + +.. H2 - H5 +.. ====================== +.. ---------------------- +.. ~~~~~~~~~~~~~~~~~~~~~~ +.. ...................... + Welcome to Varnish's documentation! =================================== diff --git a/doc/sphinx/installation/index.rst b/doc/sphinx/installation/index.rst index 15b61eb..b1e0a23 100644 --- a/doc/sphinx/installation/index.rst +++ b/doc/sphinx/installation/index.rst @@ -15,7 +15,6 @@ move traffic. install.rst help.rst bugs.rst - upgrade.rst platformnotes.rst diff --git a/doc/sphinx/installation/install.rst b/doc/sphinx/installation/install.rst index 4a836ff..cf7501f 100644 --- a/doc/sphinx/installation/install.rst +++ b/doc/sphinx/installation/install.rst @@ -11,14 +11,14 @@ are most comfortable with. Source or packages? -~~~~~~~~~~~~~~~~~~~ +------------------- Installing Varnish on most relevant operating systems can usually be done with with the systems package manager, typical examples being: FreeBSD -~~~~~~~ +------- From source: ``cd /usr/ports/varnish && make install clean`` @@ -26,7 +26,7 @@ Binary package: ``pkg_add -r varnish`` CentOS/RedHat -~~~~~~~~~~~~~ +------------- We try to keep the latest version available as prebuilt RPMs (el5) on `repo.varnish-cache.org `. See the @@ -42,7 +42,7 @@ the latest version there is Varnish 2.0.6. EPEL6 should have Varnish 2.1 available once it releases. Debian/Ubuntu -~~~~~~~~~~~~~ +------------- Varnish is distributed with both Debian and Ubuntu. In order to get Varnish up and running type `sudo apt-get install varnish`. Please @@ -53,7 +53,7 @@ instructions for `Debian `. Other systems -~~~~~~~~~~~~~ +------------- You are probably best of compiling your own code. See `Compiling Varnish from source`_. @@ -82,7 +82,7 @@ Please note that a git checkout will need some more build-dependencies than listed below, in particular the Python Docutils and Sphinx. Build dependencies on Debian / Ubuntu -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +-------------------------------------- In order to build Varnish from source you need a number of packages installed. On a Debian or Ubuntu system these are: @@ -97,7 +97,7 @@ installed. On a Debian or Ubuntu system these are: * pkg-config Build dependencies on Red Hat / CentOS -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +-------------------------------------- To build Varnish on a Red Hat or CentOS system you need the following packages installed: @@ -111,7 +111,7 @@ packages installed: * pkgconfig Configuring and compiling -~~~~~~~~~~~~~~~~~~~~~~~~~ +------------------------- Next, configuration: The configuration will need the dependencies above satisfied. Once that is taken care of:: @@ -137,7 +137,7 @@ fails, something is horribly wrong, and you will get nowhere without figuring out what. Installing -~~~~~~~~~~ +---------- And finally, the true test of a brave heart:: diff --git a/doc/sphinx/installation/prerequisites.rst b/doc/sphinx/installation/prerequisites.rst index f42c37a..3508c1e 100644 --- a/doc/sphinx/installation/prerequisites.rst +++ b/doc/sphinx/installation/prerequisites.rst @@ -7,7 +7,7 @@ In order for you to install Varnish you must have the following: * A fairly modern and 64 bit version of either - Linux - FreeBSD - - Solaris + - Solaris (x86 only) * root access to said system @@ -19,4 +19,5 @@ time, said to work on: * OS X * NetBSD * OpenBSD + * Windows with Cygwin diff --git a/doc/sphinx/installation/upgrade.rst b/doc/sphinx/installation/upgrade.rst deleted file mode 100644 index 93446ea..0000000 --- a/doc/sphinx/installation/upgrade.rst +++ /dev/null @@ -1,172 +0,0 @@ -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -Upgrading from Varnish 2.1 to 3.0 -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -This is a compilation of items you need to pay attention to when upgrading from Varnish 2.1 to 3.0 - -Changes to VCL -============== - -In most cases you need to update your VCL since there has been some changes to the syntax. - -string concatenation operator -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -String concatenation did not have an operator previously, but this has now been changed to ``+``. - -no more %-escapes in strings -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -To simplify strings, the %-encoding has been removed. If you need non-printable characters, you need to use inline C. - -``log`` moved to the std vmod -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -``log`` has moved to the std vmod:: - - log "log something"; - -becomes:: - - import std; - std.log("log something"); - -You only need to import std once. - -purges are now called bans -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -``purge()`` and ``purge_url()`` are now respectively ``ban()`` and ``ban_url()``, so you should replace all occurences:: - - purge("req.url = " req.url); - -becomes:: - - ban("req.url = " + req.url); - -``purge`` does not take any arguments anymore, but can be used in vcl_hit or vcl_miss to purge the item from the cache, where you would reduce ttl to 0 in Varnish 2.1:: - - sub vcl_hit { - if (req.request == "PURGE") { - set obj.ttl = 0s; - error 200 "Purged."; - } - } - -becomes:: - - sub vcl_hit { - if (req.request == "PURGE") { - purge; - error 200 "Purged."; - } - } - -``beresp.cacheable`` and ``obj.cacheable`` are gone -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -``beresp.cacheable`` is gone, and can be replaced with ``beresp.ttl > 0s``. Similarly ``obj.cacheable`` can be replaced with ``obj.ttl > 0s``. - -returns are now done with the ``return()`` function -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -``pass``, ``pipe``, ``lookup``, ``deliver``, ``fetch``, ``hash``, ``pipe`` and ``restart`` are no longer keywords, but arguments to ``return()``, so:: - - sub vcl_pass { - pass; - } - -becomes:: - - sub vcl_pass { - return(pass); - } - - -``req.hash`` is replaced with ``hash_data()`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -You no longer append to the hash with ``+=``, so:: - - set req.hash += req.url; - -becomes:: - - hash_data(req.url); - -``esi`` is replaced with ``beresp.do_esi`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -You no longer enable ESI with ``esi``, so:: - - esi; - -in ``vcl_fetch`` becomes:: - - set beresp.do_esi = true; - -``pass`` in ``vcl_fetch`` renamed to ``hit_for_pass`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The difference in behaviour of ``pass`` in ``vcl_recv`` and -``vcl_fetch`` confused people, so to make it clearer that they are -different, you must now do ``return(hit_for_pass)`` when doing a pass -in ``vcl_fetch``. - -Changes to runtime parameters -============================= - -Deleted parameters -~~~~~~~~~~~~~~~~~~ - -``cache_vbe_conns`` and ``err_ttl`` has been removed. - -New parameters -~~~~~~~~~~~~~~ - -The following parameters have been added, see man varnishd for reference: - -* ``default_keep`` -* ``expiry_sleep`` -* ``fetch_maxchunksize`` -* ``gzip_level`` -* ``gzip_memlevel`` -* ``gzip_stack_buffer`` -* ``gzip_tmp_space`` -* ``gzip_window`` -* ``http_gzip_support`` -* ``http_req_hdr_len`` -* ``http_req_size`` -* ``http_resp_hdr_len`` -* ``http_resp_size`` -* ``shortlived`` -* ``thread_pool_workspace`` -* ``vcc_err_unref`` -* ``vcl_dir`` -* ``vmod_dir`` - -Changed default values -~~~~~~~~~~~~~~~~~~~~~~ - -The following parameters have new defaults: - -* ``ban_lurker_sleep`` changed from 0 to 0.01 seconds, enabling the ban lurker by default. -* ``connect_timeout`` changed from 0.4 to 0.7 seconds. -* ``log_hashstring`` changed from off to on. -* ``send_timeout`` changed from 600 to 60 seconds. -* ``thread_pool_add_delay`` changed from 20 to 2 ms. - -Changed parameter names -~~~~~~~~~~~~~~~~~~~~~~~ - -The following parameters have new names: - -* ``http_headers`` has been renamed to ``http_max_hdr``. -* ``max_esi_includes`` has been renamed to ``max_esi_depth``. -* ``overflow_max`` has been renamed to ``queue_max``. -* ``purge_dups`` has been renamed to ``ban_dups``. - -Changes to behaviour -==================== - -Varnish will return an error when headers are too large instead of just ignoring them. If the limits are too low, Varnish will return HTTP 413. You can change the limits by increasing http_req_hdr_len and http_req_size. - -thread_pool_max is now per thread pool, while it was a total across all pools in 2.1. If you had this set in 2.1, you should adjust it for 3.0. From perbu at varnish-cache.org Thu Mar 7 09:36:33 2013 From: perbu at varnish-cache.org (Per Buer) Date: Thu, 07 Mar 2013 10:36:33 +0100 Subject: [master] da7d47e various cleanups Message-ID: commit da7d47efa57e3f81bdd5c823ecae0b79a6fc002e Author: Per Buer Date: Thu Mar 7 10:36:53 2013 +0100 various cleanups diff --git a/doc/sphinx/reference/vcl.rst b/doc/sphinx/reference/vcl.rst index 731da16..ca9c4c0 100644 --- a/doc/sphinx/reference/vcl.rst +++ b/doc/sphinx/reference/vcl.rst @@ -27,7 +27,7 @@ When a new configuration is loaded, the varnishd management process translates the VCL code to C and compiles it to a shared object which is then dynamically linked into the server process. -.. include:: ../include/vcl-syntax.rst +.. .. include:: ../include/vcl-syntax.rst .. include:: ../include/vcl-backends.rst diff --git a/doc/sphinx/users-guide/index.rst b/doc/sphinx/users-guide/index.rst index bfedbae..a28b08f 100644 --- a/doc/sphinx/users-guide/index.rst +++ b/doc/sphinx/users-guide/index.rst @@ -11,7 +11,7 @@ The guide is split into short chapters, each chapter explaining a separate topic. .. toctree:: - :maxdepth: 3 + :maxdepth: 2 configuration vcl diff --git a/doc/sphinx/users-guide/vcl-backends.rst b/doc/sphinx/users-guide/vcl-backends.rst index 4f721aa..586b221 100644 --- a/doc/sphinx/users-guide/vcl-backends.rst +++ b/doc/sphinx/users-guide/vcl-backends.rst @@ -7,10 +7,7 @@ Varnish has a concept of "backend" or "origin" servers. A backend server is the server providing the content Varnish will accelerate. Our first task is to tell Varnish where it can find its content. Start -your favorite text editor and open the varnish default configuration -file. If you installed from source this is -/usr/local/etc/varnish/default.vcl, if you installed from a package it -is probably /etc/varnish/default.vcl. +your favorite text editor and open the relevant VCL file. Somewhere in the top there will be a section that looks a bit like this.:: diff --git a/doc/sphinx/users-guide/vcl-example1-manipulating-headers.rst b/doc/sphinx/users-guide/vcl-example1-manipulating-headers.rst deleted file mode 100644 index 35dcb1e..0000000 --- a/doc/sphinx/users-guide/vcl-example1-manipulating-headers.rst +++ /dev/null @@ -1,21 +0,0 @@ - - - -Manipulating request headers in VCL -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Lets say we want to remove the cookie for all objects in the /images -directory of our web server:: - - sub vcl_recv { - if (req.url ~ "^/images") { - unset req.http.cookie; - } - } - -Now, when the request is handled to the backend server there will be -no cookie header. The interesting line is the one with the -if-statement. It matches the URL, taken from the request object, and -matches it against the regular expression. Note the match operator. If -it matches the Cookie: header of the request is unset (deleted). - diff --git a/doc/sphinx/users-guide/vcl-example2-manipulating-responses.rst b/doc/sphinx/users-guide/vcl-example2-manipulating-responses.rst deleted file mode 100644 index 7362789..0000000 --- a/doc/sphinx/users-guide/vcl-example2-manipulating-responses.rst +++ /dev/null @@ -1,19 +0,0 @@ - - -Altering the backend response -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Here we override the TTL of a object comming from the backend if it -matches certain criteria:: - - sub vcl_fetch { - if (req.url ~ "\.(png|gif|jpg)$") { - unset beresp.http.set-cookie; - set beresp.ttl = 1h; - } - } - -.. XXX ref hit-for-pass - -We also remove any Set-Cookie headers in order to avoid a hit-for-pass -object to be created. diff --git a/doc/sphinx/users-guide/vcl-example3-acls.rst b/doc/sphinx/users-guide/vcl-example3-acls.rst deleted file mode 100644 index 3d0226a..0000000 --- a/doc/sphinx/users-guide/vcl-example3-acls.rst +++ /dev/null @@ -1,34 +0,0 @@ - -ACLs -~~~~ - -You create a named access control list with the *acl* keyword. You can match -the IP address of the client against an ACL with the match operator.:: - - # Who is allowed to purge.... - acl local { - "localhost"; - "192.168.1.0"/24; /* and everyone on the local network */ - ! "192.168.1.23"; /* except for the dialin router */ - } - - sub vcl_recv { - if (req.method == "PURGE") { - if (client.ip ~ local) { - return(lookup); - } - } - } - - sub vcl_hit { - if (req.method == "PURGE") { - set obj.ttl = 0s; - error 200 "Purged."; - } - } - - sub vcl_miss { - if (req.method == "PURGE") { - error 404 "Not in cache."; - } - } diff --git a/doc/sphinx/users-guide/vcl-examples.rst b/doc/sphinx/users-guide/vcl-examples.rst index fdd892a..931ec27 100644 --- a/doc/sphinx/users-guide/vcl-examples.rst +++ b/doc/sphinx/users-guide/vcl-examples.rst @@ -7,8 +7,9 @@ capabilites of the VCL language. .. toctree:: - vcl-example1-manipulating-headers - vcl-example2-manipulating-responses - vcl-example3-acls + vcl-example-manipulating-headers + vcl-example-manipulating-responses + vcl-example-acls + vcl-example-websockets diff --git a/doc/sphinx/users-guide/vcl.rst b/doc/sphinx/users-guide/vcl.rst index 031cf36..0133dee 100644 --- a/doc/sphinx/users-guide/vcl.rst +++ b/doc/sphinx/users-guide/vcl.rst @@ -27,7 +27,7 @@ code commented out in default.vcl that ships with Varnish Cache. .. _users-guide-vcl_fetch_actions: .. toctree:: - :maxdepth: 2 + :maxdepth: 1 vcl-syntax vcl-built-in-subs diff --git a/doc/sphinx/users-guide/websockets.rst b/doc/sphinx/users-guide/websockets.rst index a74353e..7217b88 100644 --- a/doc/sphinx/users-guide/websockets.rst +++ b/doc/sphinx/users-guide/websockets.rst @@ -1,6 +1,6 @@ -Using Websockets ----------------- +Implementing websocket support +------------------------------ Websockets is a technology for creating a bidirectional stream-based channel over HTTP. From perbu at varnish-cache.org Thu Mar 7 09:36:33 2013 From: perbu at varnish-cache.org (Per Buer) Date: Thu, 07 Mar 2013 10:36:33 +0100 Subject: [master] 7f501a1 Examples are back Message-ID: commit 7f501a1c5d39f99655a3138731bb70358fe2fce2 Author: Per Buer Date: Thu Mar 7 10:37:33 2013 +0100 Examples are back diff --git a/doc/sphinx/users-guide/vcl-example-acls.rst b/doc/sphinx/users-guide/vcl-example-acls.rst new file mode 100644 index 0000000..3d0226a --- /dev/null +++ b/doc/sphinx/users-guide/vcl-example-acls.rst @@ -0,0 +1,34 @@ + +ACLs +~~~~ + +You create a named access control list with the *acl* keyword. You can match +the IP address of the client against an ACL with the match operator.:: + + # Who is allowed to purge.... + acl local { + "localhost"; + "192.168.1.0"/24; /* and everyone on the local network */ + ! "192.168.1.23"; /* except for the dialin router */ + } + + sub vcl_recv { + if (req.method == "PURGE") { + if (client.ip ~ local) { + return(lookup); + } + } + } + + sub vcl_hit { + if (req.method == "PURGE") { + set obj.ttl = 0s; + error 200 "Purged."; + } + } + + sub vcl_miss { + if (req.method == "PURGE") { + error 404 "Not in cache."; + } + } diff --git a/doc/sphinx/users-guide/vcl-example-manipulating-headers.rst b/doc/sphinx/users-guide/vcl-example-manipulating-headers.rst new file mode 100644 index 0000000..35dcb1e --- /dev/null +++ b/doc/sphinx/users-guide/vcl-example-manipulating-headers.rst @@ -0,0 +1,21 @@ + + + +Manipulating request headers in VCL +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Lets say we want to remove the cookie for all objects in the /images +directory of our web server:: + + sub vcl_recv { + if (req.url ~ "^/images") { + unset req.http.cookie; + } + } + +Now, when the request is handled to the backend server there will be +no cookie header. The interesting line is the one with the +if-statement. It matches the URL, taken from the request object, and +matches it against the regular expression. Note the match operator. If +it matches the Cookie: header of the request is unset (deleted). + diff --git a/doc/sphinx/users-guide/vcl-example-manipulating-responses.rst b/doc/sphinx/users-guide/vcl-example-manipulating-responses.rst new file mode 100644 index 0000000..7362789 --- /dev/null +++ b/doc/sphinx/users-guide/vcl-example-manipulating-responses.rst @@ -0,0 +1,19 @@ + + +Altering the backend response +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Here we override the TTL of a object comming from the backend if it +matches certain criteria:: + + sub vcl_fetch { + if (req.url ~ "\.(png|gif|jpg)$") { + unset beresp.http.set-cookie; + set beresp.ttl = 1h; + } + } + +.. XXX ref hit-for-pass + +We also remove any Set-Cookie headers in order to avoid a hit-for-pass +object to be created. diff --git a/doc/sphinx/users-guide/vcl-example-websockets.rst b/doc/sphinx/users-guide/vcl-example-websockets.rst new file mode 100644 index 0000000..7217b88 --- /dev/null +++ b/doc/sphinx/users-guide/vcl-example-websockets.rst @@ -0,0 +1,20 @@ + +Implementing websocket support +------------------------------ + +Websockets is a technology for creating a bidirectional stream-based channel over HTTP. + +To run websockets through Varnish you need to pipe it, and copy the Upgrade header. Use the following +VCL config to do so:: + + sub vcl_pipe { + if (req.http.upgrade) { + set bereq.http.upgrade = req.http.upgrade; + } + } + sub vcl_recv { + if (req.http.Upgrade ~ "(?i)websocket") { + return (pipe); + } + } + From phk at varnish-cache.org Thu Mar 7 09:52:09 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Thu, 07 Mar 2013 10:52:09 +0100 Subject: [master] 81b988c Create a new vmod "directors" and move the demo-rr director into it, it is no longer a demo, it is going to replace the "built-in" rr director. Message-ID: commit 81b988c15ba74505c4aa859c81b886a76345879e Author: Poul-Henning Kamp Date: Thu Mar 7 09:51:10 2013 +0000 Create a new vmod "directors" and move the demo-rr director into it, it is no longer a demo, it is going to replace the "built-in" rr director. Other directors will follow as time permits. diff --git a/bin/varnishd/flint.sh b/bin/varnishd/flint.sh index c32c01b..0694b78 100755 --- a/bin/varnishd/flint.sh +++ b/bin/varnishd/flint.sh @@ -26,6 +26,7 @@ flexelint \ ../../lib/libvcl/*.c \ ../../lib/libvmod_std/*.c \ ../../lib/libvmod_debug/*.c \ + ../../lib/libvmod_directors/*.c \ 2>&1 | tee _.fl if [ -f _.fl.old ] ; then diff --git a/bin/varnishtest/tests/m00009.vtc b/bin/varnishtest/tests/m00009.vtc index c56f2ef..cad9b96 100644 --- a/bin/varnishtest/tests/m00009.vtc +++ b/bin/varnishtest/tests/m00009.vtc @@ -1,4 +1,4 @@ -varnishtest "Test vmod.debug round robin director" +varnishtest "Test vmod.directors round robin director" server s1 { @@ -25,9 +25,9 @@ server s4 { varnish v1 -vcl+backend { - import debug from "${topbuild}/lib/libvmod_debug/.libs/libvmod_debug.so" ; + import directors from "${topbuild}/lib/libvmod_directors/.libs/libvmod_directors.so" ; sub vcl_init { - new rr = debug.rr(); + new rr = directors.round_robin(); rr.add_backend(s1); rr.add_backend(s2); rr.add_backend(s3); diff --git a/bin/varnishtest/tests/m00010.vtc b/bin/varnishtest/tests/m00010.vtc index 332d16e..63ba40d 100644 --- a/bin/varnishtest/tests/m00010.vtc +++ b/bin/varnishtest/tests/m00010.vtc @@ -1,4 +1,4 @@ -varnishtest "Test vmod.debug round robin director" +varnishtest "Test vmod.directors round robin director in stacked fashion" server s1 { @@ -25,17 +25,17 @@ server s4 { varnish v1 -vcl+backend { - import debug from "${topbuild}/lib/libvmod_debug/.libs/libvmod_debug.so" ; + import directors from "${topbuild}/lib/libvmod_directors/.libs/libvmod_directors.so" ; sub vcl_init { - new rr1 = debug.rr(); + new rr1 = directors.round_robin(); rr1.add_backend(s1); rr1.add_backend(s3); - new rr2 = debug.rr(); + new rr2 = directors.round_robin(); rr2.add_backend(s2); rr2.add_backend(s4); - new rr3 = debug.rr(); + new rr3 = directors.round_robin(); rr3.add_backend(rr1.backend()); rr3.add_backend(rr2.backend()); } diff --git a/configure.ac b/configure.ac index 597ae29..e918ad7 100644 --- a/configure.ac +++ b/configure.ac @@ -607,6 +607,7 @@ AC_CONFIG_FILES([ lib/libvgz/Makefile lib/libvmod_debug/Makefile lib/libvmod_std/Makefile + lib/libvmod_directors/Makefile lib/libjemalloc/Makefile man/Makefile redhat/Makefile diff --git a/lib/Makefile.am b/lib/Makefile.am index 4fcc0ff..080f1b7 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -8,6 +8,7 @@ SUBDIRS = \ libvgz \ libvmod_debug \ libvmod_std \ + libvmod_directors \ @JEMALLOC_SUBDIR@ DIST_SUBDIRS = \ diff --git a/lib/libvmod_debug/Makefile.am b/lib/libvmod_debug/Makefile.am index a4f9fb7..7e2c849 100644 --- a/lib/libvmod_debug/Makefile.am +++ b/lib/libvmod_debug/Makefile.am @@ -15,8 +15,7 @@ libvmod_debug_la_LDFLAGS = $(AM_LDFLAGS) -module -export-dynamic -avoid-version libvmod_debug_la_SOURCES = \ vmod_debug.c \ - vmod_debug_obj.c \ - vmod_debug_rr.c + vmod_debug_obj.c nodist_libvmod_debug_la_SOURCES = \ vcc_if.c \ diff --git a/lib/libvmod_debug/vmod.vcc b/lib/libvmod_debug/vmod.vcc index 8451c6c..57d8721 100644 --- a/lib/libvmod_debug/vmod.vcc +++ b/lib/libvmod_debug/vmod.vcc @@ -35,8 +35,3 @@ Object obj(STRING) { Method STRING .foo(STRING why) Method TIME .date() } - -Object rr() { - Method VOID .add_backend(BACKEND) - Method BACKEND .backend() -} diff --git a/lib/libvmod_debug/vmod_debug_rr.c b/lib/libvmod_debug/vmod_debug_rr.c deleted file mode 100644 index a326051..0000000 --- a/lib/libvmod_debug/vmod_debug_rr.c +++ /dev/null @@ -1,161 +0,0 @@ -/*- - * Copyright (c) 2013 Varnish Software AS - * All rights reserved. - * - * Author: Poul-Henning Kamp - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "config.h" - -#include - -#include "cache/cache.h" -#include "cache/cache_backend.h" - -#include "vrt.h" -#include "vcc_if.h" - -struct vmod_debug_rr_entry { - unsigned magic; -#define VMOD_DEBUG_RR_ENTRY_MAGIC 0xa80970cf - VTAILQ_ENTRY(vmod_debug_rr_entry) list; - VCL_BACKEND be; -}; - -struct vmod_debug_rr { - unsigned magic; -#define VMOD_DEBUG_RR_MAGIC 0x99f4b726 - VTAILQ_HEAD(, vmod_debug_rr_entry) listhead; - int nbe; - pthread_mutex_t mtx; - struct director *dir; -}; - -static unsigned -vmod_rr_healthy(const struct director *dir, const struct req *req) -{ - struct vmod_debug_rr_entry *ep; - struct vmod_debug_rr *rr; - unsigned retval = 0; - - CAST_OBJ_NOTNULL(rr, dir->priv, VMOD_DEBUG_RR_MAGIC); - AZ(pthread_mutex_lock(&rr->mtx)); - VTAILQ_FOREACH(ep, &rr->listhead, list) { - if (ep->be->healthy(ep->be, req)) { - retval = 1; - break; - } - } - AZ(pthread_mutex_unlock(&rr->mtx)); - return (retval); -} - -static struct vbc * -vmod_rr_getfd(const struct director *dir, struct req *req) -{ - struct vmod_debug_rr_entry *ep = NULL; - struct vmod_debug_rr *rr; - int i; - - CAST_OBJ_NOTNULL(rr, dir->priv, VMOD_DEBUG_RR_MAGIC); - AZ(pthread_mutex_lock(&rr->mtx)); - for (i = 0; i < rr->nbe; i++) { - ep = VTAILQ_FIRST(&rr->listhead); - VTAILQ_REMOVE(&rr->listhead, ep, list); - VTAILQ_INSERT_TAIL(&rr->listhead, ep, list); - if (ep->be->healthy(ep->be, req)) - break; - } - AZ(pthread_mutex_unlock(&rr->mtx)); - if (i == rr->nbe || ep == NULL) - return (NULL); - return (ep->be->getfd(ep->be, req)); -} - -VCL_VOID -vmod_rr__init(struct req *req, struct vmod_debug_rr **rrp, const char *vcl_name) -{ - struct vmod_debug_rr *rr; - - (void)req; - - AN(rrp); - AZ(*rrp); - ALLOC_OBJ(rr, VMOD_DEBUG_RR_MAGIC); - AN(rr); - *rrp = rr; - AZ(pthread_mutex_init(&rr->mtx, NULL)); - VTAILQ_INIT(&rr->listhead); - ALLOC_OBJ(rr->dir, DIRECTOR_MAGIC); - AN(rr->dir); - REPLACE(rr->dir->vcl_name, vcl_name); - rr->dir->priv = rr; - rr->dir->healthy = vmod_rr_healthy; - rr->dir->getfd = vmod_rr_getfd; -} - -VCL_VOID -vmod_rr__fini(struct req *req, struct vmod_debug_rr **rrp) -{ - struct vmod_debug_rr *rr; - struct vmod_debug_rr_entry *ep; - - (void)req; - - rr = *rrp; - *rrp = NULL; - CHECK_OBJ_NOTNULL(rr, VMOD_DEBUG_RR_MAGIC); - - AZ(pthread_mutex_destroy(&rr->mtx)); - while (!VTAILQ_EMPTY(&rr->listhead)) { - ep = VTAILQ_FIRST(&rr->listhead); - VTAILQ_REMOVE(&rr->listhead, ep, list); - FREE_OBJ(ep); - } - REPLACE(rr->dir->vcl_name, NULL); - FREE_OBJ(rr->dir); - FREE_OBJ(rr); -} - -VCL_VOID -vmod_rr_add_backend(struct req *req, struct vmod_debug_rr * rr, VCL_BACKEND be) -{ - struct vmod_debug_rr_entry *ep; - (void)req; - - ALLOC_OBJ(ep, VMOD_DEBUG_RR_ENTRY_MAGIC); - AN(ep); - ep->be = be; - AZ(pthread_mutex_lock(&rr->mtx)); - VTAILQ_INSERT_TAIL(&rr->listhead, ep, list); - rr->nbe++; - AZ(pthread_mutex_unlock(&rr->mtx)); -} - -VCL_BACKEND __match_proto__() -vmod_rr_backend(struct req *req, struct vmod_debug_rr *rr) -{ - (void)req; - return (rr->dir); -} diff --git a/lib/libvmod_directors/Makefile.am b/lib/libvmod_directors/Makefile.am new file mode 100644 index 0000000..1e6ee13 --- /dev/null +++ b/lib/libvmod_directors/Makefile.am @@ -0,0 +1,31 @@ +# +AM_LDFLAGS = $(AM_LT_LDFLAGS) + +AM_CPPFLAGS = \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/bin/varnishd \ + -I$(top_builddir)/include + +vmoddir = $(pkglibdir)/vmods +vmod_srcdir = $(top_srcdir)/lib/libvmod_directors +vmodtool = $(top_srcdir)/lib/libvcl/vmodtool.py +noinst_LTLIBRARIES = libvmod_directors.la + +libvmod_directors_la_LDFLAGS = $(AM_LDFLAGS) -module -export-dynamic -avoid-version -shared -rpath /nowhere + +libvmod_directors_la_SOURCES = \ + round_robin.c + +nodist_libvmod_directors_la_SOURCES = \ + vcc_if.c \ + vcc_if.h + +# BUILT_SOURCES is only a hack and dependency tracking does not help for the first build +vmod_directors.lo: vcc_if.h + +vcc_if.c vcc_if.h: $(vmodtool) $(vmod_srcdir)/vmod.vcc + @PYTHON@ $(vmodtool) $(vmod_srcdir)/vmod.vcc + +EXTRA_DIST = vmod.vcc + +CLEANFILES = $(builddir)/vcc_if.c $(builddir)/vcc_if.h diff --git a/lib/libvmod_directors/round_robin.c b/lib/libvmod_directors/round_robin.c new file mode 100644 index 0000000..ce89039 --- /dev/null +++ b/lib/libvmod_directors/round_robin.c @@ -0,0 +1,163 @@ +/*- + * Copyright (c) 2013 Varnish Software AS + * All rights reserved. + * + * Author: Poul-Henning Kamp + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "config.h" + +#include + +#include "cache/cache.h" +#include "cache/cache_backend.h" + +#include "vrt.h" +#include "vcc_if.h" + +struct rr_entry { + unsigned magic; +#define RR_ENTRY_MAGIC 0xa80970cf + VTAILQ_ENTRY(rr_entry) list; + VCL_BACKEND be; +}; + +struct vmod_directors_round_robin { + unsigned magic; +#define VMOD_DEBUG_RR_MAGIC 0x99f4b726 + VTAILQ_HEAD(, rr_entry) listhead; + int nbe; + pthread_mutex_t mtx; + struct director *dir; +}; + +static unsigned +vmod_rr_healthy(const struct director *dir, const struct req *req) +{ + struct rr_entry *ep; + struct vmod_directors_round_robin *rr; + unsigned retval = 0; + + CAST_OBJ_NOTNULL(rr, dir->priv, VMOD_DEBUG_RR_MAGIC); + AZ(pthread_mutex_lock(&rr->mtx)); + VTAILQ_FOREACH(ep, &rr->listhead, list) { + if (ep->be->healthy(ep->be, req)) { + retval = 1; + break; + } + } + AZ(pthread_mutex_unlock(&rr->mtx)); + return (retval); +} + +static struct vbc * +vmod_rr_getfd(const struct director *dir, struct req *req) +{ + struct rr_entry *ep = NULL; + struct vmod_directors_round_robin *rr; + int i; + + CAST_OBJ_NOTNULL(rr, dir->priv, VMOD_DEBUG_RR_MAGIC); + AZ(pthread_mutex_lock(&rr->mtx)); + for (i = 0; i < rr->nbe; i++) { + ep = VTAILQ_FIRST(&rr->listhead); + VTAILQ_REMOVE(&rr->listhead, ep, list); + VTAILQ_INSERT_TAIL(&rr->listhead, ep, list); + if (ep->be->healthy(ep->be, req)) + break; + } + AZ(pthread_mutex_unlock(&rr->mtx)); + if (i == rr->nbe || ep == NULL) + return (NULL); + return (ep->be->getfd(ep->be, req)); +} + +VCL_VOID +vmod_round_robin__init(struct req *req, struct vmod_directors_round_robin **rrp, + const char *vcl_name) +{ + struct vmod_directors_round_robin *rr; + + (void)req; + + AN(rrp); + AZ(*rrp); + ALLOC_OBJ(rr, VMOD_DEBUG_RR_MAGIC); + AN(rr); + *rrp = rr; + AZ(pthread_mutex_init(&rr->mtx, NULL)); + VTAILQ_INIT(&rr->listhead); + ALLOC_OBJ(rr->dir, DIRECTOR_MAGIC); + AN(rr->dir); + REPLACE(rr->dir->vcl_name, vcl_name); + rr->dir->priv = rr; + rr->dir->healthy = vmod_rr_healthy; + rr->dir->getfd = vmod_rr_getfd; +} + +VCL_VOID +vmod_round_robin__fini(struct req *req, struct vmod_directors_round_robin **rrp) +{ + struct vmod_directors_round_robin *rr; + struct rr_entry *ep; + + (void)req; + + rr = *rrp; + *rrp = NULL; + CHECK_OBJ_NOTNULL(rr, VMOD_DEBUG_RR_MAGIC); + + AZ(pthread_mutex_destroy(&rr->mtx)); + while (!VTAILQ_EMPTY(&rr->listhead)) { + ep = VTAILQ_FIRST(&rr->listhead); + VTAILQ_REMOVE(&rr->listhead, ep, list); + FREE_OBJ(ep); + } + REPLACE(rr->dir->vcl_name, NULL); + FREE_OBJ(rr->dir); + FREE_OBJ(rr); +} + +VCL_VOID +vmod_round_robin_add_backend(struct req *req, struct vmod_directors_round_robin * rr, + VCL_BACKEND be) +{ + struct rr_entry *ep; + (void)req; + + ALLOC_OBJ(ep, RR_ENTRY_MAGIC); + AN(ep); + ep->be = be; + AZ(pthread_mutex_lock(&rr->mtx)); + VTAILQ_INSERT_TAIL(&rr->listhead, ep, list); + rr->nbe++; + AZ(pthread_mutex_unlock(&rr->mtx)); +} + +VCL_BACKEND __match_proto__() +vmod_round_robin_backend(struct req *req, struct vmod_directors_round_robin *rr) +{ + (void)req; + return (rr->dir); +} diff --git a/lib/libvmod_directors/vmod.vcc b/lib/libvmod_directors/vmod.vcc new file mode 100644 index 0000000..0cf0251 --- /dev/null +++ b/lib/libvmod_directors/vmod.vcc @@ -0,0 +1,33 @@ +#- +# Copyright (c) 2013 Varnish Software AS +# All rights reserved. +# +# Author: Poul-Henning Kamp +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +Module directors + +Object round_robin() { + Method VOID .add_backend(BACKEND) + Method BACKEND .backend() +} From phk at varnish-cache.org Thu Mar 7 10:03:51 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Thu, 07 Mar 2013 11:03:51 +0100 Subject: [master] 67730b6 Add missing mention of libvmod_directors Message-ID: commit 67730b681882255f39dc94f025f5397596212548 Author: Poul-Henning Kamp Date: Thu Mar 7 10:03:33 2013 +0000 Add missing mention of libvmod_directors diff --git a/lib/Makefile.am b/lib/Makefile.am index 080f1b7..094f42e 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -19,4 +19,5 @@ DIST_SUBDIRS = \ libvgz \ libvmod_debug \ libvmod_std \ + libvmod_directors \ libjemalloc From phk at varnish-cache.org Thu Mar 7 10:15:47 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Thu, 07 Mar 2013 11:15:47 +0100 Subject: [master] cea487b Another attempt to get get things to build... Message-ID: commit cea487b40a5b7992ae809e7dd997a23c8b078c62 Author: Poul-Henning Kamp Date: Thu Mar 7 10:15:28 2013 +0000 Another attempt to get get things to build... diff --git a/lib/libvmod_directors/Makefile.am b/lib/libvmod_directors/Makefile.am index 1e6ee13..bc230a5 100644 --- a/lib/libvmod_directors/Makefile.am +++ b/lib/libvmod_directors/Makefile.am @@ -21,7 +21,7 @@ nodist_libvmod_directors_la_SOURCES = \ vcc_if.h # BUILT_SOURCES is only a hack and dependency tracking does not help for the first build -vmod_directors.lo: vcc_if.h +round_robin.lo: vcc_if.h vcc_if.c vcc_if.h: $(vmodtool) $(vmod_srcdir)/vmod.vcc @PYTHON@ $(vmodtool) $(vmod_srcdir)/vmod.vcc From phk at varnish-cache.org Thu Mar 7 10:37:46 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Thu, 07 Mar 2013 11:37:46 +0100 Subject: [master] 3a73406 Fixes for at least one GCC bug Message-ID: commit 3a73406bbdbc25c4857510f32001bacd1a8ab777 Author: Poul-Henning Kamp Date: Thu Mar 7 10:37:31 2013 +0000 Fixes for at least one GCC bug diff --git a/bin/varnishd/cache/cache_acceptor.c b/bin/varnishd/cache/cache_acceptor.c index 5c8f30a..ee9352f 100644 --- a/bin/varnishd/cache/cache_acceptor.c +++ b/bin/varnishd/cache/cache_acceptor.c @@ -120,7 +120,7 @@ static unsigned need_test; */ static int -vca_tcp_opt_init() +vca_tcp_opt_init(void) { int n, x; int one = 1; diff --git a/bin/varnishd/cache/cache_vrt_vmod.c b/bin/varnishd/cache/cache_vrt_vmod.c index 3a90a4d..dea71ff 100644 --- a/bin/varnishd/cache/cache_vrt_vmod.c +++ b/bin/varnishd/cache/cache_vrt_vmod.c @@ -120,7 +120,7 @@ VRT_Vmod_Init(void **hdl, void *ptr, int len, const char *nm, if (strcmp(w, VMOD_ABI_Version)) { VCLI_Out(cli, "Loading VMOD %s from %s:\n", nm, path); - VCLI_Out(cli, "VMOD ABI (%s)", w); + VCLI_Out(cli, "VMOD ABI (%s)", (char*)w); VCLI_Out(cli, " incompatible with varnish ABI (%s)\n", VMOD_ABI_Version); (void)dlclose(v->hdl); diff --git a/lib/libvmod_directors/round_robin.c b/lib/libvmod_directors/round_robin.c index ce89039..9339046 100644 --- a/lib/libvmod_directors/round_robin.c +++ b/lib/libvmod_directors/round_robin.c @@ -134,7 +134,7 @@ vmod_round_robin__fini(struct req *req, struct vmod_directors_round_robin **rrp) VTAILQ_REMOVE(&rr->listhead, ep, list); FREE_OBJ(ep); } - REPLACE(rr->dir->vcl_name, NULL); + free(rr->dir->vcl_name); FREE_OBJ(rr->dir); FREE_OBJ(rr); } From phk at varnish-cache.org Thu Mar 7 10:54:15 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Thu, 07 Mar 2013 11:54:15 +0100 Subject: [master] 5582b35 Remove reference to no non-existsnt doc-file Message-ID: commit 5582b35be3d6a66a1c2764a11781014066a879c6 Author: Poul-Henning Kamp Date: Thu Mar 7 10:53:52 2013 +0000 Remove reference to no non-existsnt doc-file diff --git a/doc/sphinx/Makefile.am b/doc/sphinx/Makefile.am index 8be9296..3dc88c6 100644 --- a/doc/sphinx/Makefile.am +++ b/doc/sphinx/Makefile.am @@ -97,7 +97,6 @@ EXTRA_DIST = \ installation/index.rst \ installation/install.rst \ installation/prerequisites.rst \ - installation/upgrade.rst \ installation/platformnotes.rst \ phk/autocrap.rst \ phk/backends.rst \ From phk at varnish-cache.org Sat Mar 9 08:39:38 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Sat, 09 Mar 2013 09:39:38 +0100 Subject: [master] 3ed75f5 OpenBSD is not defined (unless sys/param.h is included) so simply use the gcc builtin define for it. Message-ID: commit 3ed75f50638a9461f443337d61c0b4c9dcd3f766 Author: Poul-Henning Kamp Date: Sat Mar 9 08:39:21 2013 +0000 OpenBSD is not defined (unless sys/param.h is included) so simply use the gcc builtin define for it. From: "Federico G. Schwindt" diff --git a/bin/varnishd/mgt/mgt_shmem.c b/bin/varnishd/mgt/mgt_shmem.c index 7707309..2e92df6 100644 --- a/bin/varnishd/mgt/mgt_shmem.c +++ b/bin/varnishd/mgt/mgt_shmem.c @@ -247,7 +247,7 @@ mgt_SHM_Create(void) exit (-1); } -#ifdef OpenBSD +#ifdef __OpenBSD__ /* Commit changes, for OS's without coherent VM/buf */ AZ(msync(p, getpagesize(), MS_SYNC)); #endif From tfheen at varnish-cache.org Mon Mar 11 07:59:55 2013 From: tfheen at varnish-cache.org (Tollef Fog Heen) Date: Mon, 11 Mar 2013 08:59:55 +0100 Subject: [master] 85b8869 Fix typos Message-ID: commit 85b8869f49b0fb3d0b4cdd356572216475684285 Author: Benjamin Kerensa Date: Mon Mar 11 08:43:18 2013 +0100 Fix typos diff --git a/bin/varnishd/mgt/mgt_main.c b/bin/varnishd/mgt/mgt_main.c index b41133c..a111481 100644 --- a/bin/varnishd/mgt/mgt_main.c +++ b/bin/varnishd/mgt/mgt_main.c @@ -180,7 +180,7 @@ usage(void) fprintf(stderr, FMT, "-T address:port", "Telnet listen address and port"); fprintf(stderr, FMT, "-V", "version"); - fprintf(stderr, FMT, "-u user", "Priviledge separation user id"); + fprintf(stderr, FMT, "-u user", "Privilege separation user id"); #undef FMT exit(1); } diff --git a/bin/varnishd/mgt/mgt_param.c b/bin/varnishd/mgt/mgt_param.c index ebb784d..f83fb84 100644 --- a/bin/varnishd/mgt/mgt_param.c +++ b/bin/varnishd/mgt/mgt_param.c @@ -725,7 +725,7 @@ mcf_param_show(struct cli *cli, const char * const *av, void *priv) } /*-------------------------------------------------------------------- - * Mark paramters as protected + * Mark parameters as protected */ void From tfheen at varnish-cache.org Mon Mar 11 07:59:55 2013 From: tfheen at varnish-cache.org (Tollef Fog Heen) Date: Mon, 11 Mar 2013 08:59:55 +0100 Subject: [master] 5a1567e Output the wizard flag in the docs too Message-ID: commit 5a1567e932a958fbee0977225dcbec634c9543cf Author: Tollef Fog Heen Date: Mon Mar 11 08:48:27 2013 +0100 Output the wizard flag in the docs too diff --git a/bin/varnishd/mgt/mgt_param.c b/bin/varnishd/mgt/mgt_param.c index f83fb84..af4a982 100644 --- a/bin/varnishd/mgt/mgt_param.c +++ b/bin/varnishd/mgt/mgt_param.c @@ -950,6 +950,10 @@ MCF_DumpRstParam(void) printf("%sexperimental", q); q = ", "; } + if (pp->flags & WIZARD) { + printf("%swizard", q); + q = ", "; + } printf("\n"); } printf("\n\t"); From tfheen at varnish-cache.org Mon Mar 11 07:59:55 2013 From: tfheen at varnish-cache.org (Tollef Fog Heen) Date: Mon, 11 Mar 2013 08:59:55 +0100 Subject: [master] 7e5fca4 Whitespace Message-ID: commit 7e5fca4a427bbf57c8d500316b10d535e2e94db8 Author: Tollef Fog Heen Date: Mon Mar 11 08:58:02 2013 +0100 Whitespace diff --git a/bin/varnishd/mgt/mgt_param_tbl.c b/bin/varnishd/mgt/mgt_param_tbl.c index b92c71b..5f66f87 100644 --- a/bin/varnishd/mgt/mgt_param_tbl.c +++ b/bin/varnishd/mgt/mgt_param_tbl.c @@ -193,7 +193,7 @@ const struct parspec mgt_parspec[] = { { "send_timeout", tweak_timeout, &mgt_param.send_timeout, 0, 0, "Send timeout for client connections. " "If the HTTP response hasn't been transmitted in this many\n" - "seconds the session is closed. \n" + "seconds the session is closed.\n" "See setsockopt(2) under SO_SNDTIMEO for more information.", DELAYED_EFFECT, "600", "seconds" }, @@ -201,7 +201,7 @@ const struct parspec mgt_parspec[] = { 0, 0, "Time to wait with no data sent. " "If no data has been transmitted in this many\n" - "seconds the session is closed. \n" + "seconds the session is closed.\n" "See setsockopt(2) under SO_SNDTIMEO for more information.", DELAYED_EFFECT, "60", "seconds" }, From tfheen at varnish-cache.org Mon Mar 11 07:59:55 2013 From: tfheen at varnish-cache.org (Tollef Fog Heen) Date: Mon, 11 Mar 2013 08:59:55 +0100 Subject: [master] 7f4bf4b Update parameters to current source Message-ID: commit 7f4bf4bf5433b7469d8b962f3910ca0f572f4ccd Author: Tollef Fog Heen Date: Mon Mar 11 08:59:53 2013 +0100 Update parameters to current source diff --git a/doc/sphinx/reference/params.rst b/doc/sphinx/reference/params.rst index 1f9a486..1ec8f58 100644 --- a/doc/sphinx/reference/params.rst +++ b/doc/sphinx/reference/params.rst @@ -1,3 +1,13 @@ + +.. The following is the autogenerated output from varnishd -x dumprstparam + +accept_filter + - Units: bool + - Default: on + - Flags: must_restart + + Enable kernel accept-filters, if supported by the kernel. + acceptor_sleep_decay - Default: 0.900 - Flags: experimental @@ -46,25 +56,37 @@ between_bytes_timeout Default timeout between bytes when receiving data from backend. We only wait for this many seconds between bytes before giving up. A value of 0 means it will never time out. VCL can override this default value for each backend request and backend request. This parameter does not apply to pipe. +busyobj_worker_cache + - Units: bool + - Default: off + + Cache free busyobj per worker thread.Disable this if you have very high hitrates and wantto save the memory of one busyobj per worker thread. + cc_command - - Default: exec gcc -std=gnu99 -pthread -fpic -shared -Wl,-x -o %o %s + - Default: exec gcc -std=gnu99 -g -O2 -pthread -fpic -shared -Wl,-x -o %o %s - Flags: must_reload Command used for compiling the C source code to a dlopen(3) loadable object. Any occurrence of %s in the string will be replaced with the source file name, and %o will be replaced with the output file name. cli_buffer - Units: bytes - - Default: 8192 + - Default: 8k - Size of buffer for CLI input. + Size of buffer for CLI command input. You may need to increase this if you have big VCL files and use the vcl.inline CLI command. NB: Must be specified with -p to have effect. +cli_limit + - Units: bytes + - Default: 48k + + Maximum size of CLI response. If the response exceeds this limit, the reponse code will be 201 instead of 200 and the last line will indicate the truncation. + cli_timeout - Units: seconds - Default: 10 - Timeout for the childs replies to CLI requests from the master. + Timeout for the childs replies to CLI requests from the mgt_param. clock_skew - Units: s @@ -81,10 +103,26 @@ connect_timeout critbit_cooloff - Units: s - Default: 180.0 - - Flags: + - Flags: wizard How long time the critbit hasher keeps deleted objheads on the cooloff list. +debug + - Default: none + + Enable/Disable various kinds of debugging. + none Disable all debugging + Use +/- prefix to set/reset individual bits:: + + req_state VSL Request state engine + workspace VSL Workspace operations + waiter VSL Waiter internals + waitinglist VSL Waitinglist events + syncvsl Make VSL synchronous + hashedge Edge cases in Hash + vclrel Rapid VCL release + lurker VSL Ban lurker + default_grace - Units: seconds - Default: 10 @@ -106,30 +144,7 @@ default_ttl The TTL assigned to objects if neither the backend nor the VCL code assigns one. Objects already cached will not be affected by changes made until they are fetched from the backend again. - To force an immediate effect at the expense of a total flush of the cache use "ban.url ." - -diag_bitmap - - Units: bitmap - - Default: 0 - - Bitmap controlling diagnostics code:: - - 0x00000001 - CNT_Session states. - 0x00000002 - workspace debugging. - 0x00000004 - kqueue debugging. - 0x00000008 - mutex logging. - 0x00000010 - mutex contests. - 0x00000020 - waiting list. - 0x00000040 - object workspace. - 0x00001000 - do not core-dump child process. - 0x00002000 - only short panic message. - 0x00004000 - panic to stderr. - 0x00010000 - synchronize shmlog. - 0x00020000 - synchronous start of persistence. - 0x00040000 - release VCL early. - 0x80000000 - do edge-detection on digest. - - Use 0x notation and do the bitor in your head :-) + To force an immediate effect at the expense of a total flush of the cache use "ban obj.http.date ~ ." esi_syntax - Units: bitmap @@ -150,17 +165,28 @@ expiry_sleep How long the expiry thread sleeps when there is nothing for it to do. +feature + - Default: none + + Enable/Disable various minor features. + none Disable all features. + Use +/- prefix to enable/disable individual feature:: + + short_panic Short panic message. + wait_silo Wait for persistent silo. + no_coredump No coredumps. + fetch_chunksize - - Units: kilobytes - - Default: 128 + - Units: bytes + - Default: 128k - Flags: experimental The default chunksize used by fetcher. This should be bigger than the majority of objects with short TTLs. Internal limits in the storage_file module makes increases above 128kb a dubious idea. fetch_maxchunksize - - Units: kilobytes - - Default: 262144 + - Units: bytes + - Default: 256m - Flags: experimental The maximum chunksize we attempt to allocate from storage. Making this too large may cause delays and storage fragmentation. @@ -172,11 +198,19 @@ first_byte_timeout Default timeout for receiving first byte from backend. We only wait for this many seconds for the first byte before giving up. A value of 0 means it will never time out. VCL can override this default value for each backend and backend request. This parameter does not apply to pipe. group - - Default: magic + - Default: nogroup - Flags: must_restart The unprivileged group to run as. +gzip_buffer + - Units: bytes + - Default: 32k + - Flags: experimental + + Size of malloc buffer used for gzip processing. + These buffers are used for in-transit data, for instance gunzip'ed data being sent to a client.Making this space to small results in more overhead, writes to sockets etc, making it too big is probably just a waste of memory. + gzip_level - Default: 6 @@ -188,40 +222,14 @@ gzip_memlevel Gzip memory level 1=slow/least, 9=fast/most compression. Memory impact is 1=1k, 2=2k, ... 9=256k. -gzip_stack_buffer - - Units: Bytes - - Default: 32768 - - Flags: experimental - - Size of stack buffer used for gzip processing. - The stack buffers are used for in-transit data, for instance gunzip'ed data being sent to a client.Making this space to small results in more overhead, writes to sockets etc, making it too big is probably just a waste of memory. - -gzip_tmp_space - - Default: 0 - - Flags: experimental - - Where temporary space for gzip/gunzip is allocated:: - - 0 - malloc - 1 - session workspace - 2 - thread workspace - - If you have much gzip/gunzip activity, it may be an advantage to use workspace for these allocations to reduce malloc activity. Be aware that gzip needs 256+KB and gunzip needs 32+KB of workspace (64+KB if ESI processing). - -gzip_window - - Default: 15 - - Gzip window size 8=least, 15=most compression. - Memory impact is 8=1k, 9=2k, ... 15=128k. - http_gzip_support - Units: bool - Default: on - Flags: experimental - Enable gzip support. When enabled Varnish will compress uncompressed objects before they are stored in the cache. If a client does not support gzip encoding Varnish will uncompress compressed objects on demand. Varnish will also rewrite the Accept-Encoding header of clients indicating support for gzip to: + Enable gzip support. When enabled Varnish will compress uncompressed objects before they are stored in the cache. If a client does not support gzip encoding Varnish will uncompress compressed objects on demand. Varnish will also rewrite the Accept-Encoding header of clients indicating support for gzip to:: - Accept-Encoding: gzip + Accept-Encoding: gzip Clients that do not support gzip will have their Accept-Encoding header removed. For more information on how gzip is implemented please see the chapter on gzip in the Varnish reference. @@ -229,41 +237,50 @@ http_max_hdr - Units: header lines - Default: 64 - Maximum number of HTTP headers we will deal with in client request or backend reponses. Note that the first line occupies five header fields. - This paramter does not influence storage consumption, objects allocate exact space for the headers they store. + Maximum number of HTTP header lines we allow in {req|resp|bereq|beresp}.http (obj.http is autosized to the exact number of headers). + Cheap, ~20 bytes, in terms of workspace memory. + Note that the first line occupies five header lines. http_range_support - Units: bool - Default: on - - Flags: experimental Enable support for HTTP Range headers. http_req_hdr_len - Units: bytes - - Default: 4096 + - Default: 8k Maximum length of any HTTP client request header we will allow. The limit is inclusive its continuation lines. http_req_size - Units: bytes - - Default: 32768 + - Default: 32k Maximum number of bytes of HTTP client request we will deal with. This is a limit on all bytes up to the double blank line which ends the HTTP request. The memory for the request is allocated from the client workspace (param: workspace_client) and this parameter limits how much of that the request is allowed to take up. http_resp_hdr_len - Units: bytes - - Default: 4096 + - Default: 8k Maximum length of any HTTP backend response header we will allow. The limit is inclusive its continuation lines. http_resp_size - Units: bytes - - Default: 32768 + - Default: 32k Maximum number of bytes of HTTP backend resonse we will deal with. This is a limit on all bytes up to the double blank line which ends the HTTP request. - The memory for the request is allocated from the thread pool workspace (param: thread_pool_workspace) and this parameter limits how much of that the request is allowed to take up. + The memory for the request is allocated from the worker workspace (param: thread_pool_workspace) and this parameter limits how much of that the request is allowed to take up. + +idle_send_timeout + - Units: seconds + - Default: 60 + - Flags: delayed + + Time to wait with no data sent. If no data has been transmitted in this many + seconds the session is closed. + See setsockopt(2) under SO_SNDTIMEO for more information. listen_address - Default: :80 @@ -279,17 +296,12 @@ listen_depth Listen queue depth. -log_hashstring - - Units: bool - - Default: on - - Log the hash string components to shared memory log. - log_local_address - Units: bool - - Default: off + - Default: on - Log the local address on the TCP connection in the SessionOpen shared memory record. + Log the local address on the TCP connection in the SessionOpen VSL record. + Disabling this saves a getsockname(2) system call per TCP connection. lru_interval - Units: seconds @@ -314,11 +326,27 @@ max_restarts nuke_limit - Units: allocations - - Default: 10 + - Default: 50 - Flags: experimental Maximum number of objects we attempt to nuke in orderto make space for a object body. +obj_readonly + - Units: bool + - Default: false + + If set, we do not update obj.hits and obj.lastuse to avoid dirtying VM pages associated with cached objects. + +pcre_match_limit + - Default: 10000 + + The limit for the number of internal matching function calls in a pcre_exec() execution. + +pcre_match_limit_recursion + - Default: 10000 + + The limit for the number of internal matching function recursions in a pcre_exec() execution. + ping_interval - Units: seconds - Default: 3 @@ -333,21 +361,52 @@ pipe_timeout Idle timeout for PIPE sessions. If nothing have been received in either direction for this many seconds, the session is closed. +pool_req + - Default: 10,100,10 + + Parameters for per worker pool request memory pool. + The three numbers are:: + + min_pool -- minimum size of free pool. + max_pool -- maximum size of free pool. + max_age -- max age of free element. + +pool_sess + - Default: 10,100,10 + + Parameters for per worker pool session memory pool. + The three numbers are:: + + min_pool -- minimum size of free pool. + max_pool -- maximum size of free pool. + max_age -- max age of free element. + +pool_vbc + - Default: 10,100,10 + + Parameters for backend connection memory pool. + The three numbers are:: + + min_pool -- minimum size of free pool. + max_pool -- maximum size of free pool. + max_age -- max age of free element. + +pool_vbo + - Default: 10,100,10 + + Parameters for backend object fetch memory pool. + The three numbers are:: + + min_pool -- minimum size of free pool. + max_pool -- maximum size of free pool. + max_age -- max age of free element. + prefer_ipv6 - Units: bool - Default: off Prefer IPv6 address when connecting to backends which have both IPv4 and IPv6 addresses. -queue_max - - Units: % - - Default: 100 - - Flags: experimental - - Percentage permitted queue length. - - This sets the ratio of queued requests to worker threads, above which sessions will be dropped instead of queued. - rush_exponent - Units: requests per request - Default: 3 @@ -365,33 +424,18 @@ saintmode_threshold send_timeout - Units: seconds - - Default: 60 + - Default: 600 - Flags: delayed Send timeout for client connections. If the HTTP response hasn't been transmitted in this many - seconds the session is closed. + seconds the session is closed. See setsockopt(2) under SO_SNDTIMEO for more information. -sess_timeout - - Units: seconds - - Default: 5 - - Idle timeout for persistent sessions. If a HTTP request has not been received in this many seconds, the session is closed. - -session_linger - - Units: ms - - Default: 50 - - Flags: experimental - - How long time the workerthread lingers on the session to see if a new request appears right away. - If sessions are reused, as much as half of all reuses happen within the first 100 msec of the previous request completing. - Setting this too high results in worker threads not doing anything for their keep, setting it too low just means that more sessions take a detour around the waiter. - session_max - Units: sessions - Default: 100000 - Maximum number of sessions we will allocate before just dropping connections. + Maximum number of sessions we will allocate from one pool before just dropping connections. This is mostly an anti-DoS measure, and setting it plenty high should not hurt, as long as you have the memory for it. shm_reclen @@ -401,15 +445,6 @@ shm_reclen Maximum number of bytes in SHM log record. Maximum is 65535 bytes. -shm_workspace - - Units: bytes - - Default: 8192 - - Flags: delayed - - Bytes of shmlog workspace allocated for worker threads. If too big, it wastes some ram, if too small it causes needless flushes of the SHM workspace. - These flushes show up in stats as "SHM flushes due to overflow". - Minimum is 4096 bytes. - shortlived - Units: s - Default: 10.0 @@ -422,36 +457,58 @@ syslog_cli_traffic Log all CLI traffic to syslog(LOG_INFO). -thread_pool_add_delay - - Units: milliseconds - - Default: 2 +tcp_keepalive_intvl + - Units: seconds + - Default: 5 + - Flags: experimental - Wait at least this long between creating threads. + The number of seconds between TCP keep-alive probes. Note that this setting will only take effect when it is less thanthe system default. - Setting this too long results in insuffient worker threads. +tcp_keepalive_probes + - Units: probes + - Default: 5 + - Flags: experimental - Setting this too short increases the risk of worker thread pile-up. + The maximum number of TCP keep-alive probes to send before giving up and killing the connection if no response is obtained from the other end. Note that this setting will only take effect when it is less than the system default. -thread_pool_add_threshold - - Units: requests - - Default: 2 +tcp_keepalive_time + - Units: seconds + - Default: 600 - Flags: experimental - Overflow threshold for worker thread creation. + The number of seconds a connection needs to be idle before TCP begins sending out keep-alive probes. Note that this setting will only take effect when it is less than the system default. - Setting this too low, will result in excess worker threads, which is generally a bad idea. +thread_pool_add_delay + - Units: seconds + - Default: 0 + - Flags: experimental - Setting it too high results in insuffient worker threads. + Wait at least this long after creating a thread. + + Some (buggy) systems may need a short (sub-second) delay between creating threads. + Set this to a few milliseconds if you see the 'threads_failed' counter grow too much. + + Setting this too high results in insuffient worker threads. + +thread_pool_destroy_delay + - Units: seconds + - Default: 1 + - Flags: delayed, experimental + + Wait this long after destroying a thread. + + This controls the decay of thread pools when idle(-ish). + + Minimum is 0.01 second. thread_pool_fail_delay - - Units: milliseconds - - Default: 200 + - Units: seconds + - Default: 0.2 - Flags: experimental Wait at least this long after a failed thread creation before trying to create another thread. - Failure to create a worker thread is often a sign that the end is near, because the process is running out of RAM resources for thread stacks. - This delay tries to not rush it on needlessly. + Failure to create a worker thread is often a sign that the end is near, because the process is running out of some resource. This delay tries to not rush the end on needlessly. If thread creation failures are a problem, check that thread_pool_max is not too high. @@ -459,42 +516,34 @@ thread_pool_fail_delay thread_pool_max - Units: threads - - Default: 500 - - Flags: delayed, experimental + - Default: 5000 + - Flags: delayed The maximum number of worker threads in each pool. Do not set this higher than you have to, since excess worker threads soak up RAM and CPU and generally just get in the way of getting work done. + Minimum is 10 threads. + thread_pool_min - Units: threads - - Default: 5 - - Flags: delayed, experimental + - Default: 100 + - Flags: delayed The minimum number of worker threads in each pool. - Increasing this may help ramp up faster from low load situations where threads have expired. - - Minimum is 2 threads. - -thread_pool_purge_delay - - Units: milliseconds - - Default: 1000 - - Flags: delayed, experimental - - Wait this long between purging threads. - - This controls the decay of thread pools when idle(-ish). + Increasing this may help ramp up faster from low load situations or when threads have expired. - Minimum is 100 milliseconds. + Minimum is 10 threads. thread_pool_stack - Units: bytes - - Default: -1 + - Default: 48k - Flags: experimental Worker thread stack size. - On 32bit systems you may need to tweak this down to fit many threads into the limited address space. + This is likely rounded up to a multiple of 4k by the kernel. + The kernel/OS has a lower limit which will be enforced. thread_pool_timeout - Units: seconds @@ -503,16 +552,9 @@ thread_pool_timeout Thread idle threshold. - Threads in excess of thread_pool_min, which have been idle for at least this long are candidates for purging. + Threads in excess of thread_pool_min, which have been idle for at least this long, will be destroyed. - Minimum is 1 second. - -thread_pool_workspace - - Units: bytes - - Default: 65536 - - Flags: delayed - - Bytes of HTTP protocol workspace allocated for worker threads. This space must be big enough for the backend request and responses, and response to the client plus any other memory needs in the VCL code.Minimum is 1024 bytes. + Minimum is 10 seconds. thread_pools - Units: pools @@ -527,6 +569,14 @@ thread_pools Can be increased on the fly, but decreases require a restart to take effect. +thread_queue_limit + - Default: 20 + - Flags: experimental + + Permitted queue length per thread-pool. + + This sets the number of requests we will queue, waiting for an available thread. Above this limit sessions will be dropped instead of queued. + thread_stats_rate - Units: requests - Default: 10 @@ -535,11 +585,39 @@ thread_stats_rate Worker threads accumulate statistics, and dump these into the global stats counters if the lock is free when they finish a request. This parameters defines the maximum number of requests a worker thread may handle, before it is forced to dump its accumulated stats into the global counters. +timeout_idle + - Units: seconds + - Default: 5 + + Idle timeout for client connections. + A connection is considered idle, until we receive a non-white-space character on it. + +timeout_linger + - Units: seconds + - Default: 0.050 + - Flags: experimental + + How long time the workerthread lingers on an idle session before handing it over to the waiter. + When sessions are reused, as much as half of all reuses happen within the first 100 msec of the previous request completing. + Setting this too high results in worker threads not doing anything for their keep, setting it too low just means that more sessions take a detour around the waiter. + +timeout_req + - Units: seconds + - Default: 2 + + Max time to receive clients request header, measured from first non-white-space character to double CRNL. + user - - Default: magic + - Default: nobody - Flags: must_restart - The unprivileged user to run as. Setting this will also set "group" to the specified user's primary group. + The unprivileged user to run as. + +vcc_allow_inline_c + - Units: bool + - Default: on + + Allow inline C code in VCL. vcc_err_unref - Units: bool @@ -547,28 +625,79 @@ vcc_err_unref Unreferenced VCL objects result in error. -vcl_dir - - Default: /usr/local/etc/varnish +vcc_unsafe_path + - Units: bool + - Default: on - Directory from which relative VCL filenames (vcl.load and include) are opened. + Allow '/' in vmod & include paths. + Allow 'import ... from ...'. -vcl_trace - - Units: bool - - Default: off +vcl_dir + - Default: /tmp/z/v/etc/varnish - Trace VCL execution in the shmlog. - Enabling this will allow you to see the path each request has taken through the VCL program. - This generates a lot of logrecords so it is off by default. + Directory from which relative VCL filenames (vcl.load and include) are opened. vmod_dir - - Default: /usr/local/lib/varnish/vmods + - Default: /tmp/z/v/lib/varnish/vmods Directory where VCL modules are to be found. -waiter +vsl_buffer + - Units: bytes + - Default: 4k + + Bytes of (req-/backend-)workspace dedicated to buffering VSL records. + At a bare minimum, this must be longer than the longest HTTP header to be logged. + Setting this too high costs memory, setting it too low will cause more VSL flushes and likely increase lock-contention on the VSL mutex. + Minimum is 1k bytes. + +vsl_mask - Default: default - - Flags: must_restart, experimental + + Mask individual VSL messages from being logged. + default Set default value + Use +/- prefixe in front of VSL tag name, to mask/unmask individual VSL messages. + +vsl_space + - Units: bytes + - Default: 80M + - Flags: must_restart + + The amount of space to allocate for the VSL fifo buffer in the VSM memory segment. If you make this too small, varnish{ncsa|log} etc will not be able to keep up. Making it too large just costs memory resources. + +vsm_space + - Units: bytes + - Default: 1M + - Flags: must_restart + + The amount of space to allocate for stats counters in the VSM memory segment. If you make this too small, some counters will be invisible. Making it too large just costs memory resources. + +waiter + - Default: platform dependent + - Flags: must_restart, wizard Select the waiter kernel interface. +workspace_backend + - Units: bytes + - Default: 64k + - Flags: delayed + + Bytes of HTTP protocol workspace for backend HTTP req/resp. If larger than 4k, use a multiple of 4k for VM efficiency. + +workspace_client + - Units: bytes + - Default: 64k + - Flags: delayed + + Bytes of HTTP protocol workspace for clients HTTP req/resp. If larger than 4k, use a multiple of 4k for VM efficiency. + +workspace_thread + - Units: bytes + - Default: 2048 + - Flags: delayed + + Bytes of auxillary workspace per thread. + This workspace is used for certain temporary data structures during the operation of a worker thread. + One use is for the io-vectors for writing requests and responses to sockets, having too little space will result in more writev(2) system calls, having too much just wastes the space. From tfheen at varnish-cache.org Mon Mar 11 07:59:55 2013 From: tfheen at varnish-cache.org (Tollef Fog Heen) Date: Mon, 11 Mar 2013 08:59:55 +0100 Subject: [master] 4429629 Fix rst generation to avoid whitespace error Message-ID: commit 4429629ec76929dba23167fbdaada97301c511de Author: Tollef Fog Heen Date: Mon Mar 11 08:59:38 2013 +0100 Fix rst generation to avoid whitespace error diff --git a/bin/varnishd/mgt/mgt_param.c b/bin/varnishd/mgt/mgt_param.c index af4a982..e2af69b 100644 --- a/bin/varnishd/mgt/mgt_param.c +++ b/bin/varnishd/mgt/mgt_param.c @@ -977,5 +977,4 @@ MCF_DumpRstParam(void) } printf("\n\n"); } - printf("\n"); } From phk at varnish-cache.org Mon Mar 11 11:07:05 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Mon, 11 Mar 2013 12:07:05 +0100 Subject: [master] c9e3914 Abstract some "manage list of backends" code which most of the directors will need. Message-ID: commit c9e3914a79bf3f787b735e365085a348a8be60b2 Author: Poul-Henning Kamp Date: Mon Mar 11 11:06:34 2013 +0000 Abstract some "manage list of backends" code which most of the directors will need. diff --git a/lib/libvmod_directors/Makefile.am b/lib/libvmod_directors/Makefile.am index bc230a5..341c223 100644 --- a/lib/libvmod_directors/Makefile.am +++ b/lib/libvmod_directors/Makefile.am @@ -14,6 +14,7 @@ noinst_LTLIBRARIES = libvmod_directors.la libvmod_directors_la_LDFLAGS = $(AM_LDFLAGS) -module -export-dynamic -avoid-version -shared -rpath /nowhere libvmod_directors_la_SOURCES = \ + vdir.c \ round_robin.c nodist_libvmod_directors_la_SOURCES = \ diff --git a/lib/libvmod_directors/round_robin.c b/lib/libvmod_directors/round_robin.c index 9339046..240bcb7 100644 --- a/lib/libvmod_directors/round_robin.c +++ b/lib/libvmod_directors/round_robin.c @@ -36,61 +36,45 @@ #include "vrt.h" #include "vcc_if.h" -struct rr_entry { - unsigned magic; -#define RR_ENTRY_MAGIC 0xa80970cf - VTAILQ_ENTRY(rr_entry) list; - VCL_BACKEND be; -}; +#include "vdir.h" struct vmod_directors_round_robin { unsigned magic; -#define VMOD_DEBUG_RR_MAGIC 0x99f4b726 - VTAILQ_HEAD(, rr_entry) listhead; - int nbe; - pthread_mutex_t mtx; - struct director *dir; +#define VMOD_DIRECTORS_ROUND_ROBIN_MAGIC 0xa80970cf + struct vdir *vd; + unsigned nxt; }; -static unsigned +static unsigned __match_proto__(vdi_healthy) vmod_rr_healthy(const struct director *dir, const struct req *req) { - struct rr_entry *ep; struct vmod_directors_round_robin *rr; - unsigned retval = 0; - CAST_OBJ_NOTNULL(rr, dir->priv, VMOD_DEBUG_RR_MAGIC); - AZ(pthread_mutex_lock(&rr->mtx)); - VTAILQ_FOREACH(ep, &rr->listhead, list) { - if (ep->be->healthy(ep->be, req)) { - retval = 1; - break; - } - } - AZ(pthread_mutex_unlock(&rr->mtx)); - return (retval); + CAST_OBJ_NOTNULL(rr, dir->priv, VMOD_DIRECTORS_ROUND_ROBIN_MAGIC); + return (vdir_any_healthy(rr->vd, req)); } -static struct vbc * +static struct vbc * __match_proto__(vdi_getfd_f) vmod_rr_getfd(const struct director *dir, struct req *req) { - struct rr_entry *ep = NULL; struct vmod_directors_round_robin *rr; - int i; - - CAST_OBJ_NOTNULL(rr, dir->priv, VMOD_DEBUG_RR_MAGIC); - AZ(pthread_mutex_lock(&rr->mtx)); - for (i = 0; i < rr->nbe; i++) { - ep = VTAILQ_FIRST(&rr->listhead); - VTAILQ_REMOVE(&rr->listhead, ep, list); - VTAILQ_INSERT_TAIL(&rr->listhead, ep, list); - if (ep->be->healthy(ep->be, req)) + unsigned u; + VCL_BACKEND be = NULL; + + CAST_OBJ_NOTNULL(rr, dir->priv, VMOD_DIRECTORS_ROUND_ROBIN_MAGIC); + vdir_lock(rr->vd); + for (u = 0; u < rr->vd->n_backend; u++) { + rr->nxt %= rr->vd->n_backend; + be = rr->vd->backend[rr->nxt]; + rr->nxt++; + CHECK_OBJ_NOTNULL(be, DIRECTOR_MAGIC); + if (be->healthy(be, req)) break; } - AZ(pthread_mutex_unlock(&rr->mtx)); - if (i == rr->nbe || ep == NULL) + vdir_unlock(rr->vd); + if (u == rr->vd->n_backend || be == NULL) return (NULL); - return (ep->be->getfd(ep->be, req)); + return (be->getfd(be, req)); } VCL_VOID @@ -99,65 +83,42 @@ vmod_round_robin__init(struct req *req, struct vmod_directors_round_robin **rrp, { struct vmod_directors_round_robin *rr; - (void)req; - + AZ(req); AN(rrp); AZ(*rrp); - ALLOC_OBJ(rr, VMOD_DEBUG_RR_MAGIC); + ALLOC_OBJ(rr, VMOD_DIRECTORS_ROUND_ROBIN_MAGIC); AN(rr); *rrp = rr; - AZ(pthread_mutex_init(&rr->mtx, NULL)); - VTAILQ_INIT(&rr->listhead); - ALLOC_OBJ(rr->dir, DIRECTOR_MAGIC); - AN(rr->dir); - REPLACE(rr->dir->vcl_name, vcl_name); - rr->dir->priv = rr; - rr->dir->healthy = vmod_rr_healthy; - rr->dir->getfd = vmod_rr_getfd; + vdir_new(&rr->vd, vcl_name, vmod_rr_healthy, vmod_rr_getfd, rr); } VCL_VOID vmod_round_robin__fini(struct req *req, struct vmod_directors_round_robin **rrp) { struct vmod_directors_round_robin *rr; - struct rr_entry *ep; - - (void)req; + AZ(req); rr = *rrp; *rrp = NULL; - CHECK_OBJ_NOTNULL(rr, VMOD_DEBUG_RR_MAGIC); - - AZ(pthread_mutex_destroy(&rr->mtx)); - while (!VTAILQ_EMPTY(&rr->listhead)) { - ep = VTAILQ_FIRST(&rr->listhead); - VTAILQ_REMOVE(&rr->listhead, ep, list); - FREE_OBJ(ep); - } - free(rr->dir->vcl_name); - FREE_OBJ(rr->dir); + CHECK_OBJ_NOTNULL(rr, VMOD_DIRECTORS_ROUND_ROBIN_MAGIC); + vdir_delete(&rr->vd); FREE_OBJ(rr); } VCL_VOID -vmod_round_robin_add_backend(struct req *req, struct vmod_directors_round_robin * rr, - VCL_BACKEND be) +vmod_round_robin_add_backend(struct req *req, + struct vmod_directors_round_robin *rr, VCL_BACKEND be) { - struct rr_entry *ep; - (void)req; - ALLOC_OBJ(ep, RR_ENTRY_MAGIC); - AN(ep); - ep->be = be; - AZ(pthread_mutex_lock(&rr->mtx)); - VTAILQ_INSERT_TAIL(&rr->listhead, ep, list); - rr->nbe++; - AZ(pthread_mutex_unlock(&rr->mtx)); + (void)req; + CHECK_OBJ_NOTNULL(rr, VMOD_DIRECTORS_ROUND_ROBIN_MAGIC); + vdir_add_backend(rr->vd, be, 0.0); } VCL_BACKEND __match_proto__() vmod_round_robin_backend(struct req *req, struct vmod_directors_round_robin *rr) { (void)req; - return (rr->dir); + CHECK_OBJ_NOTNULL(rr, VMOD_DIRECTORS_ROUND_ROBIN_MAGIC); + return (rr->vd->dir); } diff --git a/lib/libvmod_directors/vdir.c b/lib/libvmod_directors/vdir.c new file mode 100644 index 0000000..be8f340 --- /dev/null +++ b/lib/libvmod_directors/vdir.c @@ -0,0 +1,144 @@ +/*- + * Copyright (c) 2013 Varnish Software AS + * All rights reserved. + * + * Author: Poul-Henning Kamp + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "config.h" + +#include + +#include "cache/cache.h" +#include "cache/cache_backend.h" + +#include "vrt.h" + +#include "vdir.h" + +static void +vdir_expand(struct vdir *vd, unsigned n) +{ + CHECK_OBJ_NOTNULL(vd, VDIR_MAGIC); + + vd->backend = realloc(vd->backend, n * sizeof *vd->backend); + AN(vd->backend); + vd->weight = realloc(vd->weight, n * sizeof *vd->weight); + AN(vd->weight); + vd->l_backend = n; +} + +void +vdir_new(struct vdir **vdp, const char *vcl_name, vdi_healthy *healthy, + vdi_getfd_f *getfd, void *priv) +{ + struct vdir *vd; + + AN(vcl_name); + AN(vdp); + AZ(*vdp); + ALLOC_OBJ(vd, VDIR_MAGIC); + AN(vd); + *vdp = vd; + AZ(pthread_mutex_init(&vd->mtx, NULL)); + + ALLOC_OBJ(vd->dir, DIRECTOR_MAGIC); + AN(vd->dir); + REPLACE(vd->dir->vcl_name, vcl_name); + vd->dir->priv = priv; + vd->dir->healthy = healthy; + vd->dir->getfd = getfd; +} + +void +vdir_delete(struct vdir **vdp) +{ + struct vdir *vd; + + AN(vdp); + vd = *vdp; + *vdp = NULL; + + CHECK_OBJ_NOTNULL(vd, VDIR_MAGIC); + + free(vd->backend); + free(vd->weight); + AZ(pthread_mutex_destroy(&vd->mtx)); + FREE_OBJ(vd->dir); + FREE_OBJ(vd); +} + +void +vdir_lock(struct vdir *vd) +{ + CHECK_OBJ_NOTNULL(vd, VDIR_MAGIC); + AZ(pthread_mutex_lock(&vd->mtx)); +} + +void +vdir_unlock(struct vdir *vd) +{ + CHECK_OBJ_NOTNULL(vd, VDIR_MAGIC); + AZ(pthread_mutex_unlock(&vd->mtx)); +} + + +unsigned +vdir_add_backend(struct vdir *vd, VCL_BACKEND be, double weight) +{ + unsigned u; + + CHECK_OBJ_NOTNULL(vd, VDIR_MAGIC); + AN(be); + vdir_lock(vd); + if (vd->n_backend >= vd->l_backend) + vdir_expand(vd, vd->l_backend + 16); + assert(vd->n_backend < vd->l_backend); + u = vd->n_backend++; + vd->backend[u] = be; + vd->weight[u] = weight; + vdir_unlock(vd); + return (u); +} + +unsigned +vdir_any_healthy(struct vdir *vd, const struct req *req) +{ + unsigned retval = 0; + VCL_BACKEND be; + unsigned u; + + CHECK_OBJ_NOTNULL(vd, VDIR_MAGIC); + vdir_lock(vd); + for (u = 0; u < vd->n_backend; u++) { + be = vd->backend[u]; + CHECK_OBJ_NOTNULL(be, DIRECTOR_MAGIC); + if (be->healthy(be, req)) { + retval = 1; + break; + } + } + vdir_unlock(vd); + return (retval); +} diff --git a/lib/libvmod_directors/vdir.h b/lib/libvmod_directors/vdir.h new file mode 100644 index 0000000..1b588b4 --- /dev/null +++ b/lib/libvmod_directors/vdir.h @@ -0,0 +1,46 @@ +/*- + * Copyright (c) 2013 Varnish Software AS + * All rights reserved. + * + * Author: Poul-Henning Kamp + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +struct vdir { + unsigned magic; +#define VDIR_MAGIC 0x99f4b726 + pthread_mutex_t mtx; + unsigned n_backend; + unsigned l_backend; + VCL_BACKEND *backend; + double *weight; + struct director *dir; +}; + +void vdir_new(struct vdir **vdp, const char *vcl_name, vdi_healthy *healthy, + vdi_getfd_f *getfd, void *priv); +void vdir_delete(struct vdir **vdp); +void vdir_lock(struct vdir *vd); +void vdir_unlock(struct vdir *vd); +unsigned vdir_add_backend(struct vdir *vd, VCL_BACKEND be, double weight); +unsigned vdir_any_healthy(struct vdir *vd, const struct req *); From tfheen at varnish-cache.org Mon Mar 11 11:14:45 2013 From: tfheen at varnish-cache.org (Tollef Fog Heen) Date: Mon, 11 Mar 2013 12:14:45 +0100 Subject: [master] cb3e952 Treat error as miss + error in %{Varnish:handling}x format Message-ID: commit cb3e952b4346e34dbf425b67ca667928d927c59b Author: Tollef Fog Heen Date: Mon Mar 11 12:13:56 2013 +0100 Treat error as miss + error in %{Varnish:handling}x format Fixes #1273 diff --git a/bin/varnishncsa/varnishncsa.c b/bin/varnishncsa/varnishncsa.c index 309019d..0b039b6 100644 --- a/bin/varnishncsa/varnishncsa.c +++ b/bin/varnishncsa/varnishncsa.c @@ -521,6 +521,11 @@ collect_client(struct logline *lp, enum VSL_tag_e tag, unsigned spec, } else if (strncmp(ptr, "pass", len) == 0) { lp->df_hitmiss = "miss"; lp->df_handling = "pass"; + } else if (strncmp(ptr, "error", len) == 0) { + /* Arguably, error isn't a hit or a miss, but + miss is less wrong */ + lp->df_hitmiss = "miss"; + lp->df_handling = "error"; } else if (strncmp(ptr, "pipe", len) == 0) { /* Just skip piped requests, since we can't * print their status code */ From tfheen at varnish-cache.org Mon Mar 11 11:16:18 2013 From: tfheen at varnish-cache.org (Tollef Fog Heen) Date: Mon, 11 Mar 2013 12:16:18 +0100 Subject: [master] ed1836b Add vdir.h to SOURCES Message-ID: commit ed1836b80970d2c1346b536d9910c53ef19faf77 Author: Tollef Fog Heen Date: Mon Mar 11 12:16:16 2013 +0100 Add vdir.h to SOURCES diff --git a/lib/libvmod_directors/Makefile.am b/lib/libvmod_directors/Makefile.am index 341c223..971885a 100644 --- a/lib/libvmod_directors/Makefile.am +++ b/lib/libvmod_directors/Makefile.am @@ -15,6 +15,7 @@ libvmod_directors_la_LDFLAGS = $(AM_LDFLAGS) -module -export-dynamic -avoid-vers libvmod_directors_la_SOURCES = \ vdir.c \ + vdir.h \ round_robin.c nodist_libvmod_directors_la_SOURCES = \ From phk at varnish-cache.org Mon Mar 11 11:47:05 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Mon, 11 Mar 2013 12:47:05 +0100 Subject: [master] 1ccba69 Move also the fall-back director to the VMOD Message-ID: commit 1ccba69ce528d5923b0c4fb62fd38412e9332bb1 Author: Poul-Henning Kamp Date: Mon Mar 11 11:46:49 2013 +0000 Move also the fall-back director to the VMOD diff --git a/bin/varnishtest/tests/b00016.vtc b/bin/varnishtest/tests/b00016.vtc index db68663..17e38f4 100644 --- a/bin/varnishtest/tests/b00016.vtc +++ b/bin/varnishtest/tests/b00016.vtc @@ -46,13 +46,17 @@ client c1 { } -run varnish v1 -vcl { - director baz round-robin { - { .backend = { - .host = "${bad_ip}"; .port = "9080"; - } } + import directors from "${topbuild}/lib/libvmod_directors/.libs/libvmod_directors.so" ; + backend b1 { + .host = "${bad_ip}"; .port = "9080"; + } + sub vcl_init { + new baz = directors.round_robin(); + baz.add_backend(b1); } sub vcl_recv { + set req.backend = baz.backend(); error 200 "ok"; } diff --git a/bin/varnishtest/tests/v00009.vtc b/bin/varnishtest/tests/v00009.vtc index 5a5d769..53e569b 100644 --- a/bin/varnishtest/tests/v00009.vtc +++ b/bin/varnishtest/tests/v00009.vtc @@ -23,15 +23,18 @@ server s4 { varnish v1 -vcl+backend { - director batman round-robin { - { .backend = s1; } - { .backend = s2; } - { .backend = s3; } - { .backend = s4; } + import directors from "${topbuild}/lib/libvmod_directors/.libs/libvmod_directors.so" ; + + sub vcl_init { + new batman = directors.round_robin(); + batman.add_backend(s1); + batman.add_backend(s2); + batman.add_backend(s3); + batman.add_backend(s4); } sub vcl_recv { - set req.backend = batman; + set req.backend = batman.backend(); } } -start diff --git a/bin/varnishtest/tests/v00036.vtc b/bin/varnishtest/tests/v00036.vtc index 323f80c..d38498c 100644 --- a/bin/varnishtest/tests/v00036.vtc +++ b/bin/varnishtest/tests/v00036.vtc @@ -15,32 +15,25 @@ server s3 { txresp -hdr "Foo: 3" } -start -varnish v1 -vcl { - backend b1 { - .host = "${s1_addr}"; - .port = "${s1_port}"; - } - backend b2 { - .host = "${s2_addr}"; - .port = "${s2_port}"; - } - backend b3 { - .host = "${s3_addr}"; - .port = "${s3_port}"; - } - director f1 fallback { - { .backend = b1; } - { .backend = b2; } - { .backend = b3; } - } +varnish v1 -vcl+backend { + import directors from "${topbuild}/lib/libvmod_directors/.libs/libvmod_directors.so" ; + + sub vcl_init { + new fb1 = directors.fall_back(); + fb1.add_backend(s1); + fb1.add_backend(s2); + fb1.add_backend(s3); + } + sub vcl_recv { - set req.backend = f1; + set req.backend = fb1.backend(); return (pass); } + } -start -varnish v1 -cliok "backend.set_health b1 sick" -varnish v1 -cliok "backend.set_health b2 sick" +varnish v1 -cliok "backend.set_health s1 sick" +varnish v1 -cliok "backend.set_health s2 sick" client c1 { # s1 & s2 are both sick, expect response from s3 @@ -49,7 +42,7 @@ client c1 { expect resp.http.foo == "3" } -run -varnish v1 -cliok "backend.set_health b2 healthy" +varnish v1 -cliok "backend.set_health s2 healthy" client c1 { txreq @@ -57,7 +50,7 @@ client c1 { expect resp.http.foo == "2" } -run -varnish v1 -cliok "backend.set_health b1 healthy" +varnish v1 -cliok "backend.set_health s1 healthy" client c1 { txreq diff --git a/lib/libvmod_directors/Makefile.am b/lib/libvmod_directors/Makefile.am index 971885a..e28ba46 100644 --- a/lib/libvmod_directors/Makefile.am +++ b/lib/libvmod_directors/Makefile.am @@ -16,6 +16,7 @@ libvmod_directors_la_LDFLAGS = $(AM_LDFLAGS) -module -export-dynamic -avoid-vers libvmod_directors_la_SOURCES = \ vdir.c \ vdir.h \ + fall_back.c \ round_robin.c nodist_libvmod_directors_la_SOURCES = \ diff --git a/lib/libvmod_directors/fall_back.c b/lib/libvmod_directors/fall_back.c new file mode 100644 index 0000000..64b53fe --- /dev/null +++ b/lib/libvmod_directors/fall_back.c @@ -0,0 +1,121 @@ +/*- + * Copyright (c) 2013 Varnish Software AS + * All rights reserved. + * + * Author: Poul-Henning Kamp + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "config.h" + +#include + +#include "cache/cache.h" +#include "cache/cache_backend.h" + +#include "vrt.h" +#include "vcc_if.h" + +#include "vdir.h" + +struct vmod_directors_fall_back { + unsigned magic; +#define VMOD_DIRECTORS_FALL_BACK_MAGIC 0xad4e26ba + struct vdir *vd; +}; + +static unsigned __match_proto__(vdi_healthy) +vmod_rr_healthy(const struct director *dir, const struct req *req) +{ + struct vmod_directors_fall_back *rr; + + CAST_OBJ_NOTNULL(rr, dir->priv, VMOD_DIRECTORS_FALL_BACK_MAGIC); + return (vdir_any_healthy(rr->vd, req)); +} + +static struct vbc * __match_proto__(vdi_getfd_f) +vmod_rr_getfd(const struct director *dir, struct req *req) +{ + struct vmod_directors_fall_back *rr; + unsigned u; + VCL_BACKEND be = NULL; + + CAST_OBJ_NOTNULL(rr, dir->priv, VMOD_DIRECTORS_FALL_BACK_MAGIC); + vdir_lock(rr->vd); + for (u = 0; u < rr->vd->n_backend; u++) { + be = rr->vd->backend[u]; + CHECK_OBJ_NOTNULL(be, DIRECTOR_MAGIC); + if (be->healthy(be, req)) + break; + } + vdir_unlock(rr->vd); + if (u == rr->vd->n_backend || be == NULL) + return (NULL); + return (be->getfd(be, req)); +} + +VCL_VOID __match_proto__() +vmod_fall_back__init(struct req *req, struct vmod_directors_fall_back **rrp, + const char *vcl_name) +{ + struct vmod_directors_fall_back *rr; + + AZ(req); + AN(rrp); + AZ(*rrp); + ALLOC_OBJ(rr, VMOD_DIRECTORS_FALL_BACK_MAGIC); + AN(rr); + *rrp = rr; + vdir_new(&rr->vd, vcl_name, vmod_rr_healthy, vmod_rr_getfd, rr); +} + +VCL_VOID __match_proto__() +vmod_fall_back__fini(struct req *req, struct vmod_directors_fall_back **rrp) +{ + struct vmod_directors_fall_back *rr; + + AZ(req); + rr = *rrp; + *rrp = NULL; + CHECK_OBJ_NOTNULL(rr, VMOD_DIRECTORS_FALL_BACK_MAGIC); + vdir_delete(&rr->vd); + FREE_OBJ(rr); +} + +VCL_VOID __match_proto__() +vmod_fall_back_add_backend(struct req *req, + struct vmod_directors_fall_back *rr, VCL_BACKEND be) +{ + + (void)req; + CHECK_OBJ_NOTNULL(rr, VMOD_DIRECTORS_FALL_BACK_MAGIC); + (void)vdir_add_backend(rr->vd, be, 0.0); +} + +VCL_BACKEND __match_proto__() +vmod_fall_back_backend(struct req *req, struct vmod_directors_fall_back *rr) +{ + (void)req; + CHECK_OBJ_NOTNULL(rr, VMOD_DIRECTORS_FALL_BACK_MAGIC); + return (rr->vd->dir); +} diff --git a/lib/libvmod_directors/round_robin.c b/lib/libvmod_directors/round_robin.c index 240bcb7..98df225 100644 --- a/lib/libvmod_directors/round_robin.c +++ b/lib/libvmod_directors/round_robin.c @@ -77,7 +77,7 @@ vmod_rr_getfd(const struct director *dir, struct req *req) return (be->getfd(be, req)); } -VCL_VOID +VCL_VOID __match_proto__() vmod_round_robin__init(struct req *req, struct vmod_directors_round_robin **rrp, const char *vcl_name) { @@ -92,7 +92,7 @@ vmod_round_robin__init(struct req *req, struct vmod_directors_round_robin **rrp, vdir_new(&rr->vd, vcl_name, vmod_rr_healthy, vmod_rr_getfd, rr); } -VCL_VOID +VCL_VOID __match_proto__() vmod_round_robin__fini(struct req *req, struct vmod_directors_round_robin **rrp) { struct vmod_directors_round_robin *rr; @@ -105,14 +105,14 @@ vmod_round_robin__fini(struct req *req, struct vmod_directors_round_robin **rrp) FREE_OBJ(rr); } -VCL_VOID +VCL_VOID __match_proto__() vmod_round_robin_add_backend(struct req *req, struct vmod_directors_round_robin *rr, VCL_BACKEND be) { (void)req; CHECK_OBJ_NOTNULL(rr, VMOD_DIRECTORS_ROUND_ROBIN_MAGIC); - vdir_add_backend(rr->vd, be, 0.0); + (void)vdir_add_backend(rr->vd, be, 0.0); } VCL_BACKEND __match_proto__() diff --git a/lib/libvmod_directors/vmod.vcc b/lib/libvmod_directors/vmod.vcc index 0cf0251..df85fc8 100644 --- a/lib/libvmod_directors/vmod.vcc +++ b/lib/libvmod_directors/vmod.vcc @@ -31,3 +31,8 @@ Object round_robin() { Method VOID .add_backend(BACKEND) Method BACKEND .backend() } + +Object fall_back() { + Method VOID .add_backend(BACKEND) + Method BACKEND .backend() +} From phk at varnish-cache.org Mon Mar 11 12:12:33 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Mon, 11 Mar 2013 13:12:33 +0100 Subject: [master] e810830 Fallback is spelled without an hyphen. Message-ID: commit e810830a3cef2b7166cec58310a47b617b96c260 Author: Poul-Henning Kamp Date: Mon Mar 11 12:12:21 2013 +0000 Fallback is spelled without an hyphen. diff --git a/bin/varnishtest/tests/r01091.vtc b/bin/varnishtest/tests/r01091.vtc index 9234ffc..ae94ca8 100644 --- a/bin/varnishtest/tests/r01091.vtc +++ b/bin/varnishtest/tests/r01091.vtc @@ -14,12 +14,16 @@ server s2 { } -start varnish v1 -vcl+backend { - director f1 fallback { - { .backend = s1; } - { .backend = s2; } - } + import directors from "${topbuild}/lib/libvmod_directors/.libs/libvmod_directors.so" ; + + sub vcl_init { + new f1 = directors.fallback(); + f1.add_backend(s1); + f1.add_backend(s2); + } + sub vcl_recv { - set req.backend = f1; + set req.backend = f1.backend(); } sub vcl_fetch { if(req.restarts < 1) { diff --git a/bin/varnishtest/tests/v00036.vtc b/bin/varnishtest/tests/v00036.vtc index d38498c..6bf1f1b 100644 --- a/bin/varnishtest/tests/v00036.vtc +++ b/bin/varnishtest/tests/v00036.vtc @@ -19,7 +19,7 @@ varnish v1 -vcl+backend { import directors from "${topbuild}/lib/libvmod_directors/.libs/libvmod_directors.so" ; sub vcl_init { - new fb1 = directors.fall_back(); + new fb1 = directors.fallback(); fb1.add_backend(s1); fb1.add_backend(s2); fb1.add_backend(s3); diff --git a/lib/libvmod_directors/fall_back.c b/lib/libvmod_directors/fall_back.c index 64b53fe..76cfb4e 100644 --- a/lib/libvmod_directors/fall_back.c +++ b/lib/libvmod_directors/fall_back.c @@ -38,29 +38,29 @@ #include "vdir.h" -struct vmod_directors_fall_back { +struct vmod_directors_fallback { unsigned magic; -#define VMOD_DIRECTORS_FALL_BACK_MAGIC 0xad4e26ba +#define VMOD_DIRECTORS_FALLBACK_MAGIC 0xad4e26ba struct vdir *vd; }; static unsigned __match_proto__(vdi_healthy) vmod_rr_healthy(const struct director *dir, const struct req *req) { - struct vmod_directors_fall_back *rr; + struct vmod_directors_fallback *rr; - CAST_OBJ_NOTNULL(rr, dir->priv, VMOD_DIRECTORS_FALL_BACK_MAGIC); + CAST_OBJ_NOTNULL(rr, dir->priv, VMOD_DIRECTORS_FALLBACK_MAGIC); return (vdir_any_healthy(rr->vd, req)); } static struct vbc * __match_proto__(vdi_getfd_f) vmod_rr_getfd(const struct director *dir, struct req *req) { - struct vmod_directors_fall_back *rr; + struct vmod_directors_fallback *rr; unsigned u; VCL_BACKEND be = NULL; - CAST_OBJ_NOTNULL(rr, dir->priv, VMOD_DIRECTORS_FALL_BACK_MAGIC); + CAST_OBJ_NOTNULL(rr, dir->priv, VMOD_DIRECTORS_FALLBACK_MAGIC); vdir_lock(rr->vd); for (u = 0; u < rr->vd->n_backend; u++) { be = rr->vd->backend[u]; @@ -75,47 +75,47 @@ vmod_rr_getfd(const struct director *dir, struct req *req) } VCL_VOID __match_proto__() -vmod_fall_back__init(struct req *req, struct vmod_directors_fall_back **rrp, +vmod_fallback__init(struct req *req, struct vmod_directors_fallback **rrp, const char *vcl_name) { - struct vmod_directors_fall_back *rr; + struct vmod_directors_fallback *rr; AZ(req); AN(rrp); AZ(*rrp); - ALLOC_OBJ(rr, VMOD_DIRECTORS_FALL_BACK_MAGIC); + ALLOC_OBJ(rr, VMOD_DIRECTORS_FALLBACK_MAGIC); AN(rr); *rrp = rr; vdir_new(&rr->vd, vcl_name, vmod_rr_healthy, vmod_rr_getfd, rr); } VCL_VOID __match_proto__() -vmod_fall_back__fini(struct req *req, struct vmod_directors_fall_back **rrp) +vmod_fallback__fini(struct req *req, struct vmod_directors_fallback **rrp) { - struct vmod_directors_fall_back *rr; + struct vmod_directors_fallback *rr; AZ(req); rr = *rrp; *rrp = NULL; - CHECK_OBJ_NOTNULL(rr, VMOD_DIRECTORS_FALL_BACK_MAGIC); + CHECK_OBJ_NOTNULL(rr, VMOD_DIRECTORS_FALLBACK_MAGIC); vdir_delete(&rr->vd); FREE_OBJ(rr); } VCL_VOID __match_proto__() -vmod_fall_back_add_backend(struct req *req, - struct vmod_directors_fall_back *rr, VCL_BACKEND be) +vmod_fallback_add_backend(struct req *req, + struct vmod_directors_fallback *rr, VCL_BACKEND be) { (void)req; - CHECK_OBJ_NOTNULL(rr, VMOD_DIRECTORS_FALL_BACK_MAGIC); + CHECK_OBJ_NOTNULL(rr, VMOD_DIRECTORS_FALLBACK_MAGIC); (void)vdir_add_backend(rr->vd, be, 0.0); } VCL_BACKEND __match_proto__() -vmod_fall_back_backend(struct req *req, struct vmod_directors_fall_back *rr) +vmod_fallback_backend(struct req *req, struct vmod_directors_fallback *rr) { (void)req; - CHECK_OBJ_NOTNULL(rr, VMOD_DIRECTORS_FALL_BACK_MAGIC); + CHECK_OBJ_NOTNULL(rr, VMOD_DIRECTORS_FALLBACK_MAGIC); return (rr->vd->dir); } diff --git a/lib/libvmod_directors/vmod.vcc b/lib/libvmod_directors/vmod.vcc index df85fc8..2945559 100644 --- a/lib/libvmod_directors/vmod.vcc +++ b/lib/libvmod_directors/vmod.vcc @@ -32,7 +32,7 @@ Object round_robin() { Method BACKEND .backend() } -Object fall_back() { +Object fallback() { Method VOID .add_backend(BACKEND) Method BACKEND .backend() } From phk at varnish-cache.org Mon Mar 11 12:21:53 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Mon, 11 Mar 2013 13:21:53 +0100 Subject: [master] 17f2e93 Remove the VCC generated round-robin and fallback directors, these now live in VMOD.directors (and can be stacked :-) Message-ID: commit 17f2e93821167ca590f2b39d0cfbb57871198c8e Author: Poul-Henning Kamp Date: Mon Mar 11 12:21:18 2013 +0000 Remove the VCC generated round-robin and fallback directors, these now live in VMOD.directors (and can be stacked :-) diff --git a/bin/varnishd/Makefile.am b/bin/varnishd/Makefile.am index 0165696..378ce55 100644 --- a/bin/varnishd/Makefile.am +++ b/bin/varnishd/Makefile.am @@ -21,7 +21,6 @@ varnishd_SOURCES = \ cache/cache_dir.c \ cache/cache_dir_dns.c \ cache/cache_dir_random.c \ - cache/cache_dir_round_robin.c \ cache/cache_esi_deliver.c \ cache/cache_esi_fetch.c \ cache/cache_esi_parse.c \ diff --git a/bin/varnishd/cache/cache_backend.h b/bin/varnishd/cache/cache_backend.h index fb88308..b1e8d89 100644 --- a/bin/varnishd/cache/cache_backend.h +++ b/bin/varnishd/cache/cache_backend.h @@ -187,6 +187,4 @@ dir_init_f VRT_init_dir_simple; dir_init_f VRT_init_dir_dns; dir_init_f VRT_init_dir_hash; dir_init_f VRT_init_dir_random; -dir_init_f VRT_init_dir_round_robin; -dir_init_f VRT_init_dir_fallback; dir_init_f VRT_init_dir_client; diff --git a/bin/varnishd/cache/cache_backend_cfg.c b/bin/varnishd/cache/cache_backend_cfg.c index 3f15ada..2cda875 100644 --- a/bin/varnishd/cache/cache_backend_cfg.c +++ b/bin/varnishd/cache/cache_backend_cfg.c @@ -257,10 +257,6 @@ VRT_init_dir(struct cli *cli, struct director **dir, const char *name, VRT_init_dir_random(cli, dir, idx, priv); else if (!strcmp(name, "dns")) VRT_init_dir_dns(cli, dir, idx, priv); - else if (!strcmp(name, "round-robin")) - VRT_init_dir_round_robin(cli, dir, idx, priv); - else if (!strcmp(name, "fallback")) - VRT_init_dir_fallback(cli, dir, idx, priv); else if (!strcmp(name, "client")) VRT_init_dir_client(cli, dir, idx, priv); else diff --git a/bin/varnishd/cache/cache_dir_round_robin.c b/bin/varnishd/cache/cache_dir_round_robin.c deleted file mode 100644 index b3a57f2..0000000 --- a/bin/varnishd/cache/cache_dir_round_robin.c +++ /dev/null @@ -1,175 +0,0 @@ -/*- - * Copyright (c) 2008-2011 Varnish Software AS - * All rights reserved. - * - * Author: Petter Knudsen - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -#include "config.h" - -#include - -#include "cache.h" - -#include "cache_backend.h" -#include "vrt.h" - -/*--------------------------------------------------------------------*/ - -struct vdi_round_robin_host { - struct director *backend; -}; - -enum mode_e { m_round_robin, m_fallback }; - -struct vdi_round_robin { - unsigned magic; -#define VDI_ROUND_ROBIN_MAGIC 0x2114a178 - struct director dir; - enum mode_e mode; - struct vdi_round_robin_host *hosts; - unsigned nhosts; - unsigned next_host; -}; - -static struct vbc * -vdi_round_robin_getfd(const struct director *d, struct req *req) -{ - int i; - struct vdi_round_robin *vs; - struct director *backend; - struct vbc *vbe; - - CHECK_OBJ_NOTNULL(req, REQ_MAGIC); - CHECK_OBJ_NOTNULL(d, DIRECTOR_MAGIC); - CAST_OBJ_NOTNULL(vs, d->priv, VDI_ROUND_ROBIN_MAGIC); - - /* - * In fallback mode we ignore the next_host and always grab the - * first healthy backend we can find. - */ - for (i = 0; i < vs->nhosts; i++) { - if (vs->mode == m_round_robin) { - backend = vs->hosts[vs->next_host].backend; - vs->next_host = (vs->next_host + 1) % vs->nhosts; - } else /* m_fallback */ { - backend = vs->hosts[i].backend; - } - if (!VDI_Healthy(backend, req)) - continue; - vbe = VDI_GetFd(backend, req); - if (vbe != NULL) - return (vbe); - } - - return (NULL); -} - -static unsigned -vdi_round_robin_healthy(const struct director *d, const struct req *req) -{ - struct vdi_round_robin *vs; - struct director *backend; - int i; - - CHECK_OBJ_NOTNULL(d, DIRECTOR_MAGIC); - CAST_OBJ_NOTNULL(vs, d->priv, VDI_ROUND_ROBIN_MAGIC); - - for (i = 0; i < vs->nhosts; i++) { - backend = vs->hosts[i].backend; - if (VDI_Healthy(backend, req)) - return (1); - } - return (0); -} - -static void -vdi_round_robin_fini(const struct director *d) -{ - struct vdi_round_robin *vs; - - CHECK_OBJ_NOTNULL(d, DIRECTOR_MAGIC); - CAST_OBJ_NOTNULL(vs, d->priv, VDI_ROUND_ROBIN_MAGIC); - - free(vs->hosts); - free(vs->dir.vcl_name); - vs->dir.magic = 0; - vs->next_host = 0; - FREE_OBJ(vs); -} - -static void -vrt_init_dir(struct cli *cli, struct director **bp, int idx, - const void *priv, enum mode_e mode) -{ - const struct vrt_dir_round_robin *t; - struct vdi_round_robin *vs; - const struct vrt_dir_round_robin_entry *te; - struct vdi_round_robin_host *vh; - int i; - - ASSERT_CLI(); - (void)cli; - t = priv; - - ALLOC_OBJ(vs, VDI_ROUND_ROBIN_MAGIC); - XXXAN(vs); - vs->hosts = calloc(sizeof *vh, t->nmember); - XXXAN(vs->hosts); - - vs->dir.magic = DIRECTOR_MAGIC; - vs->dir.priv = vs; - vs->dir.name = "round_robin"; - REPLACE(vs->dir.vcl_name, t->name); - vs->dir.getfd = vdi_round_robin_getfd; - vs->dir.fini = vdi_round_robin_fini; - vs->dir.healthy = vdi_round_robin_healthy; - - vs->mode = mode; - vh = vs->hosts; - te = t->members; - for (i = 0; i < t->nmember; i++, vh++, te++) { - vh->backend = bp[te->host]; - AN(vh->backend); - } - vs->nhosts = t->nmember; - vs->next_host = 0; - - bp[idx] = &vs->dir; -} - -void -VRT_init_dir_round_robin(struct cli *cli, struct director **bp, int idx, - const void *priv) -{ - vrt_init_dir(cli, bp, idx, priv, m_round_robin); -} - -void -VRT_init_dir_fallback(struct cli *cli, struct director **bp, int idx, - const void *priv) -{ - vrt_init_dir(cli, bp, idx, priv, m_fallback); -} diff --git a/include/vrt.h b/include/vrt.h index a2550aa..228781d 100644 --- a/include/vrt.h +++ b/include/vrt.h @@ -122,20 +122,6 @@ struct vrt_dir_random { }; /* - * A director with round robin selection - */ - -struct vrt_dir_round_robin_entry { - int host; -}; - -struct vrt_dir_round_robin { - const char *name; - unsigned nmember; - const struct vrt_dir_round_robin_entry *members; -}; - -/* * A director with dns-based selection */ diff --git a/lib/libvcl/Makefile.am b/lib/libvcl/Makefile.am index be3efe0..88c8f75 100644 --- a/lib/libvcl/Makefile.am +++ b/lib/libvcl/Makefile.am @@ -18,7 +18,6 @@ libvcl_la_SOURCES = \ vcc_backend_util.c \ vcc_compile.c \ vcc_dir_random.c \ - vcc_dir_round_robin.c \ vcc_dir_dns.c \ vcc_expr.c \ vcc_parse.c \ diff --git a/lib/libvcl/vcc_backend.c b/lib/libvcl/vcc_backend.c index a480edd..47e3280 100644 --- a/lib/libvcl/vcc_backend.c +++ b/lib/libvcl/vcc_backend.c @@ -696,6 +696,7 @@ vcc_ParseSimpleDirector(struct vcc *tl) * Parse directors and backends */ + static const struct dirlist { const char *name; parsedirector_f *func; @@ -703,8 +704,8 @@ static const struct dirlist { { "hash", vcc_ParseRandomDirector }, { "random", vcc_ParseRandomDirector }, { "client", vcc_ParseRandomDirector }, - { "round-robin", vcc_ParseRoundRobinDirector }, - { "fallback", vcc_ParseRoundRobinDirector }, + { "round-robin", NULL }, + { "fallback", NULL }, { "dns", vcc_ParseDnsDirector }, { NULL, NULL } }; @@ -753,6 +754,13 @@ vcc_ParseDirector(struct vcc *tl) vcc_ErrWhere(tl, tl->t_policy); return; } + if (dl->func == NULL) { + VSB_printf(tl->sb, + "\n%.*s director are now in VMOD.directors\n", + PF(tl->t_policy)); + vcc_ErrWhere(tl, tl->t_policy); + return; + } Ff(tl, 0, "\tVRT_fini_dir(cli, VGCDIR(_%.*s));\n", PF(tl->t_dir)); SkipToken(tl, '{'); diff --git a/lib/libvcl/vcc_compile.h b/lib/libvcl/vcc_compile.h index 162fef6..1e51f5f 100644 --- a/lib/libvcl/vcc_compile.h +++ b/lib/libvcl/vcc_compile.h @@ -269,9 +269,6 @@ void EncString(struct vsb *sb, const char *b, const char *e, int mode); /* vcc_dir_random.c */ parsedirector_f vcc_ParseRandomDirector; -/* vcc_dir_round_robin.c */ -parsedirector_f vcc_ParseRoundRobinDirector; - /* vcc_expr.c */ void vcc_Duration(struct vcc *tl, double *); unsigned vcc_UintVal(struct vcc *tl); diff --git a/lib/libvcl/vcc_dir_round_robin.c b/lib/libvcl/vcc_dir_round_robin.c deleted file mode 100644 index 835d969..0000000 --- a/lib/libvcl/vcc_dir_round_robin.c +++ /dev/null @@ -1,91 +0,0 @@ -/*- - * Copyright (c) 2008-2009 Varnish Software AS - * All rights reserved. - * - * Author: Petter Knudsen - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "config.h" - -#include "vcc_compile.h" - -/*-------------------------------------------------------------------- - * Parse directors - */ - -void -vcc_ParseRoundRobinDirector(struct vcc *tl) -{ - struct token *t_field, *t_be; - int nelem; - struct fld_spec *fs; - const char *first; - char *p; - - fs = vcc_FldSpec(tl, "!backend", NULL); - - Fc(tl, 0, "\nstatic const struct vrt_dir_round_robin_entry " - "vdrre_%.*s[] = {\n", PF(tl->t_dir)); - - for (nelem = 0; tl->t->tok != '}'; nelem++) { /* List of members */ - first = ""; - t_be = tl->t; - vcc_ResetFldSpec(fs); - - SkipToken(tl, '{'); - Fc(tl, 0, "\t{"); - - while (tl->t->tok != '}') { /* Member fields */ - vcc_IsField(tl, &t_field, fs); - ERRCHK(tl); - if (vcc_IdIs(t_field, "backend")) { - vcc_ParseBackendHost(tl, nelem, &p); - ERRCHK(tl); - AN(p); - Fc(tl, 0, "%s .host = VGC_backend_%s", - first, p); - } else { - ErrInternal(tl); - } - first = ", "; - } - vcc_FieldsOk(tl, fs); - if (tl->err) { - VSB_printf(tl->sb, - "\nIn member host specification starting at:\n"); - vcc_ErrWhere(tl, t_be); - return; - } - Fc(tl, 0, " },\n"); - vcc_NextToken(tl); - } - Fc(tl, 0, "};\n"); - Fc(tl, 0, - "\nstatic const struct vrt_dir_round_robin vgc_dir_priv_%.*s = {\n", - PF(tl->t_dir)); - Fc(tl, 0, "\t.name = \"%.*s\",\n", PF(tl->t_dir)); - Fc(tl, 0, "\t.nmember = %d,\n", nelem); - Fc(tl, 0, "\t.members = vdrre_%.*s,\n", PF(tl->t_dir)); - Fc(tl, 0, "};\n"); -} From phk at varnish-cache.org Mon Mar 11 12:24:11 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Mon, 11 Mar 2013 13:24:11 +0100 Subject: [master] e707a73 Dependency magic... Message-ID: commit e707a7388ab509bc04bac6a014950e028c00d583 Author: Poul-Henning Kamp Date: Mon Mar 11 12:24:02 2013 +0000 Dependency magic... diff --git a/lib/libvmod_directors/Makefile.am b/lib/libvmod_directors/Makefile.am index e28ba46..2c879c8 100644 --- a/lib/libvmod_directors/Makefile.am +++ b/lib/libvmod_directors/Makefile.am @@ -24,7 +24,7 @@ nodist_libvmod_directors_la_SOURCES = \ vcc_if.h # BUILT_SOURCES is only a hack and dependency tracking does not help for the first build -round_robin.lo: vcc_if.h +vdir.lo: vcc_if.h vcc_if.c vcc_if.h: $(vmodtool) $(vmod_srcdir)/vmod.vcc @PYTHON@ $(vmodtool) $(vmod_srcdir)/vmod.vcc From tfheen at varnish-cache.org Mon Mar 11 13:00:54 2013 From: tfheen at varnish-cache.org (Tollef Fog Heen) Date: Mon, 11 Mar 2013 14:00:54 +0100 Subject: [master] e4072d3 Count number of times we go through vcl_error Message-ID: commit e4072d36821a882bac743b2f6bee132315332311 Author: Tollef Fog Heen Date: Mon Mar 11 13:57:49 2013 +0100 Count number of times we go through vcl_error diff --git a/bin/varnishd/cache/cache_req_fsm.c b/bin/varnishd/cache/cache_req_fsm.c index 3a15f58..b2bdd50 100644 --- a/bin/varnishd/cache/cache_req_fsm.c +++ b/bin/varnishd/cache/cache_req_fsm.c @@ -267,6 +267,7 @@ cnt_error(struct worker *wrk, struct req *req) AZ(req->obj); AZ(req->busyobj); + req->acct_req.error++; bo = VBO_GetBusyObj(wrk, req); req->busyobj = bo; AZ(bo->stats); diff --git a/bin/varnishtest/tests/b00017.vtc b/bin/varnishtest/tests/b00017.vtc index 9edcbc5..85ec39c 100644 --- a/bin/varnishtest/tests/b00017.vtc +++ b/bin/varnishtest/tests/b00017.vtc @@ -15,3 +15,5 @@ client c1 { expect resp.status == 888 expect resp.http.connection == close } -run + +varnish v1 -expect s_error == 1 diff --git a/include/tbl/acct_fields.h b/include/tbl/acct_fields.h index 3dc1ff6..1184240 100644 --- a/include/tbl/acct_fields.h +++ b/include/tbl/acct_fields.h @@ -35,5 +35,6 @@ ACCT(req) ACCT(pipe) ACCT(pass) ACCT(fetch) +ACCT(error) ACCT(hdrbytes) ACCT(bodybytes) diff --git a/include/tbl/vsc_f_main.h b/include/tbl/vsc_f_main.h index f487471..3f6d3fe 100644 --- a/include/tbl/vsc_f_main.h +++ b/include/tbl/vsc_f_main.h @@ -370,6 +370,10 @@ VSC_F(s_fetch, uint64_t, 1, 'a', "Total fetch", "" ) +VSC_F(s_error, uint64_t, 1, 'a', + "Total error", + "" +) VSC_F(s_hdrbytes, uint64_t, 1, 'a', "Total header bytes", "" From tfheen at varnish-cache.org Tue Mar 12 10:17:25 2013 From: tfheen at varnish-cache.org (Tollef Fog Heen) Date: Tue, 12 Mar 2013 11:17:25 +0100 Subject: [master] a5d5ecd Require libedit/readline Message-ID: commit a5d5ecdea86ba6d9dcb036a78f7606c693f42190 Author: Tollef Fog Heen Date: Tue Mar 12 11:15:58 2013 +0100 Require libedit/readline Remove a bunch of ifdef code and fix up proper configure check for libedit. Fixes #1277 diff --git a/bin/varnishadm/varnishadm.c b/bin/varnishadm/varnishadm.c index 08adc79..532ab72 100644 --- a/bin/varnishadm/varnishadm.c +++ b/bin/varnishadm/varnishadm.c @@ -32,25 +32,23 @@ #include #include -#ifdef HAVE_LIBEDIT -# include -# ifdef HAVE_EDIT_READLINE_READLINE_H -# include -# elif HAVE_READLINE_READLINE_H -# include -# ifdef HAVE_READLINE_HISTORY_H -# include -# endif -# else -# include +#include + +#ifdef HAVE_EDIT_READLINE_READLINE_H +# include +#elif HAVE_READLINE_READLINE_H +# include +# ifdef HAVE_READLINE_HISTORY_H +# include # endif +#else +# include #endif #include #include #include #include -#include #include #include #include @@ -61,16 +59,12 @@ #include "vcli.h" #include "vss.h" -#ifdef HAVE_LIBEDIT #define RL_EXIT(status) \ do { \ rl_callback_handler_remove(); \ exit(status); \ } while (0) -#else -#define RL_EXIT(status) exit(status) -#endif static double timeout = 5; @@ -178,7 +172,6 @@ do_args(int sock, int argc, char * const *argv) exit(1); } -#ifdef HAVE_LIBEDIT /* Callback for readline, doesn't take a private pointer, so we need * to have a global variable. */ @@ -228,7 +221,6 @@ varnishadm_completion (const char *text, int start, int end) matches = rl_completion_matches(text, command_generator); return (matches); } -#endif /* * No arguments given, simply pass bytes on stdin/stdout and CLI socket @@ -242,11 +234,6 @@ pass(int sock) int i; char *answer = NULL; unsigned u, status; -#ifndef HAVE_LIBEDIT - int n; -#endif - -#ifdef HAVE_LIBEDIT _line_sock = sock; rl_already_prompted = 1; if (isatty(0)) { @@ -255,7 +242,6 @@ pass(int sock) rl_callback_handler_install("", send_line); } rl_attempted_completion_function = varnishadm_completion; -#endif fds[0].fd = sock; fds[0].events = POLLIN; @@ -317,25 +303,10 @@ pass(int sock) free(answer); answer = NULL; } -#ifdef HAVE_LIBEDIT rl_forced_update_display(); -#endif } if (fds[1].revents & POLLIN) { -#ifdef HAVE_LIBEDIT rl_callback_read_char(); -#else - n = read(fds[1].fd, buf, sizeof buf); - if (n == 0) { - AZ(shutdown(sock, SHUT_WR)); - fds[1].fd = -1; - } else if (n < 0) { - RL_EXIT(0); - } else { - buf[n] = '\0'; - cli_write(sock, buf); - } -#endif } } } diff --git a/configure.ac b/configure.ac index e918ad7..37e894f 100644 --- a/configure.ac +++ b/configure.ac @@ -156,7 +156,7 @@ PKG_CHECK_MODULES([LIBEDIT], [libedit], LIBEDIT_CFLAGS="" LIBEDIT_LIBS="-ledit ${CURSES_LIBS}" ], - [AC_MSG_WARN([libedit not found, disabling libedit support])], + [AC_MSG_ERROR([libedit or readline not found])], [${CURSES_LIBS}])]) # Checks for header files. From tfheen at varnish-cache.org Tue Mar 12 13:40:42 2013 From: tfheen at varnish-cache.org (Tollef Fog Heen) Date: Tue, 12 Mar 2013 14:40:42 +0100 Subject: [master] a1ed465 Simplify libedit/readline detection somewhat. Message-ID: commit a1ed465f67678d58f313da70e11d251c49ce1b6d Author: Tollef Fog Heen Date: Tue Mar 12 14:40:21 2013 +0100 Simplify libedit/readline detection somewhat. diff --git a/configure.ac b/configure.ac index 37e894f..4ae4e4f 100644 --- a/configure.ac +++ b/configure.ac @@ -148,16 +148,10 @@ AC_SUBST(PCRE_LIBS) PKG_CHECK_MODULES([LIBEDIT], [libedit], [AC_DEFINE([HAVE_LIBEDIT], [1], [Define we have libedit])], - [AC_CHECK_HEADERS([readline/readline.h]) - AC_CHECK_HEADERS([edit/readline/readline.h]) - AC_CHECK_HEADERS([readline/history.h]) - AC_CHECK_LIB(edit, el_init, - [ AC_DEFINE([HAVE_LIBEDIT], [1], [Define we have libedit]) - LIBEDIT_CFLAGS="" - LIBEDIT_LIBS="-ledit ${CURSES_LIBS}" - ], - [AC_MSG_ERROR([libedit or readline not found])], - [${CURSES_LIBS}])]) + [AX_LIB_READLINE]) +if test "$ac_cv_have_readline" = no; then + AC_MSG_ERROR([libedit or readline not found]) +fi # Checks for header files. AC_HEADER_STDC diff --git a/m4/ax_lib_readline.m4 b/m4/ax_lib_readline.m4 new file mode 100644 index 0000000..056f25c --- /dev/null +++ b/m4/ax_lib_readline.m4 @@ -0,0 +1,107 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_lib_readline.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_LIB_READLINE +# +# DESCRIPTION +# +# Searches for a readline compatible library. If found, defines +# `HAVE_LIBREADLINE'. If the found library has the `add_history' function, +# sets also `HAVE_READLINE_HISTORY'. Also checks for the locations of the +# necessary include files and sets `HAVE_READLINE_H' or +# `HAVE_READLINE_READLINE_H' and `HAVE_READLINE_HISTORY_H' or +# 'HAVE_HISTORY_H' if the corresponding include files exists. +# +# The libraries that may be readline compatible are `libedit', +# `libeditline' and `libreadline'. Sometimes we need to link a termcap +# library for readline to work, this macro tests these cases too by trying +# to link with `libtermcap', `libcurses' or `libncurses' before giving up. +# +# Here is an example of how to use the information provided by this macro +# to perform the necessary includes or declarations in a C file: +# +# #ifdef HAVE_LIBREADLINE +# # if defined(HAVE_READLINE_READLINE_H) +# # include +# # elif defined(HAVE_READLINE_H) +# # include +# # else /* !defined(HAVE_READLINE_H) */ +# extern char *readline (); +# # endif /* !defined(HAVE_READLINE_H) */ +# char *cmdline = NULL; +# #else /* !defined(HAVE_READLINE_READLINE_H) */ +# /* no readline */ +# #endif /* HAVE_LIBREADLINE */ +# +# #ifdef HAVE_READLINE_HISTORY +# # if defined(HAVE_READLINE_HISTORY_H) +# # include +# # elif defined(HAVE_HISTORY_H) +# # include +# # else /* !defined(HAVE_HISTORY_H) */ +# extern void add_history (); +# extern int write_history (); +# extern int read_history (); +# # endif /* defined(HAVE_READLINE_HISTORY_H) */ +# /* no history */ +# #endif /* HAVE_READLINE_HISTORY */ +# +# LICENSE +# +# Copyright (c) 2008 Ville Laurikari +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 6 + +AU_ALIAS([VL_LIB_READLINE], [AX_LIB_READLINE]) +AC_DEFUN([AX_LIB_READLINE], [ + AC_CACHE_CHECK([for a readline compatible library], + ax_cv_lib_readline, [ + ORIG_LIBS="$LIBS" + for readline_lib in readline edit editline; do + for termcap_lib in "" termcap curses ncurses; do + if test -z "$termcap_lib"; then + TRY_LIB="-l$readline_lib" + else + TRY_LIB="-l$readline_lib -l$termcap_lib" + fi + LIBS="$ORIG_LIBS $TRY_LIB" + AC_TRY_LINK_FUNC(readline, ax_cv_lib_readline="$TRY_LIB") + if test -n "$ax_cv_lib_readline"; then + break + fi + done + if test -n "$ax_cv_lib_readline"; then + break + fi + done + if test -z "$ax_cv_lib_readline"; then + ax_cv_lib_readline="no" + fi + LIBS="$ORIG_LIBS" + ]) + + if test "$ax_cv_lib_readline" != "no"; then + LIBS="$LIBS $ax_cv_lib_readline" + AC_DEFINE(HAVE_LIBREADLINE, 1, + [Define if you have a readline compatible library]) + AC_CHECK_HEADERS(readline.h readline/readline.h) + AC_CACHE_CHECK([whether readline supports history], + ax_cv_lib_readline_history, [ + ax_cv_lib_readline_history="no" + AC_TRY_LINK_FUNC(add_history, ax_cv_lib_readline_history="yes") + ]) + if test "$ax_cv_lib_readline_history" = "yes"; then + AC_DEFINE(HAVE_READLINE_HISTORY, 1, + [Define if your readline library has \`add_history']) + AC_CHECK_HEADERS(history.h readline/history.h) + fi + fi +])dnl From phk at varnish-cache.org Tue Mar 12 14:10:31 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Tue, 12 Mar 2013 15:10:31 +0100 Subject: [master] 0a712d9 Make sure object destructors are called as the first thing in the VCL::fini cleanup Message-ID: commit 0a712d95c1935d2c52cbaf091457e38736515c5b Author: Poul-Henning Kamp Date: Tue Mar 12 14:10:13 2013 +0000 Make sure object destructors are called as the first thing in the VCL::fini cleanup diff --git a/lib/libvcl/vcc_action.c b/lib/libvcl/vcc_action.c index 5fdae74..7d5ea2e 100644 --- a/lib/libvcl/vcc_action.c +++ b/lib/libvcl/vcc_action.c @@ -222,7 +222,7 @@ parse_new(struct vcc *tl) bprintf(buf1, ", &%s, \"%s\"", sy1->name, sy1->name); vcc_Eval_Func(tl, s_init, buf1, "ASDF", s_init + strlen(s_init) + 1); - Ff(tl, 0, "\t%s((struct req*)0, &%s);\n", s_fini, sy1->name); + Fd(tl, 0, "\t%s((struct req*)0, &%s);\n", s_fini, sy1->name); ExpectErr(tl, ';'); bprintf(buf1, ", %s", sy1->name); diff --git a/lib/libvcl/vcc_compile.c b/lib/libvcl/vcc_compile.c index e585e67..6eca56c 100644 --- a/lib/libvcl/vcc_compile.c +++ b/lib/libvcl/vcc_compile.c @@ -190,6 +190,19 @@ Fi(const struct vcc *tl, int indent, const char *fmt, ...) } void +Fd(const struct vcc *tl, int indent, const char *fmt, ...) +{ + va_list ap; + + if (indent) + VSB_printf(tl->fd, "%*.*s", tl->findent, tl->findent, ""); + va_start(ap, fmt); + VSB_vprintf(tl->fd, fmt, ap); + va_end(ap); +} + + +void Ff(const struct vcc *tl, int indent, const char *fmt, ...) { va_list ap; @@ -316,6 +329,9 @@ EmitFiniFunc(const struct vcc *tl) Fc(tl, 0, "\nstatic void\nVGC_Fini(struct cli *cli)\n{\n\n"); + AZ(VSB_finish(tl->fd)); + VSB_cat(tl->fc, VSB_data(tl->fd)); + /* * We do this here, so we are sure they happen before any * per-vcl vmod_privs get cleaned. @@ -517,6 +533,10 @@ vcc_NewVcc(const struct vcc *tl0) tl->fi = VSB_new_auto(); assert(tl->fi != NULL); + /* Destroy Objects */ + tl->fd = VSB_new_auto(); + assert(tl->fd != NULL); + /* Finish C code */ tl->ff = VSB_new_auto(); assert(tl->ff != NULL); diff --git a/lib/libvcl/vcc_compile.h b/lib/libvcl/vcc_compile.h index 1e51f5f..65e5dff 100644 --- a/lib/libvcl/vcc_compile.h +++ b/lib/libvcl/vcc_compile.h @@ -170,6 +170,7 @@ struct vcc { struct vsb *fc; /* C-code */ struct vsb *fh; /* H-code (before C-code) */ struct vsb *fi; /* Init func code */ + struct vsb *fd; /* Object destructors */ struct vsb *ff; /* Finish func code */ struct vsb *fb; /* Body of current sub * NULL otherwise @@ -258,6 +259,8 @@ void Fi(const struct vcc *tl, int indent, const char *fmt, ...) __printflike(3, 4); void Ff(const struct vcc *tl, int indent, const char *fmt, ...) __printflike(3, 4); +void Fd(const struct vcc *tl, int indent, const char *fmt, ...) + __printflike(3, 4); void EncToken(struct vsb *sb, const struct token *t); int IsMethod(const struct token *t); void *TlAlloc(struct vcc *tl, unsigned len); From tfheen at varnish-cache.org Tue Mar 12 14:13:54 2013 From: tfheen at varnish-cache.org (Tollef Fog Heen) Date: Tue, 12 Mar 2013 15:13:54 +0100 Subject: [master] f8b37ce ifdef int x declaration to fix build failure Message-ID: commit f8b37ce317b2e5b524b72dc507f842333df15197 Author: Tollef Fog Heen Date: Tue Mar 12 15:13:07 2013 +0100 ifdef int x declaration to fix build failure diff --git a/bin/varnishd/cache/cache_acceptor.c b/bin/varnishd/cache/cache_acceptor.c index ee9352f..e7de0b3 100644 --- a/bin/varnishd/cache/cache_acceptor.c +++ b/bin/varnishd/cache/cache_acceptor.c @@ -122,12 +122,15 @@ static unsigned need_test; static int vca_tcp_opt_init(void) { - int n, x; + int n; int one = 1; // int zero = 0; struct tcp_opt *to; struct timeval tv; int chg = 0; +#ifdef HAVE_TCP_KEEP + int x; +#endif for (n = 0; n < n_tcp_opts; n++) { to = &tcp_opts[n]; From phk at varnish-cache.org Tue Mar 12 14:22:06 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Tue, 12 Mar 2013 15:22:06 +0100 Subject: [master] 90b058b Add a random director to VMOD.directors Message-ID: commit 90b058b859833e740627b57998bf3b3511a8ab9b Author: Poul-Henning Kamp Date: Tue Mar 12 14:21:31 2013 +0000 Add a random director to VMOD.directors diff --git a/bin/varnishtest/tests/b00016.vtc b/bin/varnishtest/tests/b00016.vtc index 17e38f4..93be72b 100644 --- a/bin/varnishtest/tests/b00016.vtc +++ b/bin/varnishtest/tests/b00016.vtc @@ -21,21 +21,23 @@ client c1 { } -run varnish v1 -vcl { - director bar random { - { - .backend = { - .host = "${bad_ip}"; .port = "9080"; - } - .weight = 1; - } + import directors from "${topbuild}/lib/libvmod_directors/.libs/libvmod_directors.so" ; + + backend b1 { + .host = "${bad_ip}"; .port = "9080"; + } + sub vcl_init { + new bar = directors.random(); + bar.add_backend(b1, 1); } sub vcl_recv { - error 200 "ok"; + set req.backend = bar.backend(); + error 200 "ok"; } sub vcl_error { - set obj.http.X-Backend-Name = req.backend; + set obj.http.X-Backend-Name = req.backend; } } diff --git a/bin/varnishtest/tests/r00263.vtc b/bin/varnishtest/tests/r00263.vtc index 79df874..8ae4bd7 100644 --- a/bin/varnishtest/tests/r00263.vtc +++ b/bin/varnishtest/tests/r00263.vtc @@ -1,18 +1,23 @@ varnishtest "Test refcounting backends from director" +# XXX: This test is probably not relevant with VMOD.directors + varnish v1 -vcl { + import directors from "${topbuild}/lib/libvmod_directors/.libs/libvmod_directors.so" ; + backend node1 { .host = "10.0.0.1"; .port = "80"; } backend node2 { .host = "10.0.0.2"; .port = "80"; } backend node3 { .host = "10.0.0.3"; .port = "80"; } - director cluster random { - { .backend = node1; .weight = 1; } - { .backend = node2; .weight = 1; } - { .backend = node3; .weight = 1; } + sub vcl_init { + new cluster = directors.random(); + cluster.add_backend(node1, 1); + cluster.add_backend(node2, 1); + cluster.add_backend(node3, 1); } sub vcl_recv { - set req.backend = cluster; + set req.backend = cluster.backend(); } } -start diff --git a/bin/varnishtest/tests/r00306.vtc b/bin/varnishtest/tests/r00306.vtc index 079e994..c00badb 100644 --- a/bin/varnishtest/tests/r00306.vtc +++ b/bin/varnishtest/tests/r00306.vtc @@ -18,19 +18,23 @@ server s2 { } -start varnish v1 -vcl { + + import directors from "${topbuild}/lib/libvmod_directors/.libs/libvmod_directors.so" ; + backend s1 { .host = "${s1_addr}"; .port = "${s1_port}"; } backend s2 { .host = "${s2_addr}"; .port = "${s2_port}"; } - director foo random { - { .backend = s2; .weight = 1; } - { .backend = s1; .weight = 1; } + sub vcl_init { + new foo = directors.random(); + foo.add_backend(s1, 1); + foo.add_backend(s2, 1); } sub vcl_recv { - set req.backend = foo; + set req.backend = foo.backend(); } } -start diff --git a/bin/varnishtest/tests/r00722.vtc b/bin/varnishtest/tests/r00722.vtc index 8d7dc24..2e41814 100644 --- a/bin/varnishtest/tests/r00722.vtc +++ b/bin/varnishtest/tests/r00722.vtc @@ -6,18 +6,33 @@ server s1 { } -start varnish v1 -vcl+backend { - director foo random { - { .backend = s1; .weight = 1; } - { .backend = { .host = "${s1_addr}"; .port = "${s1_port}";} .weight =1; } - { .backend = { .host = "${s1_addr}"; .port = "${s1_port}";} .weight =1; } + import directors from "${topbuild}/lib/libvmod_directors/.libs/libvmod_directors.so" ; + + backend b2 { + .host = "${s1_addr}"; .port = "${s1_port}"; + } + + backend b3 { + .host = "${s1_addr}"; .port = "${s1_port}"; + } + + sub vcl_init { + new foo = directors.random(); + foo.add_backend(s1, 1); + foo.add_backend(b2, 1); + foo.add_backend(b3, 1); } sub vcl_recv { - set req.backend = foo; + set req.backend = foo.backend(); } } -start +varnish v1 -cliok "vcl.list" +varnish v1 -cliok "backend.list" varnish v1 -vcl+backend { } +varnish v1 -cliok "vcl.list" +varnish v1 -cliok "backend.list" varnish v1 -cliok "vcl.list" varnish v1 -cliok "vcl.discard vcl1" diff --git a/bin/varnishtest/tests/v00007.vtc b/bin/varnishtest/tests/v00007.vtc index 5768c02..d0c37f8 100644 --- a/bin/varnishtest/tests/v00007.vtc +++ b/bin/varnishtest/tests/v00007.vtc @@ -8,13 +8,16 @@ server s1 { } -start varnish v1 -vcl+backend { - director foo random { - { .backend = s1; .weight = 1; } - { .weight = 1; .backend = s1; } + import directors from "${topbuild}/lib/libvmod_directors/.libs/libvmod_directors.so"; + + sub vcl_init { + new foo = directors.random(); + foo.add_backend(s1, 1); + foo.add_backend(s1, 1); } sub vcl_recv { - set req.backend = foo; + set req.backend = foo.backend(); } } -start diff --git a/bin/varnishtest/tests/v00022.vtc b/bin/varnishtest/tests/v00022.vtc index 15b9a90..5bfb1fe 100644 --- a/bin/varnishtest/tests/v00022.vtc +++ b/bin/varnishtest/tests/v00022.vtc @@ -32,15 +32,18 @@ server s4 { } -start varnish v1 -vcl+backend { - director foo random { - { .backend = s1; .weight = 1; } - { .backend = s2; .weight = 1; } - { .backend = s3; .weight = 1; } - { .backend = s4; .weight = 1; } + import directors from "${topbuild}/lib/libvmod_directors/.libs/libvmod_directors.so" ; + + sub vcl_init { + new foo = directors.random(); + foo.add_backend(s1, 1); + foo.add_backend(s2, 1); + foo.add_backend(s3, 1); + foo.add_backend(s4, 1); } sub vcl_recv { - set req.backend = foo; + set req.backend = foo.backend(); return(pass); } } -start diff --git a/lib/libvmod_directors/Makefile.am b/lib/libvmod_directors/Makefile.am index 2c879c8..b222026 100644 --- a/lib/libvmod_directors/Makefile.am +++ b/lib/libvmod_directors/Makefile.am @@ -17,6 +17,7 @@ libvmod_directors_la_SOURCES = \ vdir.c \ vdir.h \ fall_back.c \ + random.c \ round_robin.c nodist_libvmod_directors_la_SOURCES = \ diff --git a/lib/libvmod_directors/random.c b/lib/libvmod_directors/random.c new file mode 100644 index 0000000..32f829a --- /dev/null +++ b/lib/libvmod_directors/random.c @@ -0,0 +1,148 @@ +/*- + * Copyright (c) 2013 Varnish Software AS + * All rights reserved. + * + * Author: Poul-Henning Kamp + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "config.h" + +#include +#include + +#include "cache/cache.h" +#include "cache/cache_backend.h" + +#include "vrt.h" +#include "vbm.h" + +#include "vdir.h" + +#include "vcc_if.h" + +struct vmod_directors_random { + unsigned magic; +#define VMOD_DIRECTORS_RANDOM_MAGIC 0x4732d092 + struct vdir *vd; + unsigned nloops; + struct vbitmap *vbm; +}; + +static unsigned __match_proto__(vdi_healthy) +vmod_rr_healthy(const struct director *dir, const struct req *req) +{ + struct vmod_directors_random *rr; + + CAST_OBJ_NOTNULL(rr, dir->priv, VMOD_DIRECTORS_RANDOM_MAGIC); + return (vdir_any_healthy(rr->vd, req)); +} + +static struct vbc * __match_proto__(vdi_getfd_f) +vmod_rr_getfd(const struct director *dir, struct req *req) +{ + struct vmod_directors_random *rr; + struct vbitmap *vbm = NULL; + unsigned u, v, l; + VCL_BACKEND be = NULL; + double tw; + int nbe; + double r; + + CAST_OBJ_NOTNULL(rr, dir->priv, VMOD_DIRECTORS_RANDOM_MAGIC); + tw = rr->vd->total_weight; + nbe = rr->vd->n_backend; + r = scalbn(random(), -31); + assert(r >= 0.0 && r <= 1.0); + vdir_lock(rr->vd); + for (l = 0; nbe > 0 && tw > 0.0 && l < rr->nloops; l++) { + u = vdir_pick_by_weight(rr->vd, r * tw, vbm); + be = rr->vd->backend[u]; + CHECK_OBJ_NOTNULL(be, DIRECTOR_MAGIC); + if (be->healthy(be, req)) + break; + if (l == 0) { + vbm = rr->vbm; + for (v = 0; v < nbe; v++) + vbit_clr(vbm, v); + } + vbit_set(vbm, u); + nbe--; + tw -= rr->vd->weight[u]; + be = NULL; + } + vdir_unlock(rr->vd); + if (be == NULL) + return (NULL); + return (be->getfd(be, req)); +} + +VCL_VOID __match_proto__() +vmod_random__init(struct req *req, struct vmod_directors_random **rrp, + const char *vcl_name) +{ + struct vmod_directors_random *rr; + + AZ(req); + AN(rrp); + AZ(*rrp); + ALLOC_OBJ(rr, VMOD_DIRECTORS_RANDOM_MAGIC); + AN(rr); + rr->vbm = vbit_init(8); + AN(rr->vbm); + rr->nloops = 3; // + *rrp = rr; + vdir_new(&rr->vd, vcl_name, vmod_rr_healthy, vmod_rr_getfd, rr); +} + +VCL_VOID __match_proto__() +vmod_random__fini(struct req *req, struct vmod_directors_random **rrp) +{ + struct vmod_directors_random *rr; + + AZ(req); + rr = *rrp; + *rrp = NULL; + CHECK_OBJ_NOTNULL(rr, VMOD_DIRECTORS_RANDOM_MAGIC); + vdir_delete(&rr->vd); + vbit_destroy(rr->vbm); + FREE_OBJ(rr); +} + +VCL_VOID __match_proto__() +vmod_random_add_backend(struct req *req, + struct vmod_directors_random *rr, VCL_BACKEND be, double w) +{ + + (void)req; + CHECK_OBJ_NOTNULL(rr, VMOD_DIRECTORS_RANDOM_MAGIC); + (void)vdir_add_backend(rr->vd, be, w); +} + +VCL_BACKEND __match_proto__() +vmod_random_backend(struct req *req, struct vmod_directors_random *rr) +{ + (void)req; + CHECK_OBJ_NOTNULL(rr, VMOD_DIRECTORS_RANDOM_MAGIC); + return (rr->vd->dir); +} diff --git a/lib/libvmod_directors/vdir.c b/lib/libvmod_directors/vdir.c index be8f340..c8d6fe5 100644 --- a/lib/libvmod_directors/vdir.c +++ b/lib/libvmod_directors/vdir.c @@ -34,6 +34,7 @@ #include "cache/cache_backend.h" #include "vrt.h" +#include "vbm.h" #include "vdir.h" @@ -118,6 +119,7 @@ vdir_add_backend(struct vdir *vd, VCL_BACKEND be, double weight) u = vd->n_backend++; vd->backend[u] = be; vd->weight[u] = weight; + vd->total_weight += weight; vdir_unlock(vd); return (u); } @@ -142,3 +144,24 @@ vdir_any_healthy(struct vdir *vd, const struct req *req) vdir_unlock(vd); return (retval); } + +unsigned +vdir_pick_by_weight(const struct vdir *vd, double w, + const struct vbitmap *blacklist) +{ + double a = 0.0; + VCL_BACKEND be = NULL; + unsigned u; + + for (u = 0; u < vd->n_backend; u++) { + be = vd->backend[u]; + CHECK_OBJ_NOTNULL(be, DIRECTOR_MAGIC); + if (blacklist != NULL && vbit_test(blacklist, u)) + continue; + a += vd->weight[u]; + if (w < a) + return (u); + } + WRONG(""); +} + diff --git a/lib/libvmod_directors/vdir.h b/lib/libvmod_directors/vdir.h index 1b588b4..7f42e70 100644 --- a/lib/libvmod_directors/vdir.h +++ b/lib/libvmod_directors/vdir.h @@ -26,6 +26,8 @@ * SUCH DAMAGE. */ +struct vbitmap; + struct vdir { unsigned magic; #define VDIR_MAGIC 0x99f4b726 @@ -34,6 +36,7 @@ struct vdir { unsigned l_backend; VCL_BACKEND *backend; double *weight; + double total_weight; struct director *dir; }; @@ -44,3 +47,5 @@ void vdir_lock(struct vdir *vd); void vdir_unlock(struct vdir *vd); unsigned vdir_add_backend(struct vdir *vd, VCL_BACKEND be, double weight); unsigned vdir_any_healthy(struct vdir *vd, const struct req *); +unsigned vdir_pick_by_weight(const struct vdir *vd, double w, + const struct vbitmap *blacklist); diff --git a/lib/libvmod_directors/vmod.vcc b/lib/libvmod_directors/vmod.vcc index 2945559..b74057d 100644 --- a/lib/libvmod_directors/vmod.vcc +++ b/lib/libvmod_directors/vmod.vcc @@ -36,3 +36,8 @@ Object fallback() { Method VOID .add_backend(BACKEND) Method BACKEND .backend() } + +Object random() { + Method VOID .add_backend(BACKEND, REAL) + Method BACKEND .backend() +} From phk at varnish-cache.org Thu Mar 14 10:06:42 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Thu, 14 Mar 2013 11:06:42 +0100 Subject: [master] 12e571b Add a hash director to vmod.directors. Message-ID: commit 12e571b3eba5d1b2d55a00fa237a3c946c0526fa Author: Poul-Henning Kamp Date: Thu Mar 14 10:06:29 2013 +0000 Add a hash director to vmod.directors. diff --git a/bin/varnishtest/tests/v00026.vtc b/bin/varnishtest/tests/v00026.vtc index e7f4fa4..d859658 100644 --- a/bin/varnishtest/tests/v00026.vtc +++ b/bin/varnishtest/tests/v00026.vtc @@ -16,13 +16,16 @@ server s2 { varnish v1 -vcl+backend { - director h1 hash { - { .backend = s1; .weight = 1; } - { .backend = s2; .weight = 1; } + import directors from "${topbuild}/lib/libvmod_directors/.libs/libvmod_directors.so" ; + + sub vcl_init { + new h1 = directors.hash(); + h1.add_backend(s1, 1); + h1.add_backend(s2, 1); } sub vcl_recv { - set req.backend = h1; + set req.backend = h1.backend(req.url); return(pass); } @@ -30,11 +33,11 @@ varnish v1 -vcl+backend { client c1 { - txreq -url /12 + txreq -url /1 rxresp expect resp.http.foo == "1" - txreq -url /1 + txreq -url /3 rxresp expect resp.http.foo == "2" @@ -42,7 +45,7 @@ client c1 { rxresp expect resp.http.foo == "3" - txreq -url /15 + txreq -url /8 rxresp expect resp.http.foo == "4" diff --git a/lib/libvmod_directors/Makefile.am b/lib/libvmod_directors/Makefile.am index b222026..e49a285 100644 --- a/lib/libvmod_directors/Makefile.am +++ b/lib/libvmod_directors/Makefile.am @@ -17,6 +17,7 @@ libvmod_directors_la_SOURCES = \ vdir.c \ vdir.h \ fall_back.c \ + hash.c \ random.c \ round_robin.c diff --git a/lib/libvmod_directors/hash.c b/lib/libvmod_directors/hash.c new file mode 100644 index 0000000..ea011a3 --- /dev/null +++ b/lib/libvmod_directors/hash.c @@ -0,0 +1,123 @@ +/*- + * Copyright (c) 2013 Varnish Software AS + * All rights reserved. + * + * Author: Poul-Henning Kamp + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "config.h" + +#include +#include + +#include "cache/cache.h" +#include "cache/cache_backend.h" + +#include "vrt.h" +#include "vbm.h" +#include "vend.h" +#include "vsha256.h" + +#include "vdir.h" + +#include "vcc_if.h" + +struct vmod_directors_hash { + unsigned magic; +#define VMOD_DIRECTORS_HASH_MAGIC 0xc08dd611 + struct vdir *vd; + unsigned nloops; + struct vbitmap *vbm; +}; + +VCL_VOID __match_proto__() +vmod_hash__init(struct req *req, struct vmod_directors_hash **rrp, + const char *vcl_name) +{ + struct vmod_directors_hash *rr; + + AZ(req); + AN(rrp); + AZ(*rrp); + ALLOC_OBJ(rr, VMOD_DIRECTORS_HASH_MAGIC); + AN(rr); + rr->vbm = vbit_init(8); + AN(rr->vbm); + rr->nloops = 3; // + *rrp = rr; + vdir_new(&rr->vd, vcl_name, NULL, NULL, rr); +} + +VCL_VOID __match_proto__() +vmod_hash__fini(struct req *req, struct vmod_directors_hash **rrp) +{ + struct vmod_directors_hash *rr; + + AZ(req); + rr = *rrp; + *rrp = NULL; + CHECK_OBJ_NOTNULL(rr, VMOD_DIRECTORS_HASH_MAGIC); + vdir_delete(&rr->vd); + vbit_destroy(rr->vbm); + FREE_OBJ(rr); +} + +VCL_VOID __match_proto__() +vmod_hash_add_backend(struct req *req, + struct vmod_directors_hash *rr, VCL_BACKEND be, double w) +{ + + (void)req; + CHECK_OBJ_NOTNULL(rr, VMOD_DIRECTORS_HASH_MAGIC); + (void)vdir_add_backend(rr->vd, be, w); +} + +VCL_BACKEND __match_proto__() +vmod_hash_backend(struct req *req, struct vmod_directors_hash *rr, const char *arg, ...) +{ + struct SHA256Context ctx; + va_list ap; + const char *p; + unsigned char sha256[SHA256_LEN]; + VCL_BACKEND be; + double r; + + (void)req; + + CHECK_OBJ_NOTNULL(rr, VMOD_DIRECTORS_HASH_MAGIC); + SHA256_Init(&ctx); + va_start(ap, arg); + p = arg; + while (p != vrt_magic_string_end) { + SHA256_Update(&ctx, arg, strlen(arg)); + p = va_arg(ap, const char *); + } + va_end(ap); + SHA256_Final(sha256, &ctx); + + r = vbe32dec(sha256); + r = scalbn(r, -32); + be = vdir_pick_be(rr->vd, req, r, rr->nloops); + return (be); +} diff --git a/lib/libvmod_directors/random.c b/lib/libvmod_directors/random.c index 32f829a..61eb677 100644 --- a/lib/libvmod_directors/random.c +++ b/lib/libvmod_directors/random.c @@ -62,36 +62,12 @@ static struct vbc * __match_proto__(vdi_getfd_f) vmod_rr_getfd(const struct director *dir, struct req *req) { struct vmod_directors_random *rr; - struct vbitmap *vbm = NULL; - unsigned u, v, l; - VCL_BACKEND be = NULL; - double tw; - int nbe; + VCL_BACKEND be; double r; CAST_OBJ_NOTNULL(rr, dir->priv, VMOD_DIRECTORS_RANDOM_MAGIC); - tw = rr->vd->total_weight; - nbe = rr->vd->n_backend; r = scalbn(random(), -31); - assert(r >= 0.0 && r <= 1.0); - vdir_lock(rr->vd); - for (l = 0; nbe > 0 && tw > 0.0 && l < rr->nloops; l++) { - u = vdir_pick_by_weight(rr->vd, r * tw, vbm); - be = rr->vd->backend[u]; - CHECK_OBJ_NOTNULL(be, DIRECTOR_MAGIC); - if (be->healthy(be, req)) - break; - if (l == 0) { - vbm = rr->vbm; - for (v = 0; v < nbe; v++) - vbit_clr(vbm, v); - } - vbit_set(vbm, u); - nbe--; - tw -= rr->vd->weight[u]; - be = NULL; - } - vdir_unlock(rr->vd); + be = vdir_pick_be(rr->vd, req, r, rr->nloops); if (be == NULL) return (NULL); return (be->getfd(be, req)); diff --git a/lib/libvmod_directors/vdir.c b/lib/libvmod_directors/vdir.c index c8d6fe5..0a8e954 100644 --- a/lib/libvmod_directors/vdir.c +++ b/lib/libvmod_directors/vdir.c @@ -70,6 +70,8 @@ vdir_new(struct vdir **vdp, const char *vcl_name, vdi_healthy *healthy, vd->dir->priv = priv; vd->dir->healthy = healthy; vd->dir->getfd = getfd; + vd->vbm = vbit_init(8); + AN(vd->vbm); } void @@ -87,6 +89,7 @@ vdir_delete(struct vdir **vdp) free(vd->weight); AZ(pthread_mutex_destroy(&vd->mtx)); FREE_OBJ(vd->dir); + vbit_destroy(vd->vbm); FREE_OBJ(vd); } @@ -145,7 +148,7 @@ vdir_any_healthy(struct vdir *vd, const struct req *req) return (retval); } -unsigned +static unsigned vdir_pick_by_weight(const struct vdir *vd, double w, const struct vbitmap *blacklist) { @@ -165,3 +168,36 @@ vdir_pick_by_weight(const struct vdir *vd, double w, WRONG(""); } +VCL_BACKEND +vdir_pick_be(struct vdir *vd, const struct req *req, double w, unsigned nloops) +{ + struct vbitmap *vbm = NULL; + unsigned u, v, l; + VCL_BACKEND be = NULL; + double tw; + int nbe; + + tw = vd->total_weight; + nbe = vd->n_backend; + assert(w >= 0.0 && w <= 1.0); + vdir_lock(vd); + for (l = 0; nbe > 0 && tw > 0.0 && l backend[u]; + CHECK_OBJ_NOTNULL(be, DIRECTOR_MAGIC); + if (be->healthy(be, req)) + break; + if (l == 0) { + vbm = vd->vbm; + for (v = 0; v < nbe; v++) + vbit_clr(vbm, v); + } + vbit_set(vbm, u); + nbe--; + tw -= vd->weight[u]; + be = NULL; + } + vdir_unlock(vd); + return (be); +} + diff --git a/lib/libvmod_directors/vdir.h b/lib/libvmod_directors/vdir.h index 7f42e70..76795d7 100644 --- a/lib/libvmod_directors/vdir.h +++ b/lib/libvmod_directors/vdir.h @@ -38,6 +38,7 @@ struct vdir { double *weight; double total_weight; struct director *dir; + struct vbitmap *vbm; }; void vdir_new(struct vdir **vdp, const char *vcl_name, vdi_healthy *healthy, @@ -47,5 +48,5 @@ void vdir_lock(struct vdir *vd); void vdir_unlock(struct vdir *vd); unsigned vdir_add_backend(struct vdir *vd, VCL_BACKEND be, double weight); unsigned vdir_any_healthy(struct vdir *vd, const struct req *); -unsigned vdir_pick_by_weight(const struct vdir *vd, double w, - const struct vbitmap *blacklist); +VCL_BACKEND vdir_pick_be(struct vdir *vd, const struct req *req, double w, + unsigned nloops); diff --git a/lib/libvmod_directors/vmod.vcc b/lib/libvmod_directors/vmod.vcc index b74057d..8b61944 100644 --- a/lib/libvmod_directors/vmod.vcc +++ b/lib/libvmod_directors/vmod.vcc @@ -41,3 +41,8 @@ Object random() { Method VOID .add_backend(BACKEND, REAL) Method BACKEND .backend() } + +Object hash() { + Method VOID .add_backend(BACKEND, REAL) + Method BACKEND .backend(STRING_LIST) +} From phk at varnish-cache.org Mon Mar 18 10:09:01 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Mon, 18 Mar 2013 11:09:01 +0100 Subject: [master] 4c2ae4e Swing the infamous "phk viking axe" and deorbit directors from the core code. Message-ID: commit 4c2ae4eae9645290aca4ddb57b06f10e91d8a40d Author: Poul-Henning Kamp Date: Mon Mar 18 10:07:32 2013 +0000 Swing the infamous "phk viking axe" and deorbit directors from the core code. In the future directors belong in VMODs, which takes the need to hack VCC code out of the learning-curve. Certain directors have already been moved to VMODs, others will need a bit of brain-surgery before they go there. This commit is to get them out of the way for V4 diff --git a/bin/varnishd/Makefile.am b/bin/varnishd/Makefile.am index 378ce55..18699e5 100644 --- a/bin/varnishd/Makefile.am +++ b/bin/varnishd/Makefile.am @@ -19,8 +19,6 @@ varnishd_SOURCES = \ cache/cache_busyobj.c \ cache/cache_cli.c \ cache/cache_dir.c \ - cache/cache_dir_dns.c \ - cache/cache_dir_random.c \ cache/cache_esi_deliver.c \ cache/cache_esi_fetch.c \ cache/cache_esi_parse.c \ diff --git a/bin/varnishd/cache/cache_backend.c b/bin/varnishd/cache/cache_backend.c index e8efb90..c6f0b9b 100644 --- a/bin/varnishd/cache/cache_backend.c +++ b/bin/varnishd/cache/cache_backend.c @@ -389,26 +389,6 @@ vbe_GetVbe(struct req *req, struct vdi_simple *vs) } /*-------------------------------------------------------------------- - * Returns the backend if and only if the this is a simple director. - * XXX: Needs a better name and possibly needs a better general approach. - * XXX: This is mainly used by the DNS director to fetch the actual backend - * XXX: so it can compare DNS lookups with the actual IP. - */ - -struct backend * -vdi_get_backend_if_simple(const struct director *d) -{ - CHECK_OBJ_NOTNULL(d, DIRECTOR_MAGIC); - struct vdi_simple *vs, *vs2; - - vs2 = d->priv; - if (vs2->magic != VDI_SIMPLE_MAGIC) - return (NULL); - CAST_OBJ_NOTNULL(vs, d->priv, VDI_SIMPLE_MAGIC); - return (vs->backend); -} - -/*-------------------------------------------------------------------- * */ diff --git a/bin/varnishd/cache/cache_backend.h b/bin/varnishd/cache/cache_backend.h index b1e8d89..b87b8d4 100644 --- a/bin/varnishd/cache/cache_backend.h +++ b/bin/varnishd/cache/cache_backend.h @@ -167,7 +167,6 @@ struct vbc { /* cache_backend.c */ void VBE_ReleaseConn(struct vbc *vc); -struct backend *vdi_get_backend_if_simple(const struct director *d); /* cache_backend_cfg.c */ void VBE_DropRefConn(struct backend *); @@ -184,7 +183,3 @@ void VBP_Summary(struct cli *cli, const struct vbp_target *vt); /* Init functions for directors */ typedef void dir_init_f(struct cli *, struct director **, int , const void*); dir_init_f VRT_init_dir_simple; -dir_init_f VRT_init_dir_dns; -dir_init_f VRT_init_dir_hash; -dir_init_f VRT_init_dir_random; -dir_init_f VRT_init_dir_client; diff --git a/bin/varnishd/cache/cache_backend_cfg.c b/bin/varnishd/cache/cache_backend_cfg.c index 2cda875..15e1104 100644 --- a/bin/varnishd/cache/cache_backend_cfg.c +++ b/bin/varnishd/cache/cache_backend_cfg.c @@ -251,14 +251,6 @@ VRT_init_dir(struct cli *cli, struct director **dir, const char *name, ASSERT_CLI(); if (!strcmp(name, "simple")) VRT_init_dir_simple(cli, dir, idx, priv); - else if (!strcmp(name, "hash")) - VRT_init_dir_hash(cli, dir, idx, priv); - else if (!strcmp(name, "random")) - VRT_init_dir_random(cli, dir, idx, priv); - else if (!strcmp(name, "dns")) - VRT_init_dir_dns(cli, dir, idx, priv); - else if (!strcmp(name, "client")) - VRT_init_dir_client(cli, dir, idx, priv); else INCOMPL(); } diff --git a/bin/varnishd/cache/cache_dir_dns.c b/bin/varnishd/cache/cache_dir_dns.c deleted file mode 100644 index d4f6772..0000000 --- a/bin/varnishd/cache/cache_dir_dns.c +++ /dev/null @@ -1,468 +0,0 @@ -/*- - * Copyright (c) 2009-2011 Varnish Software AS - * All rights reserved. - * - * Author: Kristian Lyngstol - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -#include "config.h" - -#include -#include -#include - -#include -#include -#include - -#include "cache.h" - -#include "cache_backend.h" -#include "vrt.h" - -/*--------------------------------------------------------------------*/ - -/* FIXME: Should eventually be a configurable variable. */ -#define VDI_DNS_MAX_CACHE 1024 -#define VDI_DNS_GROUP_MAX_BACKENDS 1024 - -/* DNS Cache entry - */ -struct vdi_dns_hostgroup { - unsigned magic; -#define VDI_DNSDIR_MAGIC 0x1bacab21 - char *hostname; - struct director *hosts[VDI_DNS_GROUP_MAX_BACKENDS]; - unsigned nhosts; - unsigned next_host; /* Next to use...*/ - double ttl; - VTAILQ_ENTRY(vdi_dns_hostgroup) list; -}; - -struct vdi_dns { - unsigned magic; -#define VDI_DNS_MAGIC 0x1337a178 - struct director dir; - struct director **hosts; - unsigned nhosts; - VTAILQ_HEAD(_cachelist,vdi_dns_hostgroup) cachelist; - unsigned ncachelist; - pthread_rwlock_t rwlock; - const char *suffix; - double ttl; -}; - -/* Compare an IPv4 backend to a IPv4 addr/len */ -static int -vdi_dns_comp_addrinfo4(const struct backend *bp, - const struct sockaddr_storage *addr, - const socklen_t len) -{ - uint32_t u, p; - const struct sockaddr_in *bps = (const void *)bp->ipv4; - const struct sockaddr_in *bpd = (const void *)addr; - - if (bp->ipv4len != len || len <= 0) - return (0); - - u = bpd->sin_addr.s_addr; - p = bps->sin_addr.s_addr; - - return (u == p); -} - -/* Compare an IPv6 backend to a IPv6 addr/len */ -static int -vdi_dns_comp_addrinfo6(const struct backend *bp, - const struct sockaddr_storage *addr, - const socklen_t len) -{ - const uint8_t *u, *p; - const struct sockaddr_in6 *bps = (const void *)bp->ipv6; - const struct sockaddr_in6 *bpd = (const void *)addr; - - if (bp->ipv6len != len || len <= 0) - return (0); - - u = bpd->sin6_addr.s6_addr; - p = bps->sin6_addr.s6_addr; - - return (!memcmp(u, p, 16)); -} - -/* Check if a backends socket is the same as addr */ -static int -vdi_dns_comp_addrinfo(const struct director *dir, - const struct sockaddr_storage *addr, - const socklen_t len) -{ - struct backend *bp; - - bp = vdi_get_backend_if_simple(dir); - AN(bp); - if (addr->ss_family == PF_INET && bp->ipv4) { - return (vdi_dns_comp_addrinfo4(bp, addr, len)); - } else if (addr->ss_family == PF_INET6 && bp->ipv6) { - return (vdi_dns_comp_addrinfo6(bp, addr, len)); - } - return (0); -} - -/* Pick a host from an existing hostgroup. - * Balance on round-robin if multiple backends are available and only pick - * healthy ones. - */ -static struct director * -vdi_dns_pick_host(const struct req *req, struct vdi_dns_hostgroup *group) -{ - int initial, i, nhosts, current; - - if (group->nhosts == 0) - return (NULL); // In case of error. - if (group->next_host >= group->nhosts) - group->next_host = 0; - - /* Pick a healthy backend */ - initial = group->next_host; - nhosts = group->nhosts; - for (i=0; i < nhosts; i++) { - if (i + initial >= nhosts) - current = i + initial - nhosts; - else - current = i + initial; - if (VDI_Healthy(group->hosts[current], req)) { - group->next_host = current+1; - return (group->hosts[current]); - } - } - - return (NULL); -} - -/* Remove an item from the dns cache. - * If *group is NULL, the head is popped. - * Remember locking. - */ -static void -vdi_dns_pop_cache(struct vdi_dns *vs, - struct vdi_dns_hostgroup *group) -{ - if (group == NULL) - group = VTAILQ_LAST( &vs->cachelist, _cachelist ); - assert(group != NULL); - free(group->hostname); - VTAILQ_REMOVE(&vs->cachelist, group, list); - FREE_OBJ(group); - vs->ncachelist--; -} - -/* Dummy in case someone feels like optimizing it? meh... - */ -static inline int -vdi_dns_groupmatch(const struct vdi_dns_hostgroup *group, const char *hostname) -{ - return (!strcmp(group->hostname, hostname)); -} - -/* Search the cache for 'hostname' and put a backend-pointer as necessary, - * return true for cache hit. This could still be a NULL backend if we did - * a lookup earlier and didn't find a host (ie: cache failed too) - * - * if rwlock is true, the first timed out object found (if any) is popped - * and freed. - */ -static int -vdi_dns_cache_has(const struct req *req, struct vdi_dns *vs, - const char *hostname, struct director **backend, int rwlock) -{ - struct director *ret; - struct vdi_dns_hostgroup *hostgr; - struct vdi_dns_hostgroup *hostgr2; - - VTAILQ_FOREACH_SAFE(hostgr, &vs->cachelist, list, hostgr2) { - CHECK_OBJ_NOTNULL(hostgr, VDI_DNSDIR_MAGIC); - if (hostgr->ttl <= req->t_req) { - if (rwlock) - vdi_dns_pop_cache(vs, hostgr); - return (0); - } - if (vdi_dns_groupmatch(hostgr, hostname)) { - ret = (vdi_dns_pick_host(req, hostgr)); - *backend = ret; - if (*backend != NULL) - CHECK_OBJ_NOTNULL(*backend, DIRECTOR_MAGIC); - return (1); - } - } - return (0); -} - -/* Add a newly cached item to the dns cache list. - * (Sorry for the list_add/_add confusion...) - */ -static void -vdi_dns_cache_list_add(const struct req *req, struct vdi_dns *vs, - struct vdi_dns_hostgroup *new) -{ - - if (vs->ncachelist >= VDI_DNS_MAX_CACHE) { - VSC_C_main->dir_dns_cache_full++; - vdi_dns_pop_cache(vs, NULL); - } - CHECK_OBJ_NOTNULL(new, VDI_DNSDIR_MAGIC); - assert(new->hostname != 0); - new->ttl = req->t_req + vs->ttl; - VTAILQ_INSERT_HEAD(&vs->cachelist, new, list); - vs->ncachelist++; -} - -/* Add an item to the dns cache. - * XXX: Might want to factor the getaddrinfo() out of the lock and do the - * cache_has() afterwards to do multiple dns lookups in parallel... - */ -static int -vdi_dns_cache_add(const struct req *req, struct vdi_dns *vs, - const char *hostname, struct director **backend) -{ - int error, i, host = 0; - struct addrinfo *res0, *res, hint; - struct vdi_dns_hostgroup *new; - - /* Due to possible race while upgrading the lock, we have to - * recheck if the result is already looked up. The overhead for - * this is insignificant unless dns isn't cached properly (all - * unique names or something equally troublesome). - */ - - if (vdi_dns_cache_has(req, vs, hostname, backend, 1)) - return (1); - - memset(&hint, 0, sizeof hint); - hint.ai_family = PF_UNSPEC; - hint.ai_socktype = SOCK_STREAM; - - ALLOC_OBJ(new, VDI_DNSDIR_MAGIC); - XXXAN(new); - - REPLACE(new->hostname, hostname); - - error = getaddrinfo(hostname, "80", &hint, &res0); - VSC_C_main->dir_dns_lookups++; - if (error) { - vdi_dns_cache_list_add(req, vs, new); - VSC_C_main->dir_dns_failed++; - return (0); - } - - for (res = res0; res; res = res->ai_next) { - if (res->ai_family != PF_INET && res->ai_family != PF_INET6) - continue; - - for (i = 0; i < vs->nhosts; i++) { - struct sockaddr_storage ss_hack; - memcpy(&ss_hack, res->ai_addr, res->ai_addrlen); - if (vdi_dns_comp_addrinfo(vs->hosts[i], - &ss_hack, res->ai_addrlen)) { - new->hosts[host] = vs->hosts[i]; - CHECK_OBJ_NOTNULL(new->hosts[host], - DIRECTOR_MAGIC); - host++; - } - } - } - freeaddrinfo(res0); - - new->nhosts = host; - vdi_dns_cache_list_add(req, vs, new); - *backend = vdi_dns_pick_host(req, new); - return (1); -} - -/* Walk through the cached lookups looking for the relevant host, add one - * if it isn't already cached. - * - * Returns a backend or NULL. - */ -static struct director * -vdi_dns_walk_cache(const struct req *req, struct vdi_dns *vs, - const char *hostname) -{ - struct director *backend = NULL; - int ret; - - AZ(pthread_rwlock_rdlock(&vs->rwlock)); - ret = vdi_dns_cache_has(req, vs, hostname, &backend, 0); - AZ(pthread_rwlock_unlock(&vs->rwlock)); - if (!ret) { - /* - * XXX: Isn't there a race here where another thread - * XXX: could grab the lock and add it before we do ? - * XXX: Should 'ret' be checked for that ? - */ - AZ(pthread_rwlock_wrlock(&vs->rwlock)); - ret = vdi_dns_cache_add(req, vs, hostname, &backend); - AZ(pthread_rwlock_unlock(&vs->rwlock)); - } else - VSC_C_main->dir_dns_hit++; - - /* Bank backend == cached a failure, so to speak */ - if (backend != NULL) - CHECK_OBJ_NOTNULL(backend, DIRECTOR_MAGIC); - return (backend); -} - -/* Parses the Host:-header and heads out to find a backend. - */ -static struct director * -vdi_dns_find_backend(const struct req *req, struct vdi_dns *vs) -{ - struct director *ret; - struct http *hp; - char *p, *q; - char hostname[NI_MAXHOST]; - - /* bereq is only present after recv et. al, otherwise use req (ie: - * use req for health checks in vcl_recv and such). - */ - if (req->busyobj != NULL && req->busyobj->bereq) - hp = req->busyobj->bereq; - else - hp = req->http; - - - CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC); - if (http_GetHdr(hp, H_Host, &p) == 0) - return (NULL); - - q = strchr(p, ':'); - if (q == NULL) - q = strchr(p, '\0'); - AN(q); - - bprintf(hostname, "%.*s%s", (int)(q - p), p, - vs->suffix ? vs->suffix : ""); - - ret = vdi_dns_walk_cache(req, vs, hostname); - return (ret); -} - -static struct vbc * -vdi_dns_getfd(const struct director *director, struct req *req) -{ - struct vdi_dns *vs; - struct director *dir; - struct vbc *vbe; - - CHECK_OBJ_NOTNULL(req, REQ_MAGIC); - CHECK_OBJ_NOTNULL(director, DIRECTOR_MAGIC); - CAST_OBJ_NOTNULL(vs, director->priv, VDI_DNS_MAGIC); - - dir = vdi_dns_find_backend(req, vs); - if (!dir || !VDI_Healthy(dir, req)) - return (NULL); - - vbe = VDI_GetFd(dir, req); - return (vbe); -} - -static unsigned -vdi_dns_healthy(const struct director *dir, const struct req *req) -{ - /* XXX: Fooling -Werror for a bit until it's actually implemented. - */ - (void)dir; - (void)req; - return (1); - - /* - struct vdi_dns *vs; - struct director *dir; - int i; - - CHECK_OBJ_NOTNULL(req, REQ_MAGIC); - CHECK_OBJ_NOTNULL(req->director, DIRECTOR_MAGIC); - CAST_OBJ_NOTNULL(vs, req->director->priv, VDI_DNS_MAGIC); - - dir = vdi_dns_find_backend(req, vs); - - if (dir) - return (1); - return (0); - */ -} - -static void -vdi_dns_fini(const struct director *d) -{ - struct vdi_dns *vs; - - CHECK_OBJ_NOTNULL(d, DIRECTOR_MAGIC); - CAST_OBJ_NOTNULL(vs, d->priv, VDI_DNS_MAGIC); - - free(vs->hosts); - free(vs->dir.vcl_name); - vs->dir.magic = 0; - /* FIXME: Free the cache */ - AZ(pthread_rwlock_destroy(&vs->rwlock)); - FREE_OBJ(vs); -} - -void -VRT_init_dir_dns(struct cli *cli, struct director **bp, int idx, - const void *priv) -{ - const struct vrt_dir_dns *t; - struct vdi_dns *vs; - const struct vrt_dir_dns_entry *te; - int i; - - ASSERT_CLI(); - (void)cli; - t = priv; - ALLOC_OBJ(vs, VDI_DNS_MAGIC); - XXXAN(vs); - vs->hosts = calloc(sizeof(struct director *), t->nmember); - XXXAN(vs->hosts); - - vs->dir.magic = DIRECTOR_MAGIC; - vs->dir.priv = vs; - vs->dir.name = "dns"; - REPLACE(vs->dir.vcl_name, t->name); - vs->dir.getfd = vdi_dns_getfd; - vs->dir.fini = vdi_dns_fini; - vs->dir.healthy = vdi_dns_healthy; - - vs->suffix = t->suffix; - vs->ttl = t->ttl; - - te = t->members; - for (i = 0; i < t->nmember; i++, te++) - vs->hosts[i] = bp[te->host]; - vs->nhosts = t->nmember; - vs->ttl = t->ttl; - VTAILQ_INIT(&vs->cachelist); - AZ(pthread_rwlock_init(&vs->rwlock, NULL)); - bp[idx] = &vs->dir; -} diff --git a/bin/varnishd/cache/cache_dir_random.c b/bin/varnishd/cache/cache_dir_random.c deleted file mode 100644 index c291fe0..0000000 --- a/bin/varnishd/cache/cache_dir_random.c +++ /dev/null @@ -1,296 +0,0 @@ -/*- - * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS - * All rights reserved. - * - * Author: Poul-Henning Kamp - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This code is shared between the random, client and hash directors, because - * they share the same properties and most of the same selection logic. - * - * The random director picks a backend on random. - * - * The hash director picks based on the hash from vcl_hash{} - * - * The client director picks based on client identity or IP-address - * - * In all cases, the choice is by weight of the healthy subset of - * configured backends. - * - * Failures to get a connection are retried, here all three policies - * fall back to a deterministically random choice, by weight in the - * healthy subset. - * - */ - -#include "config.h" - -#include -#include - -#include "cache.h" - -#include "cache_backend.h" -#include "vend.h" -#include "vrt.h" -#include "vsha256.h" - -/*--------------------------------------------------------------------*/ - -struct vdi_random_host { - struct director *backend; - double weight; -}; - -enum crit_e {c_random, c_hash, c_client}; - -struct vdi_random { - unsigned magic; -#define VDI_RANDOM_MAGIC 0x3771ae23 - struct director dir; - - enum crit_e criteria; - unsigned retries; - double tot_weight; - struct vdi_random_host *hosts; - unsigned nhosts; -}; - -/* - * Applies sha256 using the given context and input/length, and returns - * a double in the range [0...1[ based on the hash. - */ -static double -vdi_random_sha(const char *input, ssize_t len) -{ - struct SHA256Context ctx; - uint8_t sign[SHA256_LEN]; - - AN(input); - SHA256_Init(&ctx); - SHA256_Update(&ctx, input, len); - SHA256_Final(sign, &ctx); - return (scalbn(vle32dec(sign), -32)); -} - -/* - * Sets up the initial seed for picking a backend according to policy. - */ -static double -vdi_random_init_seed(const struct vdi_random *vs, const struct req *req) -{ - const char *p; - double retval; - - switch (vs->criteria) { - case c_client: - if (req->client_identity != NULL) - p = req->client_identity; - else - p = req->sp->addr; - retval = vdi_random_sha(p, strlen(p)); - break; - case c_hash: - AN(req->digest); - retval = scalbn(vle32dec(req->digest), -32); - break; - case c_random: - default: - retval = scalbn(random(), -31); - break; - } - return (retval); -} - -/* - * Find the healthy backend corresponding to the weight r [0...1[ - */ -static struct vbc * -vdi_random_pick_one(struct req *req, const struct vdi_random *vs, double r, - int retries) -{ - double w[vs->nhosts]; - int i; - double s1, s2; - struct vbc *vbc; - - /* Sum up the weights of all backends */ - memset(w, 0, sizeof w); - s1 = 0.0; - for (i = 0; i < vs->nhosts; i++) { - w[i] = vs->hosts[i].weight; - s1 += w[i]; - } - if (s1 == 0.0) - return (NULL); - - while (retries-- > 0) { - assert(r >= 0.0 && r < 1.0); - - r *= s1; - s2 = 0.0; - for (i = 0; i < vs->nhosts; i++) { - s2 += w[i]; - if (r >= s2) - continue; - if (!VDI_Healthy(vs->hosts[i].backend, req)) - break; - vbc = VDI_GetFd(vs->hosts[i].backend, req); - if (vbc == NULL) - break; - return (vbc); - } - /* - * Rescale and rotate r's relative position this backends - * window onto the remaining backends and try again. - */ - r -= (s2 - w[i]); // r in [0...w[i][ - r /= w[i]; // r in [0...1[ - r *= (s1 - w[i])/s1; // r in [0...1-W[i]] - r += s2 / s1; // rotate - if (r >= 1.0) - r -= 1.0; - } - return (NULL); -} - -/* - * Try the specified number of times to get a backend. - * First one according to policy, after that, deterministically - * random by rehashing the key. - */ -static struct vbc * -vdi_random_getfd(const struct director *d, struct req *req) -{ - struct vdi_random *vs; - double r; - - CHECK_OBJ_NOTNULL(req, REQ_MAGIC); - CHECK_OBJ_NOTNULL(d, DIRECTOR_MAGIC); - CAST_OBJ_NOTNULL(vs, d->priv, VDI_RANDOM_MAGIC); - - r = vdi_random_init_seed(vs, req); - - return (vdi_random_pick_one(req, vs, r, vs->retries)); -} - -/* - * Healthy if just a single backend is... - * XXX: we should really have a weight param/criteria here - */ -static unsigned -vdi_random_healthy(const struct director *d, const struct req *req) -{ - struct vdi_random *vs; - int i; - - CHECK_OBJ_NOTNULL(d, DIRECTOR_MAGIC); - CAST_OBJ_NOTNULL(vs, d->priv, VDI_RANDOM_MAGIC); - - for (i = 0; i < vs->nhosts; i++) { - if (VDI_Healthy(vs->hosts[i].backend, req)) - return (1); - } - return (0); -} - -static void -vdi_random_fini(const struct director *d) -{ - struct vdi_random *vs; - - CHECK_OBJ_NOTNULL(d, DIRECTOR_MAGIC); - CAST_OBJ_NOTNULL(vs, d->priv, VDI_RANDOM_MAGIC); - - free(vs->hosts); - free(vs->dir.vcl_name); - vs->dir.magic = 0; - FREE_OBJ(vs); -} - -static void -vrt_init(struct cli *cli, struct director **bp, int idx, - const void *priv, enum crit_e criteria) -{ - const struct vrt_dir_random *t; - struct vdi_random *vs; - const struct vrt_dir_random_entry *te; - struct vdi_random_host *vh; - int i; - - ASSERT_CLI(); - (void)cli; - t = priv; - - ALLOC_OBJ(vs, VDI_RANDOM_MAGIC); - XXXAN(vs); - vs->hosts = calloc(sizeof *vh, t->nmember); - XXXAN(vs->hosts); - - vs->dir.magic = DIRECTOR_MAGIC; - vs->dir.priv = vs; - vs->dir.name = "random"; - REPLACE(vs->dir.vcl_name, t->name); - vs->dir.getfd = vdi_random_getfd; - vs->dir.fini = vdi_random_fini; - vs->dir.healthy = vdi_random_healthy; - - vs->criteria = criteria; - vs->retries = t->retries; - if (vs->retries == 0) - vs->retries = t->nmember; - vh = vs->hosts; - te = t->members; - vs->tot_weight = 0.; - for (i = 0; i < t->nmember; i++, vh++, te++) { - assert(te->weight > 0.0); - vh->weight = te->weight; - vs->tot_weight += vh->weight; - vh->backend = bp[te->host]; - AN(vh->backend); - } - vs->nhosts = t->nmember; - bp[idx] = &vs->dir; -} - -void -VRT_init_dir_random(struct cli *cli, struct director **bp, int idx, - const void *priv) -{ - vrt_init(cli, bp, idx, priv, c_random); -} - -void -VRT_init_dir_hash(struct cli *cli, struct director **bp, int idx, - const void *priv) -{ - vrt_init(cli, bp, idx, priv, c_hash); -} - -void -VRT_init_dir_client(struct cli *cli, struct director **bp, int idx, - const void *priv) -{ - vrt_init(cli, bp, idx, priv, c_client); -} diff --git a/bin/varnishtest/tests/r00971.vtc b/bin/varnishtest/tests/r00971.vtc deleted file mode 100644 index 232f568..0000000 --- a/bin/varnishtest/tests/r00971.vtc +++ /dev/null @@ -1,25 +0,0 @@ - -varnishtest "Test DNS director order" - -varnish v1 -vcl { - - backend test { - .host = "192.168.0.1"; - } - - director foo dns { - { .backend = { .host = "127.0.0.1";} } - .list = { - "192.168.0.0"/24; - } - } - - sub vcl_recv { - set req.backend = foo; - if (req.http.x-aa) { - set req.backend = test; - } - } - -} -start - diff --git a/bin/varnishtest/tests/r00977.vtc b/bin/varnishtest/tests/r00977.vtc deleted file mode 100644 index d15b55d..0000000 --- a/bin/varnishtest/tests/r00977.vtc +++ /dev/null @@ -1,46 +0,0 @@ - -varnishtest "Test proper fallbacks of client director" - -server s1 { - rxreq - txresp -status 200 - accept - rxreq - txresp -status 200 -} -start - -varnish v1 -vcl+backend { - director foo client{ - .retries = 5; - { .backend = { .host = "${bad_ip}"; .port = "9090"; } .weight = 1; } - { .backend = s1; .weight = 1;} - } - director bar client{ - .retries = 1; - { .backend = { .host = "${bad_ip}"; .port = "9090"; } .weight = 1; } - { .backend = s1; .weight = 1;} - } - sub vcl_recv { - if (req.url ~ "/one") { - set req.backend = foo; - } else { - set req.backend = bar; - } - # Carefully chosen seed that'll give us bad backend on - # first try and good on second. - set client.identity = "1.4"; - return (pass); - } -} -start - -client c1 { - txreq -url "/one" - rxresp - expect resp.status == 200 - - txreq -url "/two" - rxresp - expect resp.status == 503 -} -run - -varnish v1 -expect backend_fail == 2 diff --git a/bin/varnishtest/tests/r01060.vtc b/bin/varnishtest/tests/r01060.vtc deleted file mode 100644 index 25a3988..0000000 --- a/bin/varnishtest/tests/r01060.vtc +++ /dev/null @@ -1,48 +0,0 @@ -varnishtest "DNS director tramples on other backends" - -server s1 { - rxreq - txresp -} -start - -server s2 { - rxreq - txresp -} -start - -varnish v1 -vcl { - backend b1 { - .host = "${s1_addr}"; - .port = "${s1_port}"; - } - - director d1 dns { - .list = { - .port = "80"; - "${bad_ip}"/32; - } - .ttl = 1m; - } - - backend b2 { - .host = "${s2_addr}"; - .port = "${s2_port}"; - } - - sub vcl_recv { - set req.backend = d1; - if (req.url == "/1") { - set req.backend = b1; - } else { - set req.backend = b2; - } - } -} -start - - -client c1 { - txreq -url "/1" - rxresp - txreq -url "/2" - rxresp -} -run diff --git a/bin/varnishtest/tests/v00002.vtc b/bin/varnishtest/tests/v00002.vtc deleted file mode 100644 index c17dc0b..0000000 --- a/bin/varnishtest/tests/v00002.vtc +++ /dev/null @@ -1,189 +0,0 @@ -varnishtest "VCL: test syntax/semantic checks on backend decls. (vcc_backend.c)" - -# Missing backend -varnish v1 -errvcl {No backends or directors found in VCL program} { -} - -# Reference to non-existent backend -varnish v1 -errvcl {Symbol not found: 'b2' (expected type BACKEND):} { - backend b1 { - .host = "127.0.0.1"; - } - sub vcl_recv { - set req.backend = b2; - } -} - -# Missing .host -varnish v1 -errvcl {Mandatory field 'host' missing.} { - backend b1 { - .port = "http"; - } -} - -# Too many .host -varnish v1 -errvcl {Field 'host' redefined at:} { - backend b1 { - .host = "foo"; - .host = "bar"; - } -} - -# Too many .port -varnish v1 -errvcl {Field 'port' redefined at:} { - backend b1 { - .host = "foo"; - .port = "http"; - .port = "https"; - } -} - -# Too many .connect_timeout -varnish v1 -errvcl {Field 'connect_timeout' redefined at:} { - backend b1 { - .host = "foo"; - .connect_timeout = 1m; - .connect_timeout = 1m; - } -} - -# unknown field -varnish v1 -errvcl {Unknown field: 'foobar' at} { - backend b1 { - .host = "127.0.0.1"; - .foobar = 123; - } -} - -# Check backend reference by name -varnish v1 -errvcl {Expected a backend host specification here, either by name or by {...}} { - backend b1 { .host = "${bad_ip}"; } - director r1 random { - { .weight = 1; .backend = b1; } - { .weight = 1; .backend = { .host = "127.0.0.3"; } } - { .weight = 1; .backend = 3745; } // Brownie points for getting the joke - } -} - -# Check backend reference by name -varnish v1 -errvcl "Expected '{' got 'b1'" { - backend b1 { .host = "${bad_ip}"; } - backend b2 b1; -} - -# Check backend reference by non-C-compat name -varnish v1 -errvcl {Identifier 'b-1' contains illegal characters, use [0-9a-zA-Z_] only.} { - backend b-1 { .host = "${bad_ip}"; } -} - -# Check backend reference by non-C-compat name -varnish v1 -errvcl {Symbol not found: 'b-1' (expected type BACKEND):} { - backend b1 { .host = "${bad_ip}"; } - sub vcl_recv { - set req.backend = b-1; - } -} - -# Old backend syntax -varnish v1 -errvcl {Remove "set" and "backend" in front of backend fields.} { - backend b1 { - set host = "127.0.0.1"; - } -} - -# Too many .connect_timeout -varnish v1 -errvcl {Unknown time unit 'q'. Legal are 's', 'm', 'h' and 'd'} { - backend b1 { - .host = "foo"; - .connect_timeout = 1 q; - } -} - -# Two clashing backends -varnish v1 -errvcl {Backend b1 redefined} { - backend b1 { .host = "127.0.0.1"; } - backend b1 { .host = "127.0.0.1"; } -} - -# Unknown director policy -varnish v1 -errvcl {Unknown director policy: 'anarchy' at} { - director r1 anarchy { .host = "127.0.0.1"; } -} - -varnish v1 -errvcl {Backend host "v00002.freebsd.dk": resolves to multiple ipv4 addresses.} { - /* too many IP numbers */ - backend b1 { .host = "v00002.freebsd.dk"; } -} - -varnish v1 -errvcl {Backend host '"////."' could not be resolved to an IP address:} { - backend b1 { .host = "////."; } -} - -varnish v1 -errvcl {Backend host '"127.0.0.1"' could not be resolved to an IP address:} { - backend b1 { .host = "127.0.0.1"; .port = "////."; } -} - -varnish v1 -errvcl {Unknown field: 'foobar' at} { - backend b1 { - .host = "127.0.0.1"; - .foobar = "foo"; - } -} - -varnish v1 -errvcl {Unknown field: 'ice' at} { - backend b1 { - .host = "127.0.0.1"; - .probe = { - .ice = "vanilla"; - } - } -} - -varnish v1 -errvcl {Must specify .threshold with .window} { - backend b1 { - .host = "127.0.0.1"; - .probe = { .window = 8; } - } -} - -varnish v1 -errvcl {Threshold must be 64 or less.} { - backend b1 { - .host = "127.0.0.1"; - .probe = { .threshold = 65; } - } -} - -varnish v1 -vcl { - backend b1 { - .host = "127.0.0.1"; - .probe = { .threshold = 64; } - } -} - -varnish v1 -errvcl {Window must be 64 or less.} { - backend b1 { - .host = "127.0.0.1"; - .probe = { .threshold = 32; .window = 65; } - } -} - -varnish v1 -vcl { - backend b1 { - .host = "127.0.0.1"; - .probe = { .threshold = 32; .window = 64; } - } -} - -varnish v1 -errvcl {Threshold can not be greater than window.} { - backend b1 { - .host = "127.0.0.1"; - .probe = { .threshold = 32; .window = 31; } - } -} - -varnish v1 -errvcl {Must specify .expected_response with exactly three digits (100 <= x <= 999)} { - backend b1 { - .host = "127.0.0.1"; - .probe = { .expected_response = 13; } - } -} diff --git a/bin/varnishtest/tests/v00003.vtc b/bin/varnishtest/tests/v00003.vtc deleted file mode 100644 index f519721..0000000 --- a/bin/varnishtest/tests/v00003.vtc +++ /dev/null @@ -1,59 +0,0 @@ -varnishtest "VCL: test syntax/semantic checks on director decls." - -# syntax in inline backend -varnish v1 -errvcl {Unknown field: 'foo' at} { - director r1 random { - { .backend = { .foo = 2; }; .weight = 1;} - } -} - -# reference to unknown backend host -varnish v1 -errvcl {Reference to unknown backend 'b2' at} { - director r1 random { - { .backend = b2; .weight = 1; } - } -} - -# missing backend -varnish v1 -errvcl {Mandatory field 'backend' missing.} { - director r1 random { - { .weight = 1; } - } -} - -# invalid weight -varnish v1 -errvcl {Expected CNUM got 'k'} { - director r1 random { - { .backend = {.host = "127.0.0.1";} .weight = k; } - } -} - -# invalid weight -varnish v1 -errvcl {The .weight must be higher than zero.} { - director r1 random { - { .backend = {.host = "127.0.0.1";} .weight = 0; } - } -} - -# retries spec -varnish v1 -vcl { - director r1 random { - .retries = 3; - { .backend = {.host = "127.0.0.1";} .weight = 1; } - } -} - -varnish v1 -errvcl {Unknown field: 'foobar' at} { - director r1 random { - .foobar = 3; - { .backend = {.host = "127.0.0.1";} .weight = 1; } - } -} - -varnish v1 -errvcl {Expected CNUM got 'x'} { - director r1 random { - .retries = x; - { .backend = {.host = "127.0.0.1";} .weight = 1; } - } -} - diff --git a/bin/varnishtest/tests/v00004.vtc b/bin/varnishtest/tests/v00004.vtc deleted file mode 100644 index b5419a1..0000000 --- a/bin/varnishtest/tests/v00004.vtc +++ /dev/null @@ -1,73 +0,0 @@ -varnishtest "VCL: test creation/destruction of backends" - -varnish v1 -vcl { - backend b1 { - .host = "127.0.0.1"; - } -} - -varnish v1 -cli vcl.list -varnish v1 -start -varnish v1 -expect n_backend == 1 - -varnish v1 -vcl { - backend b1 { - .host = "127.0.0.1"; - } -} - -varnish v1 -expect n_backend == 1 -varnish v1 -expect n_vcl == 2 - - -varnish v1 -vcl { - backend b2 { - .host = "127.0.0.1"; - } -} - -varnish v1 -expect n_backend == 2 -# give the expiry thread a chance to let go of its VCL -delay 2 -varnish v1 -expect n_vcl == 3 - - -varnish v1 -cli "vcl.discard vcl1" - -varnish v1 -expect n_backend == 2 -varnish v1 -expect n_vcl == 2 - -varnish v1 -cli "vcl.discard vcl2" - -varnish v1 -expect n_backend == 1 -varnish v1 -expect n_vcl == 1 - - -varnish v1 -vcl { - backend b2 { - .host = "127.0.0.1"; - } - director r1 random { - { .backend = { .host = "127.0.0.1"; } .weight = 1; } - { .backend = b2 ; .weight = 1; } - } - sub vcl_recv { - set req.backend = r1; - } -} - -varnish v1 -expect n_backend == 2 -varnish v1 -expect n_vcl == 2 - -varnish v1 -cli "vcl.use vcl3" - -varnish v1 -expect n_backend == 2 -varnish v1 -expect n_vcl == 2 - -varnish v1 -cli "vcl.discard vcl4" -varnish v1 -cli "vcl.list" -delay 1 -varnish v1 -cli "vcl.list" - -varnish v1 -expect n_backend == 1 -varnish v1 -expect n_vcl == 1 diff --git a/bin/varnishtest/tests/v00028.vtc b/bin/varnishtest/tests/v00028.vtc deleted file mode 100644 index c956517..0000000 --- a/bin/varnishtest/tests/v00028.vtc +++ /dev/null @@ -1,57 +0,0 @@ -varnishtest "Client director" - -server s1 { - rxreq - txresp -hdr "be: s1" -bodylen 1 -} -start - -server s2 { - rxreq - txresp -hdr "be: s2" -bodylen 2 - rxreq - txresp -hdr "be: s2" -bodylen 4 -} -start - -varnish v1 -vcl+backend { - director d1 client { - { .backend = s1; .weight = 1; } - { .backend = s2; .weight = 1; } - } - - sub vcl_recv { - set req.backend = d1; - if (req.http.id) { - set client.identity = req.http.id; - } - return (pass); - } - sub vcl_fetch { - set beresp.http.be_ip = beresp.backend.ip; - set beresp.http.be_port = beresp.backend.port; - set beresp.http.be_name = beresp.backend.name; - } - sub vcl_deliver { - set resp.http.id = client.identity; - } -} -start - - -client c1 { - txreq - rxresp - expect resp.http.id == "127.0.0.1" - expect resp.http.be == s2 - expect resp.bodylen == 2 - - txreq -hdr "id: foo" - rxresp - expect resp.http.id == "foo" - expect resp.http.be == s1 - expect resp.bodylen == 1 - - txreq -hdr "id: baz" - rxresp - expect resp.http.id == "baz" - expect resp.http.be == s2 - expect resp.bodylen == 4 -} -run diff --git a/bin/varnishtest/tests/v00029.vtc b/bin/varnishtest/tests/v00029.vtc deleted file mode 100644 index 6da2315..0000000 --- a/bin/varnishtest/tests/v00029.vtc +++ /dev/null @@ -1,43 +0,0 @@ -varnishtest "DNS director" - -server s1 { - rxreq - txresp -} -start - -varnish v1 -vcl+backend { - director d1 dns { - { .backend = s1; } - } - - sub vcl_recv { - set req.backend = d1; - return (pass); - } -} -start - - -client c1 { - txreq -hdr "Host: localhost" - rxresp - expect resp.status == 200 - - txreq -hdr "Host: .......coco-x-zamzam-i-cant-bother-making-it-random" - rxresp - expect resp.status == 503 -} -run - -varnish v2 -vcl { - - director directorname dns { - .list = { - .host_header = "www.example.com"; - .port = "80"; - .connect_timeout = 0.4s; - "192.168.15.0"/24; - "192.168.16.128"/25; - } - .ttl = 5m; - .suffix = "internal.example.net"; - } -} diff --git a/bin/varnishtest/tests/v00030.vtc b/bin/varnishtest/tests/v00030.vtc deleted file mode 100644 index 9e855ec..0000000 --- a/bin/varnishtest/tests/v00030.vtc +++ /dev/null @@ -1,63 +0,0 @@ -varnishtest "DNS director bad VCL tests" - -varnish v1 -errvcl {Expected '.' got '192'} { - director directorname dns { - .list = { - 192.168.15.0/24; - } - } -} - -varnish v1 -errvcl "Expected '.' got '}'" { - director directorname dns { - .list = { - .host_header = "www.example.com"; - .port = "80"; - .connect_timeout = 0.4s; - } - } -} - -varnish v9 -errvcl {Unknown field: 'host_hdr' at} { - director directorname dns { - .list = { - .host_hdr = "192.168.1.1"; - "192.168.1.2"; - } - } -} -varnish v1 -errvcl {Unknown field: 'host_hdr' at} { - director directorname dns { - .list = { - .host_hdr = "www.example.com"; - "192.168.16.128"/25; - } - } -} - -varnish v1 -errvcl {Expected CSTR got '80'} { - director directorname dns { - .list = { - .port = 80; - "192.168.15.0"/24; - } - } -} - -# XXX: reported token should be improved -varnish v1 -errvcl {IP and network mask not compatible: ';' at} { - director directorname dns { - .list = { - "192.168.15.0"/33; - } - } -} - -# XXX: reported token should be improved -varnish v1 -errvcl {IP and network mask not compatible: ';' at} { - director directorname dns { - .list = { - "192.168.16.255"/24; - } - } -} diff --git a/lib/libvcl/Makefile.am b/lib/libvcl/Makefile.am index 88c8f75..ebe0526 100644 --- a/lib/libvcl/Makefile.am +++ b/lib/libvcl/Makefile.am @@ -17,8 +17,6 @@ libvcl_la_SOURCES = \ vcc_backend.c \ vcc_backend_util.c \ vcc_compile.c \ - vcc_dir_random.c \ - vcc_dir_dns.c \ vcc_expr.c \ vcc_parse.c \ vcc_fixed_token.c \ diff --git a/lib/libvcl/vcc_backend.c b/lib/libvcl/vcc_backend.c index 47e3280..d5f216e 100644 --- a/lib/libvcl/vcc_backend.c +++ b/lib/libvcl/vcc_backend.c @@ -107,7 +107,7 @@ struct foo_proto { socklen_t l; }; -void +static void Emit_Sockaddr(struct vcc *tl, const struct token *t_host, const char *port) { struct foo_proto protos[3], *pp; @@ -586,68 +586,6 @@ vcc_ParseHostDef(struct vcc *tl, int serial, const char *vgcname) } /*-------------------------------------------------------------------- - * Parse and emit a backend host specification. - * - * The syntax is the following: - * - * backend_spec: - * name_of_backend # by reference - * '{' be_elements '}' # by specification - * - * The struct vrt_backend is emitted to Fh(). - */ - -void -vcc_ParseBackendHost(struct vcc *tl, int serial, char **nm) -{ - struct host *h; - struct token *t; - char vgcname[BUFSIZ]; - - AN(nm); - *nm = NULL; - if (tl->t->tok == ID) { - VTAILQ_FOREACH(h, &tl->hosts, list) { - if (vcc_Teq(h->name, tl->t)) - break; - } - if (h == NULL) { - VSB_printf(tl->sb, "Reference to unknown backend "); - vcc_ErrToken(tl, tl->t); - VSB_printf(tl->sb, " at\n"); - vcc_ErrWhere(tl, tl->t); - return; - } - vcc_AddRef(tl, h->name, SYM_BACKEND); - vcc_NextToken(tl); - SkipToken(tl, ';'); - *nm = h->vgcname; - } else if (tl->t->tok == '{') { - t = tl->t; - - sprintf(vgcname, "%.*s_%d", PF(tl->t_dir), serial); - - vcc_ParseHostDef(tl, serial, vgcname); - if (tl->err) { - VSB_printf(tl->sb, - "\nIn backend host specification starting at:\n"); - vcc_ErrWhere(tl, t); - } - *nm = strdup(vgcname); /* XXX */ - - return; - } else { - VSB_printf(tl->sb, - "Expected a backend host specification here, " - "either by name or by {...}\n"); - vcc_ErrToken(tl, tl->t); - VSB_printf(tl->sb, " at\n"); - vcc_ErrWhere(tl, tl->t); - return; - } -} - -/*-------------------------------------------------------------------- * Tell rest of compiler about a backend */ @@ -696,25 +634,10 @@ vcc_ParseSimpleDirector(struct vcc *tl) * Parse directors and backends */ - -static const struct dirlist { - const char *name; - parsedirector_f *func; -} dirlist[] = { - { "hash", vcc_ParseRandomDirector }, - { "random", vcc_ParseRandomDirector }, - { "client", vcc_ParseRandomDirector }, - { "round-robin", NULL }, - { "fallback", NULL }, - { "dns", vcc_ParseDnsDirector }, - { NULL, NULL } -}; - void vcc_ParseDirector(struct vcc *tl) { struct token *t_first; - struct dirlist const *dl; int isfirst; t_first = tl->t; @@ -738,45 +661,10 @@ vcc_ParseDirector(struct vcc *tl) tl->t_policy = t_first; vcc_ParseSimpleDirector(tl); } else { - vcc_DefBackend(tl, tl->t_dir); - ERRCHK(tl); - ExpectErr(tl, ID); /* ID: policy */ - tl->t_policy = tl->t; - vcc_NextToken(tl); - - for (dl = dirlist; dl->name != NULL; dl++) - if (vcc_IdIs(tl->t_policy, dl->name)) - break; - if (dl->name == NULL) { - VSB_printf(tl->sb, "Unknown director policy: "); - vcc_ErrToken(tl, tl->t_policy); - VSB_printf(tl->sb, " at\n"); - vcc_ErrWhere(tl, tl->t_policy); - return; - } - if (dl->func == NULL) { - VSB_printf(tl->sb, - "\n%.*s director are now in VMOD.directors\n", - PF(tl->t_policy)); - vcc_ErrWhere(tl, tl->t_policy); - return; - } - Ff(tl, 0, "\tVRT_fini_dir(cli, VGCDIR(_%.*s));\n", - PF(tl->t_dir)); - SkipToken(tl, '{'); - dl->func(tl); - if (!tl->err) - SkipToken(tl, '}'); - Fh(tl, 1, "\n#define VGC_backend__%.*s %d\n", - PF(tl->t_dir), tl->ndirector); - tl->ndirector++; - Fi(tl, 0, - "\tVRT_init_dir(cli, VCL_conf.director, \"%.*s\",\n", - PF(tl->t_policy)); - Fi(tl, 0, "\t VGC_backend__%.*s, &vgc_dir_priv_%.*s);\n", - PF(tl->t_dir), PF(tl->t_dir)); - - + VSB_printf(tl->sb, + "\ndirectors are now in VMOD.directors\n"); + vcc_ErrWhere(tl, tl->t_policy); + return; } if (tl->err) { VSB_printf(tl->sb, diff --git a/lib/libvcl/vcc_backend_util.c b/lib/libvcl/vcc_backend_util.c index efba623..de361a5 100644 --- a/lib/libvcl/vcc_backend_util.c +++ b/lib/libvcl/vcc_backend_util.c @@ -51,7 +51,7 @@ struct fld_spec { struct token *found; }; -void +static void vcc_ResetFldSpec(struct fld_spec *f) { diff --git a/lib/libvcl/vcc_compile.h b/lib/libvcl/vcc_compile.h index 65e5dff..fb3a969 100644 --- a/lib/libvcl/vcc_compile.h +++ b/lib/libvcl/vcc_compile.h @@ -227,19 +227,13 @@ int vcc_ParseAction(struct vcc *tl); /* vcc_backend.c */ struct fld_spec; -typedef void parsedirector_f(struct vcc *tl); void vcc_ParseProbe(struct vcc *tl); void vcc_ParseDirector(struct vcc *tl); -void vcc_ParseBackendHost(struct vcc *tl, int serial, char **nm); struct fld_spec * vcc_FldSpec(struct vcc *tl, const char *first, ...); -void vcc_ResetFldSpec(struct fld_spec *f); void vcc_IsField(struct vcc *tl, struct token **t, struct fld_spec *fs); void vcc_FieldsOk(struct vcc *tl, const struct fld_spec *fs); -void Emit_Sockaddr(struct vcc *tl, const struct token *t_host, - const char *port); - /* vcc_compile.c */ extern struct method method_tab[]; /* @@ -269,9 +263,6 @@ char *TlDupTok(struct vcc *tl, const struct token *tok); void EncString(struct vsb *sb, const char *b, const char *e, int mode); -/* vcc_dir_random.c */ -parsedirector_f vcc_ParseRandomDirector; - /* vcc_expr.c */ void vcc_Duration(struct vcc *tl, double *); unsigned vcc_UintVal(struct vcc *tl); @@ -284,9 +275,6 @@ void vcc_Eval_Func(struct vcc *tl, const char *cfunc, const char *extra, const char *name, const char *args); sym_expr_t vcc_Eval_Backend; -/* vcc_dir_dns.c */ -parsedirector_f vcc_ParseDnsDirector; - /* vcc_obj.c */ extern const struct var vcc_vars[]; @@ -319,7 +307,6 @@ void vcc_ErrWhere(struct vcc *, const struct token *); void vcc_ErrWhere2(struct vcc *, const struct token *, const struct token *); void vcc__Expect(struct vcc *tl, unsigned tok, unsigned line); -int vcc_Teq(const struct token *t1, const struct token *t2); int vcc_IdIs(const struct token *t, const char *p); void vcc_ExpectCid(struct vcc *tl); void vcc_Lexer(struct vcc *tl, struct source *sp); diff --git a/lib/libvcl/vcc_dir_dns.c b/lib/libvcl/vcc_dir_dns.c deleted file mode 100644 index 4d61585..0000000 --- a/lib/libvcl/vcc_dir_dns.c +++ /dev/null @@ -1,359 +0,0 @@ -/*- - * Copyright (c) 2009-2010 Varnish Software AS - * All rights reserved. - * - * Author: Kristian Lyngstol - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "config.h" - -#include -#include -#include - -#include "vcc_compile.h" - -/*-------------------------------------------------------------------- - * Parse directors - */ - -static struct vcc_dir_backend_defaults { - char *port; - char *hostheader; - double connect_timeout; - double first_byte_timeout; - double between_bytes_timeout; - unsigned max_connections; - unsigned saint; -} b_defaults; - -static void -vcc_dir_initialize_defaults(void) -{ - b_defaults.port = NULL; - b_defaults.hostheader = NULL; - b_defaults.connect_timeout = -1.0; - b_defaults.first_byte_timeout = -1.0; - b_defaults.between_bytes_timeout = -1.0; - b_defaults.max_connections = UINT_MAX; - b_defaults.saint = UINT_MAX; -} - -static const struct token *dns_first; - -static void -print_backend(struct vcc *tl, - int serial, - const uint8_t *ip) -{ - char vgcname[BUFSIZ]; - char strip[16]; - struct token tmptok; - struct vsb *vsb; - - bprintf(strip, "%u.%u.%u.%u", ip[3], ip[2], ip[1], ip[0]); - tmptok.dec = strip; - bprintf(vgcname, "%.*s_%d", PF(tl->t_dir), serial); - vsb = VSB_new_auto(); - AN(vsb); - tl->fb = vsb; - Fc(tl, 0, "\t{ .host = VGC_backend_%s },\n",vgcname); - Fh(tl, 1, "\n#define VGC_backend_%s %d\n", vgcname, tl->ndirector); - - Fb(tl, 0, "\nstatic const struct vrt_backend vgc_dir_priv_%s = {\n", - vgcname); - - Fb(tl, 0, "\t.vcl_name = \"%.*s", PF(tl->t_dir)); - if (serial >= 0) - Fb(tl, 0, "[%d]", serial); - Fb(tl, 0, "\",\n"); - Emit_Sockaddr(tl, &tmptok, b_defaults.port ? b_defaults.port : "80"); - - Fb(tl, 0, "\t.hosthdr = \""); - if (b_defaults.hostheader != NULL) - Fb(tl, 0, "%s", b_defaults.hostheader); - else - Fb(tl, 0, "%s", strip); - Fb(tl, 0, "\",\n"); - - Fb(tl, 0, "\t.saintmode_threshold = %d,\n",b_defaults.saint); -#define FB_TIMEOUT(type) do { \ - if (b_defaults.type != -1.0) \ - Fb(tl, 0, "\t.%s = %g,\n",#type,b_defaults.type); \ - } while (0) - FB_TIMEOUT(connect_timeout); - FB_TIMEOUT(first_byte_timeout); - FB_TIMEOUT(between_bytes_timeout); - - Fb(tl, 0, "};\n"); - tl->fb = NULL; - AZ(VSB_finish(vsb)); - Fh(tl, 0, "%s", VSB_data(vsb)); - VSB_delete(vsb); - Fi(tl, 0, "\tVRT_init_dir(cli, VCL_conf.director, \"simple\",\n" - "\t VGC_backend_%s, &vgc_dir_priv_%s);\n", vgcname, vgcname); - Ff(tl, 0, "\tVRT_fini_dir(cli, VGCDIR(%s));\n", vgcname); - tl->ndirector++; -} - -/* - * Output backends for all IPs in the range supplied by - * "a[0].a[1].a[2].a[3]/inmask". - * - * XXX: - * This assumes that a uint32_t can be safely accessed as an array of 4 - * uint8_ts. - */ -static void -vcc_dir_dns_makebackend(struct vcc *tl, - int *serial, - const unsigned char a[], - int inmask) -{ - uint32_t ip4=0; - uint32_t ip4end; - uint32_t mask = UINT32_MAX << (32-inmask); - - ip4 |= a[0] << 24; - ip4 |= a[1] << 16; - ip4 |= a[2] << 8; - ip4 |= a[3] ; - - ip4end = ip4 | ~mask; - if (ip4 != (ip4 & mask)) { - VSB_printf(tl->sb, "IP and network mask not compatible: "); - vcc_ErrToken(tl, tl->t); - VSB_printf(tl->sb, " at\n"); - vcc_ErrWhere(tl, tl->t); - ERRCHK(tl); - } - - while (ip4 <= ip4end) { - uint8_t *b; - b=(uint8_t *)&ip4; - (*serial)++; - print_backend(tl, *serial, b); - ip4++; - } -} - -static void -vcc_dir_dns_parse_backend_options(struct vcc *tl) -{ - struct fld_spec *fs; - struct token *t_field; - double t; - unsigned u; - vcc_dir_initialize_defaults(); - fs = vcc_FldSpec(tl, - "?port", - "?host_header", - "?connect_timeout", - "?first_byte_timeout", - "?between_bytes_timeout", - "?max_connections", - "?saintmode_threshold", - NULL); - while (tl->t->tok != CSTR) { - - vcc_IsField(tl, &t_field, fs); - ERRCHK(tl); - if (vcc_IdIs(t_field, "port")) { - ExpectErr(tl, CSTR); - assert(tl->t->dec != NULL); - b_defaults.port = strdup(tl->t->dec); - assert(b_defaults.port); - vcc_NextToken(tl); - SkipToken(tl, ';'); - } else if (vcc_IdIs(t_field, "host_header")) { - ExpectErr(tl, CSTR); - assert(tl->t->dec != NULL); - b_defaults.hostheader = strdup(tl->t->dec); - assert(b_defaults.hostheader); - vcc_NextToken(tl); - SkipToken(tl, ';'); - } else if (vcc_IdIs(t_field, "connect_timeout")) { - vcc_Duration(tl, &t); - ERRCHK(tl); - b_defaults.connect_timeout = t; - SkipToken(tl, ';'); - } else if (vcc_IdIs(t_field, "first_byte_timeout")) { - vcc_Duration(tl, &t); - ERRCHK(tl); - b_defaults.first_byte_timeout = t; - SkipToken(tl, ';'); - } else if (vcc_IdIs(t_field, "between_bytes_timeout")) { - vcc_Duration(tl, &t); - ERRCHK(tl); - b_defaults.between_bytes_timeout = t; - SkipToken(tl, ';'); - } else if (vcc_IdIs(t_field, "max_connections")) { - u = vcc_UintVal(tl); - ERRCHK(tl); - SkipToken(tl, ';'); - b_defaults.max_connections = u; - } else if (vcc_IdIs(t_field, "saintmode_threshold")) { - u = vcc_UintVal(tl); - /* UINT_MAX == magic number to mark as unset, so - * not allowed here. - */ - if (u == UINT_MAX) { - VSB_printf(tl->sb, - "Value outside allowed range: "); - vcc_ErrToken(tl, tl->t); - VSB_printf(tl->sb, " at\n"); - vcc_ErrWhere(tl, tl->t); - } - ERRCHK(tl); - b_defaults.saint = u; - SkipToken(tl, ';'); - } else { - ErrInternal(tl); - return; - } - - } -} - -/* Parse a list of backends with optional /mask notation, then print out - * all relevant backends. - */ -static void -vcc_dir_dns_parse_list(struct vcc *tl, int *serial) -{ - unsigned char a[4],mask; - int ret; - ERRCHK(tl); - SkipToken(tl, '{'); - if (tl->t->tok != CSTR) { - vcc_dir_dns_parse_backend_options(tl); - ERRCHK(tl); - } - - while (tl->t->tok == CSTR) { - mask = 32; - ret = sscanf(tl->t->dec, "%hhu.%hhu.%hhu.%hhu", - &a[0], &a[1], &a[2], &a[3]); - if (ret != 4) { - VSB_printf(tl->sb, "Incomplete IP supplied: "); - vcc_ErrToken(tl, tl->t); - VSB_printf(tl->sb, " at\n"); - vcc_ErrWhere(tl, tl->t); - ERRCHK(tl); - } - - vcc_NextToken(tl); - if (tl->t->tok == '/') { - vcc_NextToken(tl); - mask = vcc_UintVal(tl); - ERRCHK(tl); - } - vcc_dir_dns_makebackend(tl,serial,a,mask); - SkipToken(tl,';'); - } - ExpectErr(tl, '}'); -} - -void -vcc_ParseDnsDirector(struct vcc *tl) -{ - struct token *t_field, *t_be, *t_suffix = NULL; - double ttl = 60.0; - int nelem = 0; - struct fld_spec *fs; - const char *first; - char *p; - dns_first = tl->t; - tl->fb = tl->fc; - fs = vcc_FldSpec(tl, "!backend", "?ttl", "?suffix","?list", NULL); - - Fc(tl, 0, "\nstatic const struct vrt_dir_dns_entry " - "vddnse_%.*s[] = {\n", PF(tl->t_dir)); - - for (; tl->t->tok != '}'; ) { /* List of members */ - if (tl->t->tok == '{') { - nelem++; - first = ""; - t_be = tl->t; - vcc_ResetFldSpec(fs); - - ExpectErr(tl, '{'); - vcc_NextToken(tl); - Fc(tl, 0, "\t{"); - - while (tl->t->tok != '}') { /* Member fields */ - vcc_IsField(tl, &t_field, fs); - ERRCHK(tl); - if (vcc_IdIs(t_field, "backend")) { - vcc_ParseBackendHost(tl, nelem, &p); - ERRCHK(tl); - AN(p); - Fc(tl, 0, "%s .host = VGC_backend_%s", - first, p); - } else { - ErrInternal(tl); - } - first = ", "; - } - vcc_FieldsOk(tl, fs); - if (tl->err) { - VSB_printf(tl->sb, "\nIn member host" - " specification starting at:\n"); - vcc_ErrWhere(tl, t_be); - return; - } - Fc(tl, 0, " },\n"); - } else { - vcc_IsField(tl, &t_field, fs); - ERRCHK(tl); - if (vcc_IdIs(t_field, "suffix")) { - ExpectErr(tl, CSTR); - t_suffix = tl->t; - vcc_NextToken(tl); - ExpectErr(tl, ';'); - } else if (vcc_IdIs(t_field, "ttl")) { - vcc_Duration(tl, &ttl); - ExpectErr(tl, ';'); - } else if (vcc_IdIs(t_field, "list")) { - vcc_dir_dns_parse_list(tl,&nelem); - } - } - vcc_NextToken(tl); - } - Fc(tl, 0, "};\n"); - Fc(tl, 0, "\nstatic const struct vrt_dir_dns vgc_dir_priv_%.*s = {\n", - PF(tl->t_dir)); - Fc(tl, 0, "\t.name = \"%.*s\",\n", PF(tl->t_dir)); - Fc(tl, 0, "\t.nmember = %d,\n", nelem); - Fc(tl, 0, "\t.members = vddnse_%.*s,\n", PF(tl->t_dir)); - Fc(tl, 0, "\t.suffix = "); - if (t_suffix) - Fc(tl, 0, "%.*s", PF(t_suffix)); - else - Fc(tl, 0, "\"\""); - Fc(tl, 0, ",\n"); - Fc(tl, 0, "\t.ttl = %f", ttl); - Fc(tl, 0, ",\n"); - Fc(tl, 0, "};\n"); -} diff --git a/lib/libvcl/vcc_dir_random.c b/lib/libvcl/vcc_dir_random.c deleted file mode 100644 index e647bfd..0000000 --- a/lib/libvcl/vcc_dir_random.c +++ /dev/null @@ -1,125 +0,0 @@ -/*- - * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2010 Varnish Software AS - * All rights reserved. - * - * Author: Poul-Henning Kamp - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "config.h" - -#include "vcc_compile.h" - -/*-------------------------------------------------------------------- - * Parse directors - */ - -void -vcc_ParseRandomDirector(struct vcc *tl) -{ - struct token *t_field, *t_be, *t_x; - int nelem; - struct fld_spec *fs, *mfs; - unsigned u, retries; - const char *first; - char *p; - - fs = vcc_FldSpec(tl, "?retries", NULL); - - retries = 0; - while (tl->t->tok != '{') { - vcc_IsField(tl, &t_field, fs); - ERRCHK(tl); - if (vcc_IdIs(t_field, "retries")) { - ExpectErr(tl, CNUM); - retries = vcc_UintVal(tl); - ERRCHK(tl); - SkipToken(tl, ';'); - } else { - ErrInternal(tl); - } - } - - mfs = vcc_FldSpec(tl, "!backend", "!weight", NULL); - - Fc(tl, 0, - "\nstatic const struct vrt_dir_random_entry vdre_%.*s[] = {\n", - PF(tl->t_dir)); - - for (nelem = 0; tl->t->tok != '}'; nelem++) { /* List of members */ - first = ""; - t_be = tl->t; - vcc_ResetFldSpec(mfs); - - SkipToken(tl, '{'); - Fc(tl, 0, "\t{"); - - while (tl->t->tok != '}') { /* Member fields */ - vcc_IsField(tl, &t_field, mfs); - ERRCHK(tl); - if (vcc_IdIs(t_field, "backend")) { - vcc_ParseBackendHost(tl, nelem, &p); - ERRCHK(tl); - AN(p); - Fc(tl, 0, "%s .host = VGC_backend_%s", - first, p); - } else if (vcc_IdIs(t_field, "weight")) { - ExpectErr(tl, CNUM); - t_x = tl->t; - u = vcc_UintVal(tl); - ERRCHK(tl); - if (u == 0) { - VSB_printf(tl->sb, - "The .weight must be higher " - "than zero.\n"); - vcc_ErrWhere(tl, t_x); - return; - } - Fc(tl, 0, "%s .weight = %u", first, u); - SkipToken(tl, ';'); - } else { - ErrInternal(tl); - } - first = ", "; - } - vcc_FieldsOk(tl, mfs); - if (tl->err) { - VSB_printf(tl->sb, - "\nIn member host specification starting at:\n"); - vcc_ErrWhere(tl, t_be); - return; - } - Fc(tl, 0, " },\n"); - vcc_NextToken(tl); - } - Fc(tl, 0, "};\n"); - Fc(tl, 0, - "\nstatic const struct vrt_dir_random vgc_dir_priv_%.*s = {\n", - PF(tl->t_dir)); - Fc(tl, 0, "\t.name = \"%.*s\",\n", PF(tl->t_dir)); - Fc(tl, 0, "\t.retries = %u,\n", retries); - Fc(tl, 0, "\t.nmember = %d,\n", nelem); - Fc(tl, 0, "\t.members = vdre_%.*s,\n", PF(tl->t_dir)); - Fc(tl, 0, "};\n"); -} diff --git a/lib/libvcl/vcc_token.c b/lib/libvcl/vcc_token.c index 26f2545..577b784 100644 --- a/lib/libvcl/vcc_token.c +++ b/lib/libvcl/vcc_token.c @@ -272,18 +272,6 @@ vcc__Expect(struct vcc *tl, unsigned tok, unsigned line) } /*-------------------------------------------------------------------- - * Compare token to token - */ - -int -vcc_Teq(const struct token *t1, const struct token *t2) -{ - if (t1->e - t1->b != t2->e - t2->b) - return (0); - return (!memcmp(t1->b, t2->b, t1->e - t1->b)); -} - -/*-------------------------------------------------------------------- * Compare ID token to string, return true of match */ From phk at varnish-cache.org Mon Mar 18 11:05:34 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Mon, 18 Mar 2013 12:05:34 +0100 Subject: [master] ab63b45 Think of this as a warning-shot... Message-ID: commit ab63b453a9f594198ce34ef503a0a16df4de2551 Author: Poul-Henning Kamp Date: Mon Mar 18 11:05:14 2013 +0000 Think of this as a warning-shot... diff --git a/doc/sphinx/Makefile.am b/doc/sphinx/Makefile.am index 3dc88c6..579b6c8 100644 --- a/doc/sphinx/Makefile.am +++ b/doc/sphinx/Makefile.am @@ -110,6 +110,7 @@ EXTRA_DIST = \ phk/thoughts.rst \ phk/three-zero.rst \ phk/vcl_expr.rst \ + phk/wanton_destruction.rst \ reference/index.rst \ reference/params.rst \ reference/varnishadm.rst \ diff --git a/doc/sphinx/phk/index.rst b/doc/sphinx/phk/index.rst index 2b5cb1f..58da708 100644 --- a/doc/sphinx/phk/index.rst +++ b/doc/sphinx/phk/index.rst @@ -9,6 +9,7 @@ You may or may not want to know what Poul-Henning thinks. .. toctree:: :maxdepth: 1 + wanton_destruction.rst spdy.rst http20.rst varnish_does_not_hash.rst diff --git a/doc/sphinx/phk/wanton_destruction.rst b/doc/sphinx/phk/wanton_destruction.rst new file mode 100644 index 0000000..4289cf1 --- /dev/null +++ b/doc/sphinx/phk/wanton_destruction.rst @@ -0,0 +1,79 @@ +.. _phk_wanton: + +======================================= +Wanton destruction for the greater good +======================================= + +We live in an old house, and it's all wrong for us. + +When I bought this house, it was perfect, or at least perfect enough. + +But times have changed. + +I have no small kids anymore, and rather than just right for two +kids to tumble in, the garden is now too small for all the flowers +we want. + +And the rooms are not where we want them, there are too many stairs +in all the wrong places, and the kitchen needs to be torn out and +a new built. + +I'm sure that some other family will be able to fall in love with +this house, the way we did, but there is no realistic way to +rebuild it, to become the house we want now. + +For one thing, doing major surgery on a house while you live in it +is double-minus-fun and it always slows the rebuild project down +when you have to keep at least one toilet working and sanitary and +be able to cook and sleep on the building site. + +So we'll be building a new house on a plot of land on the other +side of the road, one of the coming years, a house which is right +for us, and then we will sell this old house, to a family with small +children, who will love it, and rip out the old funky kitchen and +make a new one before they move in. + +One would think that software would be nothing like an old house, +but they are more alike than most people imagine. + +Using a major piece of software, is like moving into a house: You +need to adapt your life and the house or the software to each other, +since nothing is ever quite perfect, there will be limitations. + +And those limitations affect how you think: If you live in a +2 bedroom apartment, you won't even be considering inviting 80 +guests to a party. + +A lot of Varnish-users have taken time to figure out how Varnish +fits into their lives and made the compromises necessary to make +it work, and once you've done that, you moved on to other problems, +but the limitations of Varnish keeps affecting how you think about +your website, even if you don't realize this. + +Well, I've got news for you: You'll be moving into a new house in +the next couple of years, it'll be called Varnish V4 and that means +that you will have to decide who gets which room and where to store +the towels and grandmothers old china, all over again. + +I'm sure you'll hate me for it, "Why do we have to move ?", "It +really wasn't that bad after all" and so on and so forth. +But if I do my job right, that will soon turn into "Ohh, that's +pretty neat, I always wanted one of those..." and "Hey... Watch me +do THIS!" etc. + +I could have started with a fresh GIT repository, to make it clear +that what is happening right now is the construction of an entirely +new house, but software isn't built from physical objects, so I +don't need to do that: You can keep using Varnish, while I rebuild +it, and thanks to the wonder of bits, you won't see a trace of +dirt or dust while it happens. + +So don't be alarmed by the wanton destruction you will see in -trunk +the coming weeks, it is not destroying the Varnish you are using +for your website today, it is building the new one you will be using +in the future. + +And it's going to be perfect for you, at least for some years... + + +Poul-Henning, 2013-03-18 From martin at varnish-cache.org Tue Mar 19 14:43:18 2013 From: martin at varnish-cache.org (Martin Blix Grydeland) Date: Tue, 19 Mar 2013 15:43:18 +0100 Subject: [master] d770a10 Resource cleanup in cnt_error() when Transient is full. Message-ID: commit d770a105b5587c7b402a1dff1629b78eaa82b0e9 Author: Martin Blix Grydeland Date: Mon Mar 18 15:25:42 2013 +0100 Resource cleanup in cnt_error() when Transient is full. Fixes: #1283 diff --git a/bin/varnishd/cache/cache_hash.c b/bin/varnishd/cache/cache_hash.c index db906ec..b680605 100644 --- a/bin/varnishd/cache/cache_hash.c +++ b/bin/varnishd/cache/cache_hash.c @@ -682,7 +682,8 @@ HSH_Deref(struct dstat *ds, struct objcore *oc, struct object **oo) BAN_DestroyObj(oc); AZ(oc->ban); - } + } else + AZ(oc->refcnt); if (oc->methods != NULL) { oc_freeobj(oc); diff --git a/bin/varnishd/cache/cache_req_fsm.c b/bin/varnishd/cache/cache_req_fsm.c index b2bdd50..a7f8778 100644 --- a/bin/varnishd/cache/cache_req_fsm.c +++ b/bin/varnishd/cache/cache_req_fsm.c @@ -280,11 +280,16 @@ cnt_error(struct worker *wrk, struct req *req) if (req->obj == NULL) { req->doclose = SC_OVERLOAD; req->director = NULL; + AZ(HSH_Deref(&wrk->stats, req->objcore, NULL)); + req->objcore = NULL; http_Teardown(bo->beresp); http_Teardown(bo->bereq); + VBO_DerefBusyObj(wrk, &req->busyobj); + AZ(req->busyobj); return (REQ_FSM_DONE); } CHECK_OBJ_NOTNULL(req->obj, OBJECT_MAGIC); + AZ(req->objcore); req->obj->vxid = bo->vsl->wid; req->obj->exp.entered = req->t_req; diff --git a/bin/varnishtest/tests/r01283.vtc b/bin/varnishtest/tests/r01283.vtc new file mode 100644 index 0000000..9283209 --- /dev/null +++ b/bin/varnishtest/tests/r01283.vtc @@ -0,0 +1,44 @@ +varnishtest "#1283 - Test failure to allocate object for error (transient full)" + +server s1 { + rxreq + txresp -bodylen 1048000 +} -start + +varnish v1 -arg "-p nuke_limit=0" -storage "-sTransient=malloc,1m" -vcl+backend { + sub vcl_recv { + if (req.http.x-do-error) { + error 500; + } + } + sub vcl_fetch { + set beresp.storage = "Transient"; + } +} -start + +client c1 { + # Fill transient + txreq + rxresp + expect resp.status == 200 +} -run + +varnish v1 -expect SMA.Transient.g_bytes > 1048000 +varnish v1 -expect SMA.Transient.g_space < 200 +varnish v1 -expect SMA.Transient.c_fail == 0 + +client c1 { + # Trigger vcl_error. Don't wait for reply as Varnish will not send one + # due to Transient full + txreq -hdr "X-Do-Error: true" + delay 1 +} -run + +varnish v1 -expect SMA.Transient.c_fail == 1 + +client c1 { + # Check that Varnish is still alive + txreq + rxresp + expect resp.status == 200 +} -run From martin at varnish-cache.org Tue Mar 19 14:43:19 2013 From: martin at varnish-cache.org (Martin Blix Grydeland) Date: Tue, 19 Mar 2013 15:43:19 +0100 Subject: [master] d1bbd0b Properly clean up resources after STV_NewObject fails before jumping to error. Message-ID: commit d1bbd0b38fe067da391a1ad9cba42484321c6b8b Author: Martin Blix Grydeland Date: Mon Mar 18 16:07:02 2013 +0100 Properly clean up resources after STV_NewObject fails before jumping to error. Fixes: #1284 diff --git a/bin/varnishd/cache/cache_req_fsm.c b/bin/varnishd/cache/cache_req_fsm.c index a7f8778..49a6732 100644 --- a/bin/varnishd/cache/cache_req_fsm.c +++ b/bin/varnishd/cache/cache_req_fsm.c @@ -487,6 +487,7 @@ cnt_fetchbody(struct worker *wrk, struct req *req) CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(req, REQ_MAGIC); + CHECK_OBJ_NOTNULL(req->objcore, OBJCORE_MAGIC); bo = req->busyobj; CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC); @@ -571,7 +572,6 @@ cnt_fetchbody(struct worker *wrk, struct req *req) /* Create Vary instructions */ if (req->objcore->objhead != NULL) { - CHECK_OBJ_NOTNULL(req->objcore, OBJCORE_MAGIC); vary = VRY_Create(req, bo->beresp); if (vary != NULL) { varyl = VSB_len(vary); @@ -610,6 +610,8 @@ cnt_fetchbody(struct worker *wrk, struct req *req) if (req->obj == NULL) { req->err_code = 503; req->req_step = R_STP_ERROR; + AZ(HSH_Deref(&wrk->stats, req->objcore, NULL)); + req->objcore = NULL; VDI_CloseFd(&bo->vbc); VBO_DerefBusyObj(wrk, &req->busyobj); return (REQ_FSM_MORE); diff --git a/bin/varnishtest/tests/r01284.vtc b/bin/varnishtest/tests/r01284.vtc new file mode 100644 index 0000000..33a2a08 --- /dev/null +++ b/bin/varnishtest/tests/r01284.vtc @@ -0,0 +1,43 @@ +varnishtest "#1284 - Test resource cleanup after STV_NewObject fail in fetch" + +server s1 { + rxreq + expect req.url == "/obj1" + txresp -bodylen 1048000 + rxreq + expect req.url == "/obj2" + txresp -hdr "Long: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" -hdr "Long2: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +} -start + +varnish v1 -arg "-p nuke_limit=0" -storage "-sTransient=malloc,1m" -vcl+backend { + sub vcl_fetch { + set beresp.storage = "Transient"; + } +} -start + +client c1 { + # Fill transient + txreq -url "/obj1" + rxresp + expect resp.status == 200 +} -run + +varnish v1 -expect SMA.Transient.g_bytes > 1048000 +varnish v1 -expect SMA.Transient.g_space < 200 + +client c1 { + # No space for this object (more than 256 bytes in headers). Don't wait + # for reply as Varnish will not send one due to Transient full. + txreq -url "/obj2" + delay 1 +} -run + +# Two failures, one for obj2 and two for the attempts at sending error +varnish v1 -expect SMA.Transient.c_fail == 3 + +client c1 { + # Check that Varnish is still alive + txreq -url "/obj1" + rxresp + expect resp.status == 200 +} -run From martin at varnish-cache.org Tue Mar 19 14:43:19 2013 From: martin at varnish-cache.org (Martin Blix Grydeland) Date: Tue, 19 Mar 2013 15:43:19 +0100 Subject: [master] c394dfb Be able to detect parse error during processing of backend Vary headers, and do 503 on parse error. Message-ID: commit c394dfb760191171a2a1e2eb0b630077b40c079c Author: Martin Blix Grydeland Date: Mon Mar 18 11:55:54 2013 +0100 Be able to detect parse error during processing of backend Vary headers, and do 503 on parse error. diff --git a/bin/varnishd/cache/cache.h b/bin/varnishd/cache/cache.h index 6be2c73..a63c36e 100644 --- a/bin/varnishd/cache/cache.h +++ b/bin/varnishd/cache/cache.h @@ -1003,7 +1003,7 @@ void RES_BuildHttp(struct req *); void RES_WriteObj(struct req *); /* cache_vary.c */ -struct vsb *VRY_Create(struct req *sp, const struct http *hp); +int VRY_Create(struct req *req, const struct http *hp, struct vsb **psb); int VRY_Match(struct req *, const uint8_t *vary); void VRY_Validate(const uint8_t *vary); void VRY_Prep(struct req *); diff --git a/bin/varnishd/cache/cache_req_fsm.c b/bin/varnishd/cache/cache_req_fsm.c index 49a6732..e1fd343 100644 --- a/bin/varnishd/cache/cache_req_fsm.c +++ b/bin/varnishd/cache/cache_req_fsm.c @@ -572,12 +572,24 @@ cnt_fetchbody(struct worker *wrk, struct req *req) /* Create Vary instructions */ if (req->objcore->objhead != NULL) { - vary = VRY_Create(req, bo->beresp); - if (vary != NULL) { - varyl = VSB_len(vary); - assert(varyl > 0); + varyl = VRY_Create(req, bo->beresp, &vary); + if (varyl > 0) { + AN(vary); + assert(varyl == VSB_len(vary)); l += varyl; - } + } else if (varyl < 0) { + /* Vary parse error */ + AZ(vary); + req->err_code = 503; + req->req_step = R_STP_ERROR; + AZ(HSH_Deref(&wrk->stats, req->objcore, NULL)); + req->objcore = NULL; + VDI_CloseFd(&bo->vbc); + VBO_DerefBusyObj(wrk, &req->busyobj); + return (REQ_FSM_MORE); + } else + /* No vary */ + AZ(vary); } /* diff --git a/bin/varnishd/cache/cache_vary.c b/bin/varnishd/cache/cache_vary.c index d4319b2..f35b2ae 100644 --- a/bin/varnishd/cache/cache_vary.c +++ b/bin/varnishd/cache/cache_vary.c @@ -61,16 +61,29 @@ #include "vct.h" #include "vend.h" -struct vsb * -VRY_Create(struct req *req, const struct http *hp) +/********************************************************************** + * Create a Vary matching string from a Vary header + * + * Return value: + * <0: Parse error + * 0: No Vary header on object + * >0: Length of Vary matching string in *psb + */ + +int +VRY_Create(struct req *req, const struct http *hp, struct vsb **psb) { char *v, *p, *q, *h, *e; struct vsb *sb, *sbh; unsigned l; + int error = 0; + + AN(psb); + AZ(*psb); /* No Vary: header, no worries */ if (!http_GetHdr(hp, H_Vary, &v)) - return (NULL); + return (0); /* For vary matching string */ sb = VSB_new_auto(); @@ -125,12 +138,20 @@ VRY_Create(struct req *req, const struct http *hp) xxxassert(*q == ','); p = q; } + + if (error) { + VSB_delete(sbh); + VSB_delete(sb); + return (-1); + } + /* Terminate vary matching string */ VSB_printf(sb, "%c%c%c", 0xff, 0xff, 0); VSB_delete(sbh); AZ(VSB_finish(sb)); - return(sb); + *psb = sb; + return (VSB_len(sb)); } /* From martin at varnish-cache.org Tue Mar 19 14:43:19 2013 From: martin at varnish-cache.org (Martin Blix Grydeland) Date: Tue, 19 Mar 2013 15:43:19 +0100 Subject: [master] e316a5f Remove dodgy workaround introduced for #763. Message-ID: commit e316a5fb72d67f3f3e64e4d73a9a423bf74c88ae Author: Martin Blix Grydeland Date: Mon Mar 18 17:11:34 2013 +0100 Remove dodgy workaround introduced for #763. With fix for #1275 we can now do a proper 503 when malformed Vary-headers are received from backend. Error out instead of accepting bogus ':'. diff --git a/bin/varnishd/cache/cache_vary.c b/bin/varnishd/cache/cache_vary.c index f35b2ae..3a99bf3 100644 --- a/bin/varnishd/cache/cache_vary.c +++ b/bin/varnishd/cache/cache_vary.c @@ -93,11 +93,6 @@ VRY_Create(struct req *req, const struct http *hp, struct vsb **psb) sbh = VSB_new_auto(); AN(sbh); - if (*v == ':') { - VSLb(req->vsl, SLT_Error, - "Vary header had extra ':', fix backend"); - v++; - } for (p = v; *p; p++) { /* Find next header-name */ diff --git a/bin/varnishtest/tests/r00763.vtc b/bin/varnishtest/tests/r00763.vtc index 24a4d6f..72fced4 100644 --- a/bin/varnishtest/tests/r00763.vtc +++ b/bin/varnishtest/tests/r00763.vtc @@ -10,5 +10,5 @@ varnish v1 -vcl+backend {} -start client c1 { txreq rxresp - expect resp.http.vary == ": foo" + expect resp.status == 503 } -run From martin at varnish-cache.org Tue Mar 19 14:43:19 2013 From: martin at varnish-cache.org (Martin Blix Grydeland) Date: Tue, 19 Mar 2013 15:43:19 +0100 Subject: [master] f8f75cb Don't panic on malformed Vary headers. Message-ID: commit f8f75cb1a7f4d391bf1c0684c393c336628fb3d5 Author: Martin Blix Grydeland Date: Mon Mar 18 17:07:46 2013 +0100 Don't panic on malformed Vary headers. Fixes: #1275 Test case by: Dag Haavi Finstad diff --git a/bin/varnishd/cache/cache_vary.c b/bin/varnishd/cache/cache_vary.c index 3a99bf3..d8a84eb 100644 --- a/bin/varnishd/cache/cache_vary.c +++ b/bin/varnishd/cache/cache_vary.c @@ -130,7 +130,11 @@ VRY_Create(struct req *req, const struct http *hp, struct vsb **psb) q++; if (*q == '\0') break; - xxxassert(*q == ','); + if (*q != ',') { + VSLb(req->vsl, SLT_Error, "Malformed Vary header"); + error = 1; + break; + } p = q; } diff --git a/bin/varnishtest/tests/r01275.vtc b/bin/varnishtest/tests/r01275.vtc new file mode 100644 index 0000000..72c7184 --- /dev/null +++ b/bin/varnishtest/tests/r01275.vtc @@ -0,0 +1,14 @@ +varnishtest "#1275 - panic with malformed Vary header" + +server s1 { + rxreq + txresp -hdr "Vary: foo bar" +} -start + +varnish v1 -vcl+backend { } -start + +client c1 { + txreq + rxresp + expect resp.status == 503 +} -run From martin at varnish-cache.org Tue Mar 19 14:43:19 2013 From: martin at varnish-cache.org (Martin Blix Grydeland) Date: Tue, 19 Mar 2013 15:43:19 +0100 Subject: [master] f5c42c6 Return 503 when Vary-headers references header names more than 127 (out limit) characters long. Message-ID: commit f5c42c6aaf9bdadf58f58dddb2b9e755d12d790b Author: Martin Blix Grydeland Date: Mon Mar 18 17:00:57 2013 +0100 Return 503 when Vary-headers references header names more than 127 (out limit) characters long. Fixes: #1274 Test case by: Dag Haavi Finstad diff --git a/bin/varnishd/cache/cache_vary.c b/bin/varnishd/cache/cache_vary.c index d8a84eb..be98201 100644 --- a/bin/varnishd/cache/cache_vary.c +++ b/bin/varnishd/cache/cache_vary.c @@ -101,6 +101,13 @@ VRY_Create(struct req *req, const struct http *hp, struct vsb **psb) for (q = p; *q && !vct_issp(*q) && *q != ','; q++) continue; + if (q - p > INT8_MAX) { + VSLb(req->vsl, SLT_Error, + "Vary header name length exceeded"); + error = 1; + break; + } + /* Build a header-matching string out of it */ VSB_clear(sbh); VSB_printf(sbh, "%c%.*s:%c", diff --git a/bin/varnishtest/tests/r01274.vtc b/bin/varnishtest/tests/r01274.vtc new file mode 100644 index 0000000..fe427cc --- /dev/null +++ b/bin/varnishtest/tests/r01274.vtc @@ -0,0 +1,15 @@ +varnishtest "#1274 - panic when Vary field-name is too large to fit in a signed char" + +server s1 { + rxreq + # Vary header more than 127 characters long + txresp -hdr "Vary: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +} -start + +varnish v1 -vcl+backend { } -start + +client c1 { + txreq + rxresp + expect resp.status == 503 +} -run From martin at varnish-cache.org Tue Mar 19 14:43:19 2013 From: martin at varnish-cache.org (Martin Blix Grydeland) Date: Tue, 19 Mar 2013 15:43:19 +0100 Subject: [master] 7b6a395 Throw 503 on exceeding max 65k Vary header constituent limit. Message-ID: commit 7b6a395c8a08308560f9617d71a4d9ac1d3c44a7 Author: Martin Blix Grydeland Date: Mon Mar 18 17:53:35 2013 +0100 Throw 503 on exceeding max 65k Vary header constituent limit. diff --git a/bin/varnishd/cache/cache_vary.c b/bin/varnishd/cache/cache_vary.c index be98201..ba87608 100644 --- a/bin/varnishd/cache/cache_vary.c +++ b/bin/varnishd/cache/cache_vary.c @@ -122,7 +122,12 @@ VRY_Create(struct req *req, const struct http *hp, struct vsb **psb) e--; /* Encode two byte length and contents */ l = e - h; - assert(!(l & ~0xffff)); + if (l > 0xffff - 1) { + VSLb(req->vsl, SLT_Error, + "Vary header maximum length exceeded"); + error = 1; + break; + } } else { e = h; l = 0xffff; From martin at varnish-cache.org Tue Mar 19 14:43:19 2013 From: martin at varnish-cache.org (Martin Blix Grydeland) Date: Tue, 19 Mar 2013 15:43:19 +0100 Subject: [master] ab17fec Document Vary parse error behavior Message-ID: commit ab17fecd4ddb7a163e96e80a20decf2c47e24d51 Author: Martin Blix Grydeland Date: Tue Mar 19 15:37:05 2013 +0100 Document Vary parse error behavior diff --git a/doc/sphinx/users-guide/vary.rst b/doc/sphinx/users-guide/vary.rst index 4f4f475..31c3bde 100644 --- a/doc/sphinx/users-guide/vary.rst +++ b/doc/sphinx/users-guide/vary.rst @@ -42,6 +42,14 @@ following VCL code will normalize the Accept-Encoding headers:: The code sets the Accept-Encoding header from the client to either gzip, deflate with a preference for gzip. +Vary parse errors +~~~~~~~~~~~~~~~~~ + +Varnish will return a 503 internal server error page when it fails to +parse the Vary server header, or if any of the client headers listed +in the Vary header exceeds the limit of 65k characters. An SLT_Error +log entry is added in these cases. + Pitfall - Vary: User-Agent ~~~~~~~~~~~~~~~~~~~~~~~~~~ From martin at varnish-cache.org Tue Mar 19 15:35:49 2013 From: martin at varnish-cache.org (Martin Blix Grydeland) Date: Tue, 19 Mar 2013 16:35:49 +0100 Subject: [3.0] 956f64e Be able to detect parse error during processing of backend Vary headers, and do 503 on parse error. Message-ID: commit 956f64e2ede0289acc91dc19429e8d7e96af254e Author: Martin Blix Grydeland Date: Mon Mar 18 11:55:54 2013 +0100 Be able to detect parse error during processing of backend Vary headers, and do 503 on parse error. Conflicts: bin/varnishd/cache.h bin/varnishd/cache/cache_req_fsm.c bin/varnishd/cache_vary.c diff --git a/bin/varnishd/cache.h b/bin/varnishd/cache.h index 31b19ef..d7f6ab8 100644 --- a/bin/varnishd/cache.h +++ b/bin/varnishd/cache.h @@ -894,7 +894,7 @@ void RES_StreamEnd(struct sess *sp); void RES_StreamPoll(const struct sess *sp); /* cache_vary.c */ -struct vsb *VRY_Create(const struct sess *sp, const struct http *hp); +int VRY_Create(const struct sess *sp, const struct http *hp, struct vsb **psb); int VRY_Match(struct sess *sp, const uint8_t *vary); void VRY_Validate(const uint8_t *vary); diff --git a/bin/varnishd/cache/cache_req_fsm.c b/bin/varnishd/cache/cache_req_fsm.c new file mode 100644 index 0000000..e1fd343 --- /dev/null +++ b/bin/varnishd/cache/cache_req_fsm.c @@ -0,0 +1,1294 @@ +/*- + * Copyright (c) 2006 Verdens Gang AS + * Copyright (c) 2006-2011 Varnish Software AS + * All rights reserved. + * + * Author: Poul-Henning Kamp + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file contains the request-handling state engine, which is intended to + * (over time) be(ome) protocol agnostic. + * We already use this now with ESI:includes, which are for all relevant + * purposes a different "protocol" + * + * A special complication is the fact that we can suspend processing of + * a request when hash-lookup finds a busy objhdr. + * + * Since the states are rather nasty in detail, I have decided to embedd + * a dot(1) graph in the source code comments. So to see the big picture, + * extract the DOT lines and run though dot(1), for instance with the + * command: + * sed -n '/^DOT/s///p' cache/cache_req_fsm.c | dot -Tps > /tmp/_.ps + */ + +/* +DOT digraph vcl_center { +xDOT page="8.2,11.5" +DOT size="7.2,10.5" +DOT margin="0.5" +DOT center="1" +DOT acceptor [ +DOT shape=hexagon +DOT label="Request received" +DOT ] +DOT ESI_REQ [ shape=hexagon ] +DOT ESI_REQ -> recv +DOT ERROR [shape=plaintext] +DOT RESTART [shape=plaintext] +DOT acceptor -> recv [style=bold,color=green] + */ + +#include "config.h" + +#include +#include +#include + +#include "cache.h" + +#include "hash/hash_slinger.h" +#include "vcl.h" +#include "vsha256.h" +#include "vtim.h" + +#ifndef HAVE_SRANDOMDEV +#include "compat/srandomdev.h" +#endif + +/*-------------------------------------------------------------------- + * We have a refcounted object on the session, and possibly the busyobj + * which is fetching it, prepare a response. + * +DOT subgraph xcluster_prepresp { +DOT prepresp [ +DOT shape=record +DOT label="{cnt_prepresp:|Filter obj.-\>resp.|{vcl_deliver\{\}|{req.|resp.}}|{error?|restart?}|stream ?}" +DOT ] +DOT prepresp -> deliver [style=bold,color=green,label=deliver] +DOT prepresp -> deliver [style=bold,color=red] +DOT prepresp -> deliver [style=bold,color=blue] +DOT } + * + */ + +static enum req_fsm_nxt +cnt_prepresp(struct worker *wrk, struct req *req) +{ + struct busyobj *bo; + + CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); + CHECK_OBJ_NOTNULL(req, REQ_MAGIC); + bo = req->busyobj; + CHECK_OBJ_ORNULL(bo, BUSYOBJ_MAGIC); + + CHECK_OBJ_NOTNULL(req->obj, OBJECT_MAGIC); + CHECK_OBJ_NOTNULL(req->vcl, VCL_CONF_MAGIC); + + req->res_mode = 0; + + if (bo == NULL) { + if (!req->disable_esi && req->obj->esidata != NULL) { + /* In ESI mode, we can't know the aggregate length */ + req->res_mode &= ~RES_LEN; + req->res_mode |= RES_ESI; + } else { + req->res_mode |= RES_LEN; + } + } else { + AZ(bo->do_esi); + } + + if (req->esi_level > 0) { + /* Included ESI object, always CHUNKED or EOF */ + req->res_mode &= ~RES_LEN; + req->res_mode |= RES_ESI_CHILD; + } + + if (cache_param->http_gzip_support && req->obj->gziped && + !RFC2616_Req_Gzip(req->http)) { + /* + * We don't know what it uncompresses to + * XXX: we could cache that + */ + req->res_mode &= ~RES_LEN; + req->res_mode |= RES_GUNZIP; + } + + if (!(req->res_mode & (RES_LEN|RES_CHUNKED|RES_EOF))) { + /* We havn't chosen yet, do so */ + if (!req->wantbody) { + /* Nothing */ + } else if (req->http->protover >= 11) { + req->res_mode |= RES_CHUNKED; + } else { + req->res_mode |= RES_EOF; + req->doclose = SC_TX_EOF; + } + } + + req->t_resp = W_TIM_real(wrk); + if (req->obj->objcore->objhead != NULL) { + if ((req->t_resp - req->obj->last_lru) > + cache_param->lru_timeout && + EXP_Touch(req->obj->objcore)) + req->obj->last_lru = req->t_resp; + if (!cache_param->obj_readonly) + req->obj->last_use = req->t_resp; /* XXX: locking ? */ + } + HTTP_Setup(req->resp, req->ws, req->vsl, HTTP_Resp); + RES_BuildHttp(req); + + VCL_deliver_method(req); + switch (req->handling) { + case VCL_RET_DELIVER: + break; + case VCL_RET_RESTART: + if (req->restarts >= cache_param->max_restarts) + break; + if (bo != NULL) { + AN(bo->do_stream); + (void)HSH_Deref(&wrk->stats, NULL, &req->obj); + VBO_DerefBusyObj(wrk, &req->busyobj); + } else { + (void)HSH_Deref(&wrk->stats, NULL, &req->obj); + } + AZ(req->obj); + http_Teardown(req->resp); + req->req_step = R_STP_RESTART; + return (REQ_FSM_MORE); + default: + WRONG("Illegal action in vcl_deliver{}"); + } + req->req_step = R_STP_DELIVER; + return (REQ_FSM_MORE); +} + +/*-------------------------------------------------------------------- + * Deliver an already stored object + * +DOT subgraph xcluster_deliver { +DOT deliver [ +DOT shape=record +DOT label="{cnt_deliver:|Send body}" +DOT ] +DOT } +DOT deliver -> DONE [style=bold,color=green] +DOT deliver -> DONE [style=bold,color=red] +DOT deliver -> DONE [style=bold,color=blue] + * + */ + +static enum req_fsm_nxt +cnt_deliver(struct worker *wrk, struct req *req) +{ + struct busyobj *bo; + + CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); + CHECK_OBJ_NOTNULL(req, REQ_MAGIC); + CHECK_OBJ_NOTNULL(req->obj, OBJECT_MAGIC); + bo = req->busyobj; + CHECK_OBJ_ORNULL(bo, BUSYOBJ_MAGIC); + + if (bo != NULL) { + while (bo->state < BOS_FAILED) + (void)usleep(10000); + assert(bo->state >= BOS_FAILED); + + if (bo->state == BOS_FAILED) { + (void)HSH_Deref(&wrk->stats, NULL, &req->obj); + VBO_DerefBusyObj(wrk, &req->busyobj); + req->err_code = 503; + req->req_step = R_STP_ERROR; + return (REQ_FSM_MORE); + } + VBO_DerefBusyObj(wrk, &req->busyobj); + } + + AZ(req->busyobj); + req->director = NULL; + req->restarts = 0; + + RES_WriteObj(req); + + /* No point in saving the body if it is hit-for-pass */ + if (req->obj->objcore->flags & OC_F_PASS) + STV_Freestore(req->obj); + + assert(WRW_IsReleased(wrk)); + (void)HSH_Deref(&wrk->stats, NULL, &req->obj); + http_Teardown(req->resp); + return (REQ_FSM_DONE); +} +/*-------------------------------------------------------------------- + * Emit an error + * +DOT subgraph xcluster_error { +DOT vcl_error [ +DOT shape=record +DOT label="vcl_error()|resp." +DOT ] +DOT ERROR -> vcl_error +DOT vcl_error-> prepresp [label=deliver] +DOT } +DOT vcl_error-> rsterr [label="restart",color=purple] +DOT rsterr [label="RESTART",shape=plaintext] + */ + +static enum req_fsm_nxt +cnt_error(struct worker *wrk, struct req *req) +{ + struct http *h; + struct busyobj *bo; + char date[40]; + + CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); + CHECK_OBJ_NOTNULL(req, REQ_MAGIC); + AZ(req->objcore); + AZ(req->obj); + AZ(req->busyobj); + + req->acct_req.error++; + bo = VBO_GetBusyObj(wrk, req); + req->busyobj = bo; + AZ(bo->stats); + bo->stats = &wrk->stats; + req->objcore = HSH_NewObjCore(wrk); + req->obj = STV_NewObject(bo, &req->objcore, + TRANSIENT_STORAGE, cache_param->http_resp_size, + (uint16_t)cache_param->http_max_hdr); + bo->stats = NULL; + if (req->obj == NULL) { + req->doclose = SC_OVERLOAD; + req->director = NULL; + AZ(HSH_Deref(&wrk->stats, req->objcore, NULL)); + req->objcore = NULL; + http_Teardown(bo->beresp); + http_Teardown(bo->bereq); + VBO_DerefBusyObj(wrk, &req->busyobj); + AZ(req->busyobj); + return (REQ_FSM_DONE); + } + CHECK_OBJ_NOTNULL(req->obj, OBJECT_MAGIC); + AZ(req->objcore); + req->obj->vxid = bo->vsl->wid; + req->obj->exp.entered = req->t_req; + + h = req->obj->http; + + if (req->err_code < 100 || req->err_code > 999) + req->err_code = 501; + + http_PutProtocol(h, "HTTP/1.1"); + http_PutStatus(h, req->err_code); + VTIM_format(W_TIM_real(wrk), date); + http_PrintfHeader(h, "Date: %s", date); + http_SetHeader(h, "Server: Varnish"); + + if (req->err_reason != NULL) + http_PutResponse(h, req->err_reason); + else + http_PutResponse(h, http_StatusMessage(req->err_code)); + VCL_error_method(req); + + if (req->handling == VCL_RET_RESTART && + req->restarts < cache_param->max_restarts) { + HSH_Drop(wrk, &req->obj); + VBO_DerefBusyObj(wrk, &req->busyobj); + req->req_step = R_STP_RESTART; + return (REQ_FSM_MORE); + } else if (req->handling == VCL_RET_RESTART) + req->handling = VCL_RET_DELIVER; + + + /* We always close when we take this path */ + req->doclose = SC_TX_ERROR; + req->wantbody = 1; + + assert(req->handling == VCL_RET_DELIVER); + req->err_code = 0; + req->err_reason = NULL; + http_Teardown(bo->bereq); + VBO_DerefBusyObj(wrk, &req->busyobj); + req->req_step = R_STP_PREPRESP; + return (REQ_FSM_MORE); +} + +/*-------------------------------------------------------------------- + * Fetch response headers from the backend + * +DOT subgraph xcluster_fetch { +DOT fetch [ +DOT shape=record +DOT label="{cnt_fetch:|fetch hdr\nfrom backend|(find obj.ttl)|{vcl_fetch\{\}|{req.|bereq.|beresp.}}|{error?|restart?}}" +DOT ] +DOT } +DOT fetch -> fetchbody [style=bold,color=red] +DOT fetch -> fetchbody [style=bold,color=blue] + */ + +static enum req_fsm_nxt +cnt_fetch(struct worker *wrk, struct req *req) +{ + int i, need_host_hdr; + struct busyobj *bo; + + CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); + CHECK_OBJ_NOTNULL(req, REQ_MAGIC); + + CHECK_OBJ_NOTNULL(req->vcl, VCL_CONF_MAGIC); + bo = req->busyobj; + CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC); + + AN(req->director); + AZ(bo->vbc); + AZ(bo->should_close); + AZ(req->storage_hint); + + HTTP_Setup(bo->beresp, bo->ws, bo->vsl, HTTP_Beresp); + + need_host_hdr = !http_GetHdr(bo->bereq, H_Host, NULL); + + req->acct_req.fetch++; + + i = FetchHdr(req, need_host_hdr, req->objcore->objhead == NULL); + /* + * If we recycle a backend connection, there is a finite chance + * that the backend closed it before we get a request to it. + * Do a single retry in that case. + */ + if (i == 1) { + VSC_C_main->backend_retry++; + i = FetchHdr(req, need_host_hdr, req->objcore->objhead == NULL); + } + + if (i) { + req->handling = VCL_RET_ERROR; + req->err_code = 503; + } else { + /* + * These two headers can be spread over multiple actual headers + * and we rely on their content outside of VCL, so collect them + * into one line here. + */ + http_CollectHdr(bo->beresp, H_Cache_Control); + http_CollectHdr(bo->beresp, H_Vary); + + /* + * Figure out how the fetch is supposed to happen, before the + * headers are adultered by VCL + * NB: Also sets other wrk variables + */ + bo->htc.body_status = RFC2616_Body(bo, &wrk->stats); + + req->err_code = http_GetStatus(bo->beresp); + + /* + * What does RFC2616 think about TTL ? + */ + EXP_Clr(&bo->exp); + bo->exp.entered = W_TIM_real(wrk); + RFC2616_Ttl(bo); + + /* pass from vclrecv{} has negative TTL */ + if (req->objcore->objhead == NULL) + bo->exp.ttl = -1.; + + AZ(bo->do_esi); + AZ(bo->do_pass); + + VCL_fetch_method(req); + + if (bo->do_pass) + req->objcore->flags |= OC_F_PASS; + + switch (req->handling) { + case VCL_RET_DELIVER: + req->req_step = R_STP_FETCHBODY; + return (REQ_FSM_MORE); + default: + break; + } + + /* We are not going to fetch the body, Close the connection */ + VDI_CloseFd(&bo->vbc); + } + + /* Clean up partial fetch */ + AZ(bo->vbc); + + if (req->objcore->objhead != NULL || + req->handling == VCL_RET_RESTART || + req->handling == VCL_RET_ERROR) { + CHECK_OBJ_NOTNULL(req->objcore, OBJCORE_MAGIC); + AZ(HSH_Deref(&wrk->stats, req->objcore, NULL)); + req->objcore = NULL; + } + assert(bo->refcount == 2); + VBO_DerefBusyObj(wrk, &bo); + VBO_DerefBusyObj(wrk, &req->busyobj); + req->director = NULL; + req->storage_hint = NULL; + + switch (req->handling) { + case VCL_RET_RESTART: + req->req_step = R_STP_RESTART; + return (REQ_FSM_MORE); + case VCL_RET_ERROR: + req->req_step = R_STP_ERROR; + return (REQ_FSM_MORE); + default: + WRONG("Illegal action in vcl_fetch{}"); + } +} + +/*-------------------------------------------------------------------- + * Prepare to fetch body from backend + * +DOT subgraph xcluster_body { +DOT fetchbody [ +DOT shape=record +DOT label="{cnt_fetchbody:|start fetch_thread}" +DOT ] +DOT } +DOT fetchbody:out -> prepresp [style=bold,color=red] +DOT fetchbody:out -> prepresp [style=bold,color=blue] + */ + +static enum req_fsm_nxt +cnt_fetchbody(struct worker *wrk, struct req *req) +{ + struct http *hp, *hp2; + char *b; + uint16_t nhttp; + unsigned l; + struct vsb *vary = NULL; + int varyl = 0, pass; + struct busyobj *bo; + + CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); + CHECK_OBJ_NOTNULL(req, REQ_MAGIC); + CHECK_OBJ_NOTNULL(req->objcore, OBJCORE_MAGIC); + bo = req->busyobj; + CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC); + + assert(req->handling == VCL_RET_DELIVER); + + if (req->objcore->objhead == NULL) { + /* This is a pass from vcl_recv */ + pass = 1; + /* VCL may have fiddled this, but that doesn't help */ + bo->exp.ttl = -1.; + } else if (bo->do_pass) { + pass = 1; + } else { + /* regular object */ + pass = 0; + } + + /* + * The VCL variables beresp.do_g[un]zip tells us how we want the + * object processed before it is stored. + * + * The backend Content-Encoding header tells us what we are going + * to receive, which we classify in the following three classes: + * + * "Content-Encoding: gzip" --> object is gzip'ed. + * no Content-Encoding --> object is not gzip'ed. + * anything else --> do nothing wrt gzip + * + */ + + /* We do nothing unless the param is set */ + if (!cache_param->http_gzip_support) + bo->do_gzip = bo->do_gunzip = 0; + + bo->is_gzip = http_HdrIs(bo->beresp, H_Content_Encoding, "gzip"); + + bo->is_gunzip = !http_GetHdr(bo->beresp, H_Content_Encoding, NULL); + + /* It can't be both */ + assert(bo->is_gzip == 0 || bo->is_gunzip == 0); + + /* We won't gunzip unless it is gzip'ed */ + if (bo->do_gunzip && !bo->is_gzip) + bo->do_gunzip = 0; + + /* If we do gunzip, remove the C-E header */ + if (bo->do_gunzip) + http_Unset(bo->beresp, H_Content_Encoding); + + /* We wont gzip unless it is ungziped */ + if (bo->do_gzip && !bo->is_gunzip) + bo->do_gzip = 0; + + /* If we do gzip, add the C-E header */ + if (bo->do_gzip) + http_SetHeader(bo->beresp, "Content-Encoding: gzip"); + + /* But we can't do both at the same time */ + assert(bo->do_gzip == 0 || bo->do_gunzip == 0); + + /* ESI takes precedence and handles gzip/gunzip itself */ + if (bo->do_esi) + bo->vfp = &vfp_esi; + else if (bo->do_gunzip) + bo->vfp = &vfp_gunzip; + else if (bo->do_gzip) + bo->vfp = &vfp_gzip; + else if (bo->is_gzip) + bo->vfp = &vfp_testgzip; + + if (bo->do_esi || req->esi_level > 0) + bo->do_stream = 0; + if (!req->wantbody) + bo->do_stream = 0; + + /* No reason to try streaming a non-existing body */ + if (bo->htc.body_status == BS_NONE) + bo->do_stream = 0; + + l = http_EstimateWS(bo->beresp, + pass ? HTTPH_R_PASS : HTTPH_A_INS, &nhttp); + + /* Create Vary instructions */ + if (req->objcore->objhead != NULL) { + varyl = VRY_Create(req, bo->beresp, &vary); + if (varyl > 0) { + AN(vary); + assert(varyl == VSB_len(vary)); + l += varyl; + } else if (varyl < 0) { + /* Vary parse error */ + AZ(vary); + req->err_code = 503; + req->req_step = R_STP_ERROR; + AZ(HSH_Deref(&wrk->stats, req->objcore, NULL)); + req->objcore = NULL; + VDI_CloseFd(&bo->vbc); + VBO_DerefBusyObj(wrk, &req->busyobj); + return (REQ_FSM_MORE); + } else + /* No vary */ + AZ(vary); + } + + /* + * Space for producing a Content-Length: header including padding + * A billion gigabytes is enough for anybody. + */ + l += strlen("Content-Length: XxxXxxXxxXxxXxxXxx") + sizeof(void *); + + if (bo->exp.ttl < cache_param->shortlived || + req->objcore == NULL) + req->storage_hint = TRANSIENT_STORAGE; + + AZ(bo->stats); + bo->stats = &wrk->stats; + req->obj = STV_NewObject(bo, &req->objcore, req->storage_hint, l, + nhttp); + if (req->obj == NULL) { + /* + * Try to salvage the transaction by allocating a + * shortlived object on Transient storage. + */ + if (bo->exp.ttl > cache_param->shortlived) + bo->exp.ttl = cache_param->shortlived; + bo->exp.grace = 0.0; + bo->exp.keep = 0.0; + req->obj = STV_NewObject(bo, &req->objcore, TRANSIENT_STORAGE, + l, nhttp); + } + bo->stats = NULL; + if (req->obj == NULL) { + req->err_code = 503; + req->req_step = R_STP_ERROR; + AZ(HSH_Deref(&wrk->stats, req->objcore, NULL)); + req->objcore = NULL; + VDI_CloseFd(&bo->vbc); + VBO_DerefBusyObj(wrk, &req->busyobj); + return (REQ_FSM_MORE); + } + CHECK_OBJ_NOTNULL(req->obj, OBJECT_MAGIC); + + req->storage_hint = NULL; + + AZ(bo->fetch_obj); + bo->fetch_obj = req->obj; + + if (bo->do_gzip || (bo->is_gzip && !bo->do_gunzip)) + req->obj->gziped = 1; + + if (vary != NULL) { + req->obj->vary = (void *)WS_Copy(req->obj->http->ws, + VSB_data(vary), varyl); + AN(req->obj->vary); + VRY_Validate(req->obj->vary); + VSB_delete(vary); + } + + req->obj->vxid = bo->vsl->wid; + req->obj->response = req->err_code; + WS_Assert(req->obj->ws_o); + + /* Filter into object */ + hp = bo->beresp; + hp2 = req->obj->http; + + hp2->logtag = HTTP_Obj; + http_FilterResp(hp, hp2, pass ? HTTPH_R_PASS : HTTPH_A_INS); + http_CopyHome(hp2); + + if (http_GetHdr(hp, H_Last_Modified, &b)) + req->obj->last_modified = VTIM_parse(b); + else + req->obj->last_modified = floor(bo->exp.entered); + + assert(WRW_IsReleased(wrk)); + + /* + * If we can deliver a 304 reply, we don't bother streaming. + * Notice that vcl_deliver{} could still nuke the headers + * that allow the 304, in which case we return 200 non-stream. + */ + if (req->obj->response == 200 && + req->http->conds && + RFC2616_Do_Cond(req)) + bo->do_stream = 0; + + /* + * Ready to fetch the body + */ + bo->fetch_task.func = FetchBody; + bo->fetch_task.priv = bo; + + assert(bo->refcount == 2); /* one for each thread */ + + if (req->obj->objcore->objhead != NULL) { + EXP_Insert(req->obj); + AN(req->obj->objcore->ban); + AZ(req->obj->ws_o->overflow); + HSH_Unbusy(&wrk->stats, req->obj->objcore); + } + + if (!bo->do_stream || + Pool_Task(wrk->pool, &bo->fetch_task, POOL_NO_QUEUE)) + FetchBody(wrk, bo); + + if (req->obj->objcore->objhead != NULL) + HSH_Ref(req->obj->objcore); + + if (bo->state == BOS_FINISHED) { + VBO_DerefBusyObj(wrk, &req->busyobj); + } else if (bo->state == BOS_FAILED) { + /* handle early failures */ + (void)HSH_Deref(&wrk->stats, NULL, &req->obj); + VBO_DerefBusyObj(wrk, &req->busyobj); + req->err_code = 503; + req->req_step = R_STP_ERROR; + return (REQ_FSM_MORE); + } + + assert(WRW_IsReleased(wrk)); + req->req_step = R_STP_PREPRESP; + return (REQ_FSM_MORE); +} + +/*-------------------------------------------------------------------- + * HIT + * We had a cache hit. Ask VCL, then march off as instructed. + * +DOT subgraph xcluster_hit { +DOT hit [ +DOT shape=record +DOT label="{cnt_hit:|{vcl_hit()|{req.|obj.}}|{error?|restart?}|{deliver?|pass?}}" +DOT ] +DOT } +XDOT hit:err -> err_hit [label="error"] +XDOT err_hit [label="ERROR",shape=plaintext] +XDOT hit:rst -> rst_hit [label="restart",color=purple] +XDOT rst_hit [label="RESTART",shape=plaintext] +DOT hit:pass -> pass [label=pass,style=bold,color=red] +DOT hit:del -> prepresp [label="deliver",style=bold,color=green] + */ + +static enum req_fsm_nxt +cnt_hit(struct worker *wrk, struct req *req) +{ + CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); + CHECK_OBJ_NOTNULL(req, REQ_MAGIC); + + CHECK_OBJ_NOTNULL(req->obj, OBJECT_MAGIC); + CHECK_OBJ_NOTNULL(req->vcl, VCL_CONF_MAGIC); + AZ(req->objcore); + AZ(req->busyobj); + + assert(!(req->obj->objcore->flags & OC_F_PASS)); + + VCL_hit_method(req); + + if (req->handling == VCL_RET_DELIVER) { + //AZ(req->busyobj->bereq->ws); + //AZ(req->busyobj->beresp->ws); + (void)HTTP1_DiscardReqBody(req); // XXX: handle err + req->req_step = R_STP_PREPRESP; + return (REQ_FSM_MORE); + } + + /* Drop our object, we won't need it */ + (void)HSH_Deref(&wrk->stats, NULL, &req->obj); + req->objcore = NULL; + + switch(req->handling) { + case VCL_RET_PASS: + req->req_step = R_STP_PASS; + return (REQ_FSM_MORE); + case VCL_RET_ERROR: + req->req_step = R_STP_ERROR; + return (REQ_FSM_MORE); + case VCL_RET_RESTART: + req->req_step = R_STP_RESTART; + return (REQ_FSM_MORE); + default: + WRONG("Illegal action in vcl_hit{}"); + } +} + +/*-------------------------------------------------------------------- + * LOOKUP + * Hash things together and look object up in hash-table. + * + * LOOKUP consists of two substates so that we can reenter if we + * encounter a busy object. + * +DOT subgraph xcluster_lookup { +DOT lookup [ +DOT shape=record +DOT label="{cnt_lookup:|hash lookup|{busy ?|miss ?}|{no|obj.f.pass?|yes}}" +DOT ] +DOT } +DOT lookup:busy -> lookup:top [label="(waitinglist)"] +DOT lookup:miss -> miss [style=bold,color=blue] +DOT lookup:no -> hit [style=bold,color=green] +DOT lookup:yes -> pass [style=bold,color=red] + */ + +static enum req_fsm_nxt +cnt_lookup(struct worker *wrk, struct req *req) +{ + struct objcore *oc; + struct object *o; + struct objhead *oh; + struct busyobj *bo; + + CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); + CHECK_OBJ_NOTNULL(req, REQ_MAGIC); + AZ(req->objcore); + + CHECK_OBJ_NOTNULL(req->vcl, VCL_CONF_MAGIC); + AZ(req->busyobj); + + VRY_Prep(req); + + AZ(req->objcore); + oc = HSH_Lookup(req); + if (oc == NULL) { + /* + * We lost the session to a busy object, disembark the + * worker thread. We return to STP_LOOKUP when the busy + * object has been unbusied, and still have the objhead + * around to restart the lookup with. + */ + return (REQ_FSM_DISEMBARK); + } + AZ(req->objcore); + + CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC); + oh = oc->objhead; + CHECK_OBJ_NOTNULL(oh, OBJHEAD_MAGIC); + + /* If we inserted a new object it's a miss */ + if (oc->flags & OC_F_BUSY) { + AZ(req->busyobj); + bo = VBO_GetBusyObj(wrk, req); + req->busyobj = bo; + /* One ref for req, one for FetchBody */ + bo->refcount = 2; + VRY_Finish(req, bo); + + oc->busyobj = bo; + wrk->stats.cache_miss++; + + req->objcore = oc; + req->req_step = R_STP_MISS; + return (REQ_FSM_MORE); + } + + /* We are not prepared to do streaming yet */ + XXXAZ(req->busyobj); + + o = oc_getobj(&wrk->stats, oc); + CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC); + req->obj = o; + + VRY_Finish(req, NULL); + + if (oc->flags & OC_F_PASS) { + wrk->stats.cache_hitpass++; + VSLb(req->vsl, SLT_HitPass, "%u", req->obj->vxid); + (void)HSH_Deref(&wrk->stats, NULL, &req->obj); + AZ(req->objcore); + req->req_step = R_STP_PASS; + return (REQ_FSM_MORE); + } + + wrk->stats.cache_hit++; + VSLb(req->vsl, SLT_Hit, "%u", req->obj->vxid); + req->req_step = R_STP_HIT; + return (REQ_FSM_MORE); +} + +/*-------------------------------------------------------------------- + * We had a miss, ask VCL, proceed as instructed + * +DOT subgraph xcluster_miss { +DOT miss [ +DOT shape=record +DOT label="{cnt_miss:|filter req.-\>bereq.|{vcl_miss\{\}|{req.*|bereq.*}}|{error?|restart?}|{pass?|fetch?}}" +DOT ] +DOT } +DOT miss:fetch -> fetch [label="fetch",style=bold,color=blue] +DOT miss:pass -> pass [label="pass",style=bold,color=red] +DOT + */ + +static enum req_fsm_nxt +cnt_miss(struct worker *wrk, struct req *req) +{ + struct busyobj *bo; + + CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); + CHECK_OBJ_NOTNULL(req, REQ_MAGIC); + CHECK_OBJ_NOTNULL(req->vcl, VCL_CONF_MAGIC); + CHECK_OBJ_NOTNULL(req->objcore, OBJCORE_MAGIC); + bo = req->busyobj; + CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC); + AZ(req->obj); + + HTTP_Setup(bo->bereq, bo->ws, bo->vsl, HTTP_Bereq); + http_FilterReq(req, HTTPH_R_FETCH); + http_ForceGet(bo->bereq); + if (cache_param->http_gzip_support) { + /* + * We always ask the backend for gzip, even if the + * client doesn't grok it. We will uncompress for + * the minority of clients which don't. + */ + http_Unset(bo->bereq, H_Accept_Encoding); + http_SetHeader(bo->bereq, "Accept-Encoding: gzip"); + } + + VCL_miss_method(req); + + if (req->handling == VCL_RET_FETCH) { + CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC); + req->req_step = R_STP_FETCH; + return (REQ_FSM_MORE); + } + + AZ(HSH_Deref(&wrk->stats, req->objcore, NULL)); + req->objcore = NULL; + http_Teardown(bo->bereq); + VBO_DerefBusyObj(wrk, &req->busyobj); + + switch(req->handling) { + case VCL_RET_ERROR: + req->req_step = R_STP_ERROR; + break; + case VCL_RET_PASS: + req->req_step = R_STP_PASS; + break; + case VCL_RET_RESTART: + req->req_step = R_STP_RESTART; + break; + default: + WRONG("Illegal action in vcl_miss{}"); + } + return (REQ_FSM_MORE); +} + +/*-------------------------------------------------------------------- + * Start pass processing by getting headers from backend, then + * continue in passbody. + * +DOT subgraph xcluster_pass { +DOT pass [ +DOT shape=record +DOT label="{cnt_pass:|(XXX: deref obj.)|filter req.*-\>bereq.|{vcl_pass\{\}|{req.*|bereq.*}}|{error?|restart?}|create anon obj}" +DOT ] +DOT } +DOT pass:pass -> fetch [style=bold, color=red] +XDOT pass:rst -> rst_pass [label="restart",color=purple] +XDOT rst_pass [label="RESTART",shape=plaintext] +XDOT pass:err -> err_pass [label="error"] +XDOT err_pass [label="ERROR",shape=plaintext] + */ + +static enum req_fsm_nxt +cnt_pass(struct worker *wrk, struct req *req) +{ + struct busyobj *bo; + + CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); + CHECK_OBJ_NOTNULL(req, REQ_MAGIC); + CHECK_OBJ_NOTNULL(req->vcl, VCL_CONF_MAGIC); + AZ(req->objcore); + AZ(req->obj); + AZ(req->busyobj); + + req->busyobj = VBO_GetBusyObj(wrk, req); + bo = req->busyobj; + bo->refcount = 2; + HTTP_Setup(bo->bereq, bo->ws, bo->vsl, HTTP_Bereq); + http_FilterReq(req, HTTPH_R_PASS); + + VCL_pass_method(req); + + if (req->handling == VCL_RET_ERROR) { + http_Teardown(bo->bereq); + VBO_DerefBusyObj(wrk, &req->busyobj); + req->req_step = R_STP_ERROR; + return (REQ_FSM_MORE); + } + assert(req->handling == VCL_RET_PASS); + req->acct_req.pass++; + req->req_step = R_STP_FETCH; + + req->objcore = HSH_NewObjCore(wrk); + req->objcore->busyobj = bo; + return (REQ_FSM_MORE); +} + +/*-------------------------------------------------------------------- + * Ship the request header to the backend unchanged, then pipe + * until one of the ends close the connection. + * +DOT subgraph xcluster_pipe { +DOT pipe [ +DOT shape=ellipse +DOT label="Filter req.->bereq." +DOT ] +DOT vcl_pipe [ +DOT shape=record +DOT label="vcl_pipe()|req.\nbereq\." +DOT ] +DOT pipe_do [ +DOT shape=ellipse +DOT label="send bereq.\npipe until close" +DOT ] +DOT vcl_pipe -> pipe_do [label="pipe",style=bold,color=orange] +DOT pipe -> vcl_pipe [style=bold,color=orange] +DOT } +DOT pipe_do -> DONE [style=bold,color=orange] +DOT vcl_pipe -> err_pipe [label="error"] +DOT err_pipe [label="ERROR",shape=plaintext] + */ + +static enum req_fsm_nxt +cnt_pipe(struct worker *wrk, struct req *req) +{ + struct busyobj *bo; + + CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); + CHECK_OBJ_NOTNULL(req, REQ_MAGIC); + CHECK_OBJ_NOTNULL(req->vcl, VCL_CONF_MAGIC); + AZ(req->busyobj); + + req->acct_req.pipe++; + req->busyobj = VBO_GetBusyObj(wrk, req); + bo = req->busyobj; + HTTP_Setup(bo->bereq, bo->ws, bo->vsl, HTTP_Bereq); + http_FilterReq(req, 0); + + VCL_pipe_method(req); + + if (req->handling == VCL_RET_ERROR) + INCOMPL(); + assert(req->handling == VCL_RET_PIPE); + + PipeRequest(req); + assert(WRW_IsReleased(wrk)); + http_Teardown(bo->bereq); + VBO_DerefBusyObj(wrk, &req->busyobj); + return (REQ_FSM_DONE); +} + +/*-------------------------------------------------------------------- + * +DOT subgraph xcluster_restart { +DOT restart [ +DOT shape=record +DOT label="{cnt_restart}" +DOT ] +DOT } +DOT RESTART -> restart [color=purple] +DOT restart -> recv [color=purple] +DOT restart -> err_restart +DOT err_restart [label="ERROR",shape=plaintext] + */ + +static enum req_fsm_nxt +cnt_restart(const struct worker *wrk, struct req *req) +{ + + CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); + CHECK_OBJ_NOTNULL(req, REQ_MAGIC); + + req->director = NULL; + if (++req->restarts >= cache_param->max_restarts) { + req->err_code = 503; + req->req_step = R_STP_ERROR; + } else { + req->err_code = 0; + req->req_step = R_STP_RECV; + } + return (REQ_FSM_MORE); +} + +/*-------------------------------------------------------------------- + * RECV + * We have a complete request, set everything up and start it. + * We can come here both with a request from the client and with + * a interior request during ESI delivery. + * +DOT subgraph xcluster_recv { +DOT recv [ +DOT shape=record +DOT label="{cnt_recv:|{vcl_recv\{\}|req.*}|{pipe?|pass?|error?|lookup?}}" +DOT ] +DOT } +DOT subgraph xcluster_hash { +DOT hash [ +DOT shape=record +DOT label="{cnt_recv:|{vcl_hash\{\}|req.*}}" +DOT ] +DOT } +DOT recv:pipe -> pipe [style=bold,color=orange] +DOT recv:pass -> pass [style=bold,color=red] +#DOT recv:error -> err_recv +#DOT err_recv [label="ERROR",shape=plaintext] +DOT recv:lookup -> hash [style=bold,color=green] +DOT hash -> lookup [label="hash",style=bold,color=green] + */ + +static enum req_fsm_nxt +cnt_recv(const struct worker *wrk, struct req *req) +{ + unsigned recv_handling; + struct SHA256Context sha256ctx; + + CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); + CHECK_OBJ_NOTNULL(req, REQ_MAGIC); + CHECK_OBJ_NOTNULL(req->vcl, VCL_CONF_MAGIC); + AZ(req->objcore); + AZ(req->obj); + AZ(req->objcore); + AZ(req->busyobj); + + VSLb(req->vsl, SLT_ReqStart, "%s %s", req->sp->addr, req->sp->port); + + if (req->err_code) { + req->req_step = R_STP_ERROR; + return (REQ_FSM_MORE); + } + + /* By default we use the first backend */ + AZ(req->director); + req->director = req->vcl->director[0]; + AN(req->director); + + EXP_Clr(&req->exp); + + req->disable_esi = 0; + req->hash_always_miss = 0; + req->hash_ignore_busy = 0; + req->client_identity = NULL; + + http_CollectHdr(req->http, H_Cache_Control); + + VCL_recv_method(req); + recv_handling = req->handling; + + if (cache_param->http_gzip_support && + (recv_handling != VCL_RET_PIPE) && + (recv_handling != VCL_RET_PASS)) { + if (RFC2616_Req_Gzip(req->http)) { + http_Unset(req->http, H_Accept_Encoding); + http_SetHeader(req->http, "Accept-Encoding: gzip"); + } else { + http_Unset(req->http, H_Accept_Encoding); + } + } + + req->sha256ctx = &sha256ctx; /* so HSH_AddString() can find it */ + SHA256_Init(req->sha256ctx); + VCL_hash_method(req); + assert(req->handling == VCL_RET_HASH); + SHA256_Final(req->digest, req->sha256ctx); + req->sha256ctx = NULL; + + if (!strcmp(req->http->hd[HTTP_HDR_METHOD].b, "HEAD")) + req->wantbody = 0; + else + req->wantbody = 1; + + switch(recv_handling) { + case VCL_RET_LOOKUP: + req->req_step = R_STP_LOOKUP; + return (REQ_FSM_MORE); + case VCL_RET_PIPE: + if (req->esi_level > 0) { + /* XXX: VSL something */ + INCOMPL(); + return (REQ_FSM_DONE); + } + req->req_step = R_STP_PIPE; + return (REQ_FSM_MORE); + case VCL_RET_PASS: + req->req_step = R_STP_PASS; + return (REQ_FSM_MORE); + case VCL_RET_ERROR: + req->req_step = R_STP_ERROR; + return (REQ_FSM_MORE); + default: + WRONG("Illegal action in vcl_recv{}"); + } +} + +/*-------------------------------------------------------------------- + * Central state engine dispatcher. + * + * Kick the session around until it has had enough. + * + */ + +static void +cnt_diag(struct req *req, const char *state) +{ + + CHECK_OBJ_NOTNULL(req, REQ_MAGIC); + + VSLb(req->vsl, SLT_Debug, "vxid %u STP_%s sp %p obj %p vcl %p", + req->vsl->wid, state, req->sp, req->obj, req->vcl); + VSL_Flush(req->vsl, 0); +} + +enum req_fsm_nxt +CNT_Request(struct worker *wrk, struct req *req) +{ + enum req_fsm_nxt nxt; + struct storage *st; + + CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); + CHECK_OBJ_NOTNULL(req, REQ_MAGIC); + + /* + * Possible entrance states + */ + assert( + req->req_step == R_STP_LOOKUP || + req->req_step == R_STP_RECV); + + AN(req->vsl->wid & VSL_CLIENTMARKER); + + req->wrk = wrk; + + for (nxt = REQ_FSM_MORE; nxt == REQ_FSM_MORE; ) { + /* + * This is a good place to be paranoid about the various + * pointers still pointing to the things we expect. + */ + CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); + CHECK_OBJ_ORNULL(wrk->nobjhead, OBJHEAD_MAGIC); + CHECK_OBJ_NOTNULL(req, REQ_MAGIC); + + /* + * We don't want the thread workspace to be used for + * anything of long duration, so mandate that it be + * empty on state-transitions. + */ + WS_Assert(wrk->aws); + assert(wrk->aws->s == wrk->aws->f); + + switch (req->req_step) { +#define REQ_STEP(l,u,arg) \ + case R_STP_##u: \ + if (DO_DEBUG(DBG_REQ_STATE)) \ + cnt_diag(req, #u); \ + nxt = cnt_##l arg; \ + break; +#include "tbl/steps.h" +#undef REQ_STEP + default: + WRONG("State engine misfire"); + } + WS_Assert(wrk->aws); + CHECK_OBJ_ORNULL(wrk->nobjhead, OBJHEAD_MAGIC); + } + if (nxt == REQ_FSM_DONE) { + /* XXX: Workaround for pipe */ + if (req->sp->fd >= 0) { + VSLb(req->vsl, SLT_Length, "%ju", + (uintmax_t)req->resp_bodybytes); + } + VSLb(req->vsl, SLT_ReqEnd, "%.9f %.9f %.9f %.9f %.9f", + req->t_req, + req->sp->t_idle, + req->sp->t_idle - req->t_resp, + req->t_resp - req->t_req, + req->sp->t_idle - req->t_resp); + + while (!VTAILQ_EMPTY(&req->body)) { + st = VTAILQ_FIRST(&req->body); + VTAILQ_REMOVE(&req->body, st, list); + STV_free(st); + } + + /* done == 2 was charged by cache_hash.c */ + SES_Charge(wrk, req); + + /* + * Nuke the VXID, cache_http1_fsm.c::http1_dissect() will + * allocate a new one when necessary. + */ + req->vsl->wid = 0; + } + + req->wrk = NULL; + + assert(WRW_IsReleased(wrk)); + return (nxt); +} + +/* +DOT } +*/ diff --git a/bin/varnishd/cache_center.c b/bin/varnishd/cache_center.c index ea0a961..ba16417 100644 --- a/bin/varnishd/cache_center.c +++ b/bin/varnishd/cache_center.c @@ -764,12 +764,21 @@ cnt_fetchbody(struct sess *sp) /* Create Vary instructions */ if (sp->objcore != NULL) { CHECK_OBJ_NOTNULL(sp->objcore, OBJCORE_MAGIC); - vary = VRY_Create(sp, sp->wrk->beresp); - if (vary != NULL) { - varyl = VSB_len(vary); - assert(varyl > 0); + varyl = VRY_Create(sp, sp->wrk->beresp, &vary); + if (varyl > 0) { + AN(vary); + assert(varyl == VSB_len(vary)); l += varyl; - } + } else if (varyl < 0) { + /* Vary parse error */ + AZ(vary); + sp->err_code = 503; + sp->step = STP_ERROR; + VDI_CloseFd(sp); + return (0); + } else + /* No vary */ + AZ(vary); } /* diff --git a/bin/varnishd/cache_vary.c b/bin/varnishd/cache_vary.c index b7a6b01..f6ec5f2 100644 --- a/bin/varnishd/cache_vary.c +++ b/bin/varnishd/cache_vary.c @@ -61,16 +61,29 @@ #include "vend.h" #include "vct.h" -struct vsb * -VRY_Create(const struct sess *sp, const struct http *hp) +/********************************************************************** + * Create a Vary matching string from a Vary header + * + * Return value: + * <0: Parse error + * 0: No Vary header on object + * >0: Length of Vary matching string in *psb + */ + +int +VRY_Create(const struct sess *sp, const struct http *hp, struct vsb **psb) { char *v, *p, *q, *h, *e; struct vsb *sb, *sbh; int l; + int error = 0; + + AN(psb); + AZ(*psb); /* No Vary: header, no worries */ if (!http_GetHdr(hp, H_Vary, &v)) - return (NULL); + return (0); /* For vary matching string */ sb = VSB_new_auto(); @@ -124,12 +137,20 @@ VRY_Create(const struct sess *sp, const struct http *hp) xxxassert(*q == ','); p = q; } + + if (error) { + VSB_delete(sbh); + VSB_delete(sb); + return (-1); + } + /* Terminate vary matching string */ VSB_printf(sb, "%c%c%c", 0xff, 0xff, 0); VSB_delete(sbh); AZ(VSB_finish(sb)); - return(sb); + *psb = sb; + return (VSB_len(sb)); } /* From martin at varnish-cache.org Tue Mar 19 15:35:49 2013 From: martin at varnish-cache.org (Martin Blix Grydeland) Date: Tue, 19 Mar 2013 16:35:49 +0100 Subject: [3.0] 3f2ce1e Don't panic on malformed Vary headers. Message-ID: commit 3f2ce1efedb7cab76048ae62a33b59023c06cb88 Author: Martin Blix Grydeland Date: Mon Mar 18 17:07:46 2013 +0100 Don't panic on malformed Vary headers. Fixes: #1275 Test case by: Dag Haavi Finstad diff --git a/bin/varnishd/cache_vary.c b/bin/varnishd/cache_vary.c index f6ec5f2..c53a19a 100644 --- a/bin/varnishd/cache_vary.c +++ b/bin/varnishd/cache_vary.c @@ -134,7 +134,11 @@ VRY_Create(const struct sess *sp, const struct http *hp, struct vsb **psb) q++; if (*q == '\0') break; - xxxassert(*q == ','); + if (*q != ',') { + WSP(sp, SLT_Error, "Malformed Vary header"); + error = 1; + break; + } p = q; } diff --git a/bin/varnishtest/tests/r01275.vtc b/bin/varnishtest/tests/r01275.vtc new file mode 100644 index 0000000..72c7184 --- /dev/null +++ b/bin/varnishtest/tests/r01275.vtc @@ -0,0 +1,14 @@ +varnishtest "#1275 - panic with malformed Vary header" + +server s1 { + rxreq + txresp -hdr "Vary: foo bar" +} -start + +varnish v1 -vcl+backend { } -start + +client c1 { + txreq + rxresp + expect resp.status == 503 +} -run From martin at varnish-cache.org Tue Mar 19 15:35:49 2013 From: martin at varnish-cache.org (Martin Blix Grydeland) Date: Tue, 19 Mar 2013 16:35:49 +0100 Subject: [3.0] 6f5812c Return 503 when Vary-headers references header names more than 127 (out limit) characters long. Message-ID: commit 6f5812c528430fabd175611aeb51b0c9c8dc42b0 Author: Martin Blix Grydeland Date: Mon Mar 18 17:00:57 2013 +0100 Return 503 when Vary-headers references header names more than 127 (out limit) characters long. Fixes: #1274 Test case by: Dag Haavi Finstad diff --git a/bin/varnishd/cache_vary.c b/bin/varnishd/cache_vary.c index c53a19a..65a1978 100644 --- a/bin/varnishd/cache_vary.c +++ b/bin/varnishd/cache_vary.c @@ -105,6 +105,12 @@ VRY_Create(const struct sess *sp, const struct http *hp, struct vsb **psb) for (q = p; *q && !vct_issp(*q) && *q != ','; q++) continue; + if (q - p > INT8_MAX) { + WSP(sp, SLT_Error, "Vary header name length exceeded"); + error = 1; + break; + } + /* Build a header-matching string out of it */ VSB_clear(sbh); VSB_printf(sbh, "%c%.*s:%c", diff --git a/bin/varnishtest/tests/r01274.vtc b/bin/varnishtest/tests/r01274.vtc new file mode 100644 index 0000000..fe427cc --- /dev/null +++ b/bin/varnishtest/tests/r01274.vtc @@ -0,0 +1,15 @@ +varnishtest "#1274 - panic when Vary field-name is too large to fit in a signed char" + +server s1 { + rxreq + # Vary header more than 127 characters long + txresp -hdr "Vary: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +} -start + +varnish v1 -vcl+backend { } -start + +client c1 { + txreq + rxresp + expect resp.status == 503 +} -run From martin at varnish-cache.org Tue Mar 19 15:35:49 2013 From: martin at varnish-cache.org (Martin Blix Grydeland) Date: Tue, 19 Mar 2013 16:35:49 +0100 Subject: [3.0] bcc81eb Throw 503 on exceeding max 65k Vary header constituent limit. Message-ID: commit bcc81eb5b516628088b24eaa23e2f851d6b80ce7 Author: Martin Blix Grydeland Date: Mon Mar 18 17:53:35 2013 +0100 Throw 503 on exceeding max 65k Vary header constituent limit. diff --git a/bin/varnishd/cache_vary.c b/bin/varnishd/cache_vary.c index 65a1978..a415822 100644 --- a/bin/varnishd/cache_vary.c +++ b/bin/varnishd/cache_vary.c @@ -125,7 +125,12 @@ VRY_Create(const struct sess *sp, const struct http *hp, struct vsb **psb) e--; /* Encode two byte length and contents */ l = e - h; - assert(!(l & ~0xffff)); + if (l > 0xffff - 1) { + WSP(sp, SLT_Error, + "Vary header maximum length exceeded"); + error = 1; + break; + } } else { e = h; l = 0xffff; From martin at varnish-cache.org Tue Mar 19 15:35:49 2013 From: martin at varnish-cache.org (Martin Blix Grydeland) Date: Tue, 19 Mar 2013 16:35:49 +0100 Subject: [3.0] be4891e Remove dodgy workaround introduced for #763. Message-ID: commit be4891e87d918598920f49a38d0c74fa5dbd5ded Author: Martin Blix Grydeland Date: Mon Mar 18 17:11:34 2013 +0100 Remove dodgy workaround introduced for #763. With fix for #1275 we can now do a proper 503 when malformed Vary-headers are received from backend. Error out instead of accepting bogus ':'. Conflicts: bin/varnishd/cache_vary.c diff --git a/bin/varnishd/cache_vary.c b/bin/varnishd/cache_vary.c index a415822..ead247d 100644 --- a/bin/varnishd/cache_vary.c +++ b/bin/varnishd/cache_vary.c @@ -93,10 +93,6 @@ VRY_Create(const struct sess *sp, const struct http *hp, struct vsb **psb) sbh = VSB_new_auto(); AN(sbh); - if (*v == ':') { - WSP(sp, SLT_Error, "Vary header had extra ':', fix backend"); - v++; - } for (p = v; *p; p++) { /* Find next header-name */ diff --git a/bin/varnishtest/tests/r00763.vtc b/bin/varnishtest/tests/r00763.vtc index 24a4d6f..72fced4 100644 --- a/bin/varnishtest/tests/r00763.vtc +++ b/bin/varnishtest/tests/r00763.vtc @@ -10,5 +10,5 @@ varnish v1 -vcl+backend {} -start client c1 { txreq rxresp - expect resp.http.vary == ": foo" + expect resp.status == 503 } -run From martin at varnish-cache.org Tue Mar 19 15:35:49 2013 From: martin at varnish-cache.org (Martin Blix Grydeland) Date: Tue, 19 Mar 2013 16:35:49 +0100 Subject: [3.0] 6d9426d Document Vary parse error behavior Message-ID: commit 6d9426dcf3b9693c90301231c1fb1761bef42f7e Author: Martin Blix Grydeland Date: Tue Mar 19 15:37:05 2013 +0100 Document Vary parse error behavior diff --git a/doc/sphinx/tutorial/vary.rst b/doc/sphinx/tutorial/vary.rst index ad7b48d..236f078 100644 --- a/doc/sphinx/tutorial/vary.rst +++ b/doc/sphinx/tutorial/vary.rst @@ -42,6 +42,14 @@ following VCL code will normalize the Accept-Encoding headers:: The code sets the Accept-Encoding header from the client to either gzip, deflate with a preference for gzip. +Vary parse errors +~~~~~~~~~~~~~~~~~ + +Varnish will return a 503 internal server error page when it fails to +parse the Vary server header, or if any of the client headers listed +in the Vary header exceeds the limit of 65k characters. An SLT_Error +log entry is added in these cases. + Pitfall - Vary: User-Agent ~~~~~~~~~~~~~~~~~~~~~~~~~~ From daghf at varnish-cache.org Wed Mar 20 09:52:09 2013 From: daghf at varnish-cache.org (Dag Haavi Finstad) Date: Wed, 20 Mar 2013 10:52:09 +0100 Subject: [master] b7572af Fixes an issue in backend probe initialization that causes the default value of .initial to equal .threshold. Message-ID: commit b7572affa9e7cc4c2d77c90c51e8bf2418ac9613 Author: Dag Haavi Finstad Date: Wed Mar 20 10:45:24 2013 +0100 Fixes an issue in backend probe initialization that causes the default value of .initial to equal .threshold. The default for .initial is now .threshold - 1, meaning that the backend starts up as sick and a single successful poll is required for it to be considered healthy. With the previous behaviour, a sick backend would not be considered sick until after the initial polls exit the polling window. Thanks to Colin Curtin. Fixes: #1227 diff --git a/bin/varnishd/cache/cache_backend_poll.c b/bin/varnishd/cache/cache_backend_poll.c index ab405f9..4780165 100644 --- a/bin/varnishd/cache/cache_backend_poll.c +++ b/bin/varnishd/cache/cache_backend_poll.c @@ -461,7 +461,7 @@ vbp_new_vcl(const struct vrt_backend_probe *p, const char *hosthdr) if (vcl->probe.exp_status == 0) vcl->probe.exp_status = 200; - if (vcl->probe.threshold == ~0U) + if (vcl->probe.initial == ~0U) vcl->probe.initial = vcl->probe.threshold - 1; if (vcl->probe.initial > vcl->probe.threshold) diff --git a/doc/sphinx/reference/vcl.rst b/doc/sphinx/reference/vcl.rst index ca9c4c0..b5f5dec 100644 --- a/doc/sphinx/reference/vcl.rst +++ b/doc/sphinx/reference/vcl.rst @@ -201,8 +201,10 @@ Probes take the following parameters: the backend healthy. Defaults to 3. .initial - How many of the probes are considered good when Varnish starts. - Defaults to the same amount as the threshold. + How many of the polls in .window are considered good when Varnish + starts. Defaults to the value of threshold - 1. In this case, the + backend starts as sick and requires one single poll to be considered + healthy. .expected_response The expected backend HTTP response code. Defaults to 200. From phk at varnish-cache.org Wed Mar 20 12:08:50 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Wed, 20 Mar 2013 13:08:50 +0100 Subject: [master] 084fe15 Rename vcl_fetch{} to vcl_response{} Message-ID: commit 084fe159017f38b5b132dbb68f3bc60ab1557935 Author: Poul-Henning Kamp Date: Wed Mar 20 12:08:36 2013 +0000 Rename vcl_fetch{} to vcl_response{} diff --git a/bin/varnishd/cache/cache_req_fsm.c b/bin/varnishd/cache/cache_req_fsm.c index e1fd343..2c65976 100644 --- a/bin/varnishd/cache/cache_req_fsm.c +++ b/bin/varnishd/cache/cache_req_fsm.c @@ -416,7 +416,7 @@ cnt_fetch(struct worker *wrk, struct req *req) AZ(bo->do_esi); AZ(bo->do_pass); - VCL_fetch_method(req); + VCL_response_method(req); if (bo->do_pass) req->objcore->flags |= OC_F_PASS; diff --git a/bin/varnishd/default.vcl b/bin/varnishd/default.vcl index 0e2031a..8b90194 100644 --- a/bin/varnishd/default.vcl +++ b/bin/varnishd/default.vcl @@ -101,7 +101,7 @@ sub vcl_miss { return (fetch); } -sub vcl_fetch { +sub vcl_response { if (beresp.ttl <= 0s || beresp.http.Set-Cookie || beresp.http.Surrogate-control ~ "no-store" || diff --git a/bin/varnishtest/tests.disabled/r00929.vtc b/bin/varnishtest/tests.disabled/r00929.vtc index 3b2f7ca..996465a 100644 --- a/bin/varnishtest/tests.disabled/r00929.vtc +++ b/bin/varnishtest/tests.disabled/r00929.vtc @@ -8,7 +8,7 @@ server s1 { varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.do_stream = true; } diff --git a/bin/varnishtest/tests.disabled/r00978.vtc b/bin/varnishtest/tests.disabled/r00978.vtc index 39b89cb..e14402d 100644 --- a/bin/varnishtest/tests.disabled/r00978.vtc +++ b/bin/varnishtest/tests.disabled/r00978.vtc @@ -22,7 +22,7 @@ varnish v1 -vcl+backend { set req.url = req.url + req.esi_level; } } - sub vcl_fetch { + sub vcl_response { if (req.url == "/") { set beresp.do_esi = true; } diff --git a/bin/varnishtest/tests.disabled/r00979.vtc b/bin/varnishtest/tests.disabled/r00979.vtc index bc72efc..0857981 100644 --- a/bin/varnishtest/tests.disabled/r00979.vtc +++ b/bin/varnishtest/tests.disabled/r00979.vtc @@ -11,7 +11,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.do_stream = true; } sub vcl_deliver { diff --git a/bin/varnishtest/tests.disabled/r00980.vtc b/bin/varnishtest/tests.disabled/r00980.vtc index b7d307e..da4d83c 100644 --- a/bin/varnishtest/tests.disabled/r00980.vtc +++ b/bin/varnishtest/tests.disabled/r00980.vtc @@ -9,7 +9,7 @@ server s1 { varnish v1 -cliok "param.set http_gzip_support true" -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.do_gzip = true; set beresp.do_stream = true; } diff --git a/bin/varnishtest/tests.disabled/t00000.vtc b/bin/varnishtest/tests.disabled/t00000.vtc index 8265195..b4fcc5b 100644 --- a/bin/varnishtest/tests.disabled/t00000.vtc +++ b/bin/varnishtest/tests.disabled/t00000.vtc @@ -15,7 +15,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.do_stream = true; } } -start diff --git a/bin/varnishtest/tests.disabled/t00001.vtc b/bin/varnishtest/tests.disabled/t00001.vtc index 2237466..84aa647 100644 --- a/bin/varnishtest/tests.disabled/t00001.vtc +++ b/bin/varnishtest/tests.disabled/t00001.vtc @@ -22,7 +22,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { if (req.url == "/foo") { set beresp.do_gzip = true; } diff --git a/bin/varnishtest/tests/b00015.vtc b/bin/varnishtest/tests/b00015.vtc index fc022c3..7cb1b97 100644 --- a/bin/varnishtest/tests/b00015.vtc +++ b/bin/varnishtest/tests/b00015.vtc @@ -53,7 +53,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { if (beresp.status == 502) { set beresp.ttl = 10m; } diff --git a/bin/varnishtest/tests/b00018.vtc b/bin/varnishtest/tests/b00018.vtc index bbd7c0e..6197511 100644 --- a/bin/varnishtest/tests/b00018.vtc +++ b/bin/varnishtest/tests/b00018.vtc @@ -1,4 +1,4 @@ -varnishtest "Check that error in vcl_fetch works" +varnishtest "Check that error in vcl_response works" server s1 { rxreq @@ -6,7 +6,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.http.Foo = "bar"; error 523 "not ok"; } diff --git a/bin/varnishtest/tests/b00019.vtc b/bin/varnishtest/tests/b00019.vtc index 2572a57..542e32d 100644 --- a/bin/varnishtest/tests/b00019.vtc +++ b/bin/varnishtest/tests/b00019.vtc @@ -21,7 +21,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { return (restart); } diff --git a/bin/varnishtest/tests/b00020.vtc b/bin/varnishtest/tests/b00020.vtc index 365c305..a6baaed 100644 --- a/bin/varnishtest/tests/b00020.vtc +++ b/bin/varnishtest/tests/b00020.vtc @@ -10,7 +10,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.do_stream = false; } } -start diff --git a/bin/varnishtest/tests/b00021.vtc b/bin/varnishtest/tests/b00021.vtc index 5c3261a..eedcca2 100644 --- a/bin/varnishtest/tests/b00021.vtc +++ b/bin/varnishtest/tests/b00021.vtc @@ -13,7 +13,7 @@ varnish v1 -vcl+backend { sub vcl_miss { set bereq.between_bytes_timeout = 2s; } - sub vcl_fetch { + sub vcl_response { set beresp.do_stream = false; } } -start diff --git a/bin/varnishtest/tests/b00022.vtc b/bin/varnishtest/tests/b00022.vtc index 722d9f1..9f4dd1e 100644 --- a/bin/varnishtest/tests/b00022.vtc +++ b/bin/varnishtest/tests/b00022.vtc @@ -15,7 +15,7 @@ varnish v1 -vcl { .port = "${s1_port}"; .between_bytes_timeout = 1s; } - sub vcl_fetch { + sub vcl_response { set beresp.do_stream = false; } } -start diff --git a/bin/varnishtest/tests/b00027.vtc b/bin/varnishtest/tests/b00027.vtc index 9cc7a7a..941dc9c 100644 --- a/bin/varnishtest/tests/b00027.vtc +++ b/bin/varnishtest/tests/b00027.vtc @@ -12,7 +12,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.do_stream = false; } } -start diff --git a/bin/varnishtest/tests/b00028.vtc b/bin/varnishtest/tests/b00028.vtc index 20e30aa..6316fde 100644 --- a/bin/varnishtest/tests/b00028.vtc +++ b/bin/varnishtest/tests/b00028.vtc @@ -7,7 +7,7 @@ server s1 { varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { if (beresp.http.foo ~ "bar") { set beresp.http.foo1 = "1"; } else { diff --git a/bin/varnishtest/tests/c00001.vtc b/bin/varnishtest/tests/c00001.vtc index f1a6824..bfc9d08 100644 --- a/bin/varnishtest/tests/c00001.vtc +++ b/bin/varnishtest/tests/c00001.vtc @@ -9,7 +9,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.http.Snafu1 = regsub(beresp.http.Foobar, "ar", "\0\0"); set beresp.http.Snafu2 = regsub(beresp.http.Foobar, "(b)(a)(r)(f)", "\4\3\2p"); diff --git a/bin/varnishtest/tests/c00009.vtc b/bin/varnishtest/tests/c00009.vtc index d0c4b71..9d5f1a0 100644 --- a/bin/varnishtest/tests/c00009.vtc +++ b/bin/varnishtest/tests/c00009.vtc @@ -21,7 +21,7 @@ varnish v1 -vcl+backend { } } - sub vcl_fetch { + sub vcl_response { if (beresp.status != 200) { return (restart); } diff --git a/bin/varnishtest/tests/c00011.vtc b/bin/varnishtest/tests/c00011.vtc index 952966b..3145575 100644 --- a/bin/varnishtest/tests/c00011.vtc +++ b/bin/varnishtest/tests/c00011.vtc @@ -10,7 +10,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.do_pass = true; } } -start diff --git a/bin/varnishtest/tests/c00014.vtc b/bin/varnishtest/tests/c00014.vtc index 7e5dab1..aefd1ce 100644 --- a/bin/varnishtest/tests/c00014.vtc +++ b/bin/varnishtest/tests/c00014.vtc @@ -14,7 +14,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.do_pass = true; } } -start diff --git a/bin/varnishtest/tests/c00027.vtc b/bin/varnishtest/tests/c00027.vtc index 62d0716..9e842de 100644 --- a/bin/varnishtest/tests/c00027.vtc +++ b/bin/varnishtest/tests/c00027.vtc @@ -19,7 +19,7 @@ server s1 { } -start varnish v1 -arg "-s malloc,1M" -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.ttl = 10m; } } -start diff --git a/bin/varnishtest/tests/c00029.vtc b/bin/varnishtest/tests/c00029.vtc index 7396a2b..2eb685b 100644 --- a/bin/varnishtest/tests/c00029.vtc +++ b/bin/varnishtest/tests/c00029.vtc @@ -37,7 +37,7 @@ varnish v1 -arg "-p saintmode_threshold=2" -vcl+backend { set req.grace = 1h; } - sub vcl_fetch { + sub vcl_response { if (beresp.http.X-Saint == "yes") { set beresp.saintmode = 20s; return(restart); diff --git a/bin/varnishtest/tests/c00030.vtc b/bin/varnishtest/tests/c00030.vtc index adb39ee..8941a45 100644 --- a/bin/varnishtest/tests/c00030.vtc +++ b/bin/varnishtest/tests/c00030.vtc @@ -44,7 +44,7 @@ varnish v1 -arg "-p saintmode_threshold=10" -vcl { set req.grace = 1h; } - sub vcl_fetch { + sub vcl_response { if (beresp.http.X-Saint == "yes") { set beresp.saintmode = 20s; return (restart); diff --git a/bin/varnishtest/tests/c00032.vtc b/bin/varnishtest/tests/c00032.vtc index 621758f..eb7e57c 100644 --- a/bin/varnishtest/tests/c00032.vtc +++ b/bin/varnishtest/tests/c00032.vtc @@ -20,7 +20,7 @@ varnish v1 -vcl+backend { } } - sub vcl_fetch { + sub vcl_response { if (beresp.status == 400) { rollback; set req.url = "/bar"; diff --git a/bin/varnishtest/tests/c00044.vtc b/bin/varnishtest/tests/c00044.vtc index f72d2e1..ad6d3c6 100644 --- a/bin/varnishtest/tests/c00044.vtc +++ b/bin/varnishtest/tests/c00044.vtc @@ -16,7 +16,7 @@ server s1 { } -start varnish v1 -storage "-smalloc,1m -smalloc,1m, -smalloc,1m" -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.storage = "invalid"; } } -start diff --git a/bin/varnishtest/tests/c00045.vtc b/bin/varnishtest/tests/c00045.vtc index 683c443..a480fe1 100644 --- a/bin/varnishtest/tests/c00045.vtc +++ b/bin/varnishtest/tests/c00045.vtc @@ -10,7 +10,7 @@ server s1 { } -start varnish v1 -storage "-smalloc,1m -smalloc,1m, -smalloc,1m" -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.storage = "s0"; } } -start diff --git a/bin/varnishtest/tests/c00046.vtc b/bin/varnishtest/tests/c00046.vtc index 0719df3..17fb33b 100644 --- a/bin/varnishtest/tests/c00046.vtc +++ b/bin/varnishtest/tests/c00046.vtc @@ -10,7 +10,7 @@ server s1 { } -start varnish v1 -storage "-smalloc,1m -smalloc,1m, -smalloc,1m" -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.storage = "s0"; } } -start diff --git a/bin/varnishtest/tests/c00047.vtc b/bin/varnishtest/tests/c00047.vtc index 4b23194..d9e4ee2 100644 --- a/bin/varnishtest/tests/c00047.vtc +++ b/bin/varnishtest/tests/c00047.vtc @@ -8,7 +8,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.http.baz1 = regsuball(beresp.http.foo, "barb", "zz"); set beresp.http.baz2 = regsuball(beresp.http.foo, "ar", "zz"); set beresp.http.baz3 = regsuball(beresp.http.foo, "^", "baz"); diff --git a/bin/varnishtest/tests/c00055.vtc b/bin/varnishtest/tests/c00055.vtc index fb9a575..15590d3 100644 --- a/bin/varnishtest/tests/c00055.vtc +++ b/bin/varnishtest/tests/c00055.vtc @@ -15,7 +15,7 @@ varnish v1 -vcl+backend { C{ VRT_CacheReqBody(req, 1000); }C return (pass); } - sub vcl_fetch { + sub vcl_response { if (beresp.http.foo == "BAR") { return (restart); } diff --git a/bin/varnishtest/tests/e00000.vtc b/bin/varnishtest/tests/e00000.vtc index 1cc41fc..2de8f23 100644 --- a/bin/varnishtest/tests/e00000.vtc +++ b/bin/varnishtest/tests/e00000.vtc @@ -9,7 +9,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.do_esi = true; } } -start diff --git a/bin/varnishtest/tests/e00001.vtc b/bin/varnishtest/tests/e00001.vtc index 9b6d1de..13312d3 100644 --- a/bin/varnishtest/tests/e00001.vtc +++ b/bin/varnishtest/tests/e00001.vtc @@ -14,7 +14,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.do_esi = true; } } -start -cliok "param.set esi_syntax 4" diff --git a/bin/varnishtest/tests/e00002.vtc b/bin/varnishtest/tests/e00002.vtc index 3f755d1..8aa223f 100644 --- a/bin/varnishtest/tests/e00002.vtc +++ b/bin/varnishtest/tests/e00002.vtc @@ -13,7 +13,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.do_esi = true; } } -start diff --git a/bin/varnishtest/tests/e00003.vtc b/bin/varnishtest/tests/e00003.vtc index 805219f..6a8ea92 100644 --- a/bin/varnishtest/tests/e00003.vtc +++ b/bin/varnishtest/tests/e00003.vtc @@ -22,7 +22,7 @@ varnish v1 -vcl+backend { set req.url = req.url + req.esi_level; } } - sub vcl_fetch { + sub vcl_response { set beresp.do_esi = true; } } -start diff --git a/bin/varnishtest/tests/e00004.vtc b/bin/varnishtest/tests/e00004.vtc index 1643e14..9a95dac 100644 --- a/bin/varnishtest/tests/e00004.vtc +++ b/bin/varnishtest/tests/e00004.vtc @@ -17,7 +17,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.do_esi = true; } } -start diff --git a/bin/varnishtest/tests/e00005.vtc b/bin/varnishtest/tests/e00005.vtc index a47837d..7f5c333 100644 --- a/bin/varnishtest/tests/e00005.vtc +++ b/bin/varnishtest/tests/e00005.vtc @@ -18,7 +18,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.do_esi = true; } } -start diff --git a/bin/varnishtest/tests/e00006.vtc b/bin/varnishtest/tests/e00006.vtc index 804ee5a..3b9c6db 100644 --- a/bin/varnishtest/tests/e00006.vtc +++ b/bin/varnishtest/tests/e00006.vtc @@ -29,7 +29,7 @@ varnish v1 -vcl+backend { set req.backend = s1; } } - sub vcl_fetch { + sub vcl_response { set beresp.do_esi = true; } } -start diff --git a/bin/varnishtest/tests/e00007.vtc b/bin/varnishtest/tests/e00007.vtc index 2418f81..225ec3c 100644 --- a/bin/varnishtest/tests/e00007.vtc +++ b/bin/varnishtest/tests/e00007.vtc @@ -32,7 +32,7 @@ server s1 { } -start varnish v1 -storage "-smalloc,2m" -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.do_esi = true; } } -start diff --git a/bin/varnishtest/tests/e00008.vtc b/bin/varnishtest/tests/e00008.vtc index 15b915a..4af581f 100644 --- a/bin/varnishtest/tests/e00008.vtc +++ b/bin/varnishtest/tests/e00008.vtc @@ -56,7 +56,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.do_esi = true; } } -start diff --git a/bin/varnishtest/tests/e00009.vtc b/bin/varnishtest/tests/e00009.vtc index f3754ff..099d1b9 100644 --- a/bin/varnishtest/tests/e00009.vtc +++ b/bin/varnishtest/tests/e00009.vtc @@ -18,7 +18,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.do_esi = true; } } -start diff --git a/bin/varnishtest/tests/e00010.vtc b/bin/varnishtest/tests/e00010.vtc index 2cc0d78..1a0b33d 100644 --- a/bin/varnishtest/tests/e00010.vtc +++ b/bin/varnishtest/tests/e00010.vtc @@ -12,7 +12,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.do_esi = true; } } -start -cli "param.set esi_syntax 2" diff --git a/bin/varnishtest/tests/e00011.vtc b/bin/varnishtest/tests/e00011.vtc index 062b13a..8d129b8 100644 --- a/bin/varnishtest/tests/e00011.vtc +++ b/bin/varnishtest/tests/e00011.vtc @@ -16,7 +16,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.do_pass = true; set beresp.do_esi = true; } diff --git a/bin/varnishtest/tests/e00012.vtc b/bin/varnishtest/tests/e00012.vtc index 97672f1..60cc4d1 100644 --- a/bin/varnishtest/tests/e00012.vtc +++ b/bin/varnishtest/tests/e00012.vtc @@ -17,7 +17,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.do_esi = true; } } -start diff --git a/bin/varnishtest/tests/e00013.vtc b/bin/varnishtest/tests/e00013.vtc index 700914c..b659e53 100644 --- a/bin/varnishtest/tests/e00013.vtc +++ b/bin/varnishtest/tests/e00013.vtc @@ -8,7 +8,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.do_esi = true; } } -start diff --git a/bin/varnishtest/tests/e00014.vtc b/bin/varnishtest/tests/e00014.vtc index e366f1f..d174650 100644 --- a/bin/varnishtest/tests/e00014.vtc +++ b/bin/varnishtest/tests/e00014.vtc @@ -10,7 +10,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.do_esi = true; } } -start diff --git a/bin/varnishtest/tests/e00015.vtc b/bin/varnishtest/tests/e00015.vtc index d658d61..5acf6bc 100644 --- a/bin/varnishtest/tests/e00015.vtc +++ b/bin/varnishtest/tests/e00015.vtc @@ -23,7 +23,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { if(req.url == "/") { set req.esi = false; } diff --git a/bin/varnishtest/tests/e00016.vtc b/bin/varnishtest/tests/e00016.vtc index f9a3901..718c690 100644 --- a/bin/varnishtest/tests/e00016.vtc +++ b/bin/varnishtest/tests/e00016.vtc @@ -27,7 +27,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { set req.esi = true; if(req.url == "/body") { set req.esi = false; diff --git a/bin/varnishtest/tests/e00017.vtc b/bin/varnishtest/tests/e00017.vtc index ac32d5f..0eedd1d 100644 --- a/bin/varnishtest/tests/e00017.vtc +++ b/bin/varnishtest/tests/e00017.vtc @@ -71,7 +71,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.do_esi = true; } } -start diff --git a/bin/varnishtest/tests/e00018.vtc b/bin/varnishtest/tests/e00018.vtc index 305ff0f..6b709db 100644 --- a/bin/varnishtest/tests/e00018.vtc +++ b/bin/varnishtest/tests/e00018.vtc @@ -36,7 +36,7 @@ varnish v1 -vcl+backend { sub vcl_recv { return (pass); } - sub vcl_fetch { + sub vcl_response { set beresp.do_esi = true; } } -start diff --git a/bin/varnishtest/tests/e00019.vtc b/bin/varnishtest/tests/e00019.vtc index 54c756f..a45ed76 100644 --- a/bin/varnishtest/tests/e00019.vtc +++ b/bin/varnishtest/tests/e00019.vtc @@ -29,7 +29,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { if (req.url == "bar") { set beresp.do_esi = true; } diff --git a/bin/varnishtest/tests/e00020.vtc b/bin/varnishtest/tests/e00020.vtc index f9b73a4..5a20356 100644 --- a/bin/varnishtest/tests/e00020.vtc +++ b/bin/varnishtest/tests/e00020.vtc @@ -14,7 +14,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.do_esi = true; set beresp.do_gunzip = true; } diff --git a/bin/varnishtest/tests/e00021.vtc b/bin/varnishtest/tests/e00021.vtc index 03fb530..02bd4e8 100644 --- a/bin/varnishtest/tests/e00021.vtc +++ b/bin/varnishtest/tests/e00021.vtc @@ -17,7 +17,7 @@ varnish v1 -vcl+backend { sub vcl_recv { set req.esi = true; } - sub vcl_fetch { + sub vcl_response { set beresp.do_esi = true; set beresp.do_gzip = true; } diff --git a/bin/varnishtest/tests/e00022.vtc b/bin/varnishtest/tests/e00022.vtc index b4b3572..fc45ed3 100644 --- a/bin/varnishtest/tests/e00022.vtc +++ b/bin/varnishtest/tests/e00022.vtc @@ -18,7 +18,7 @@ varnish v1 -arg "-p thread_pool_stack=262144" -vcl+backend { sub vcl_recv { set req.esi = true; } - sub vcl_fetch { + sub vcl_response { set beresp.do_esi = true; } } -start diff --git a/bin/varnishtest/tests/e00023.vtc b/bin/varnishtest/tests/e00023.vtc index 03d185b..47dec0f 100644 --- a/bin/varnishtest/tests/e00023.vtc +++ b/bin/varnishtest/tests/e00023.vtc @@ -36,7 +36,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.do_esi = true; } } -start diff --git a/bin/varnishtest/tests/e00024.vtc b/bin/varnishtest/tests/e00024.vtc index 87235c5..b99d296 100644 --- a/bin/varnishtest/tests/e00024.vtc +++ b/bin/varnishtest/tests/e00024.vtc @@ -60,7 +60,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { if (req.url == "/") { set beresp.do_esi = true; } diff --git a/bin/varnishtest/tests/e00026.vtc b/bin/varnishtest/tests/e00026.vtc index fa6cf9a..39c3de0 100644 --- a/bin/varnishtest/tests/e00026.vtc +++ b/bin/varnishtest/tests/e00026.vtc @@ -28,7 +28,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { if (req.url != "/foo") { set beresp.do_esi = true; } diff --git a/bin/varnishtest/tests/e00027.vtc b/bin/varnishtest/tests/e00027.vtc index 2ee4339..b977004 100644 --- a/bin/varnishtest/tests/e00027.vtc +++ b/bin/varnishtest/tests/e00027.vtc @@ -8,7 +8,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.do_esi = true; } } -start diff --git a/bin/varnishtest/tests/g00002.vtc b/bin/varnishtest/tests/g00002.vtc index eb10ba0..1ddd9ec 100644 --- a/bin/varnishtest/tests/g00002.vtc +++ b/bin/varnishtest/tests/g00002.vtc @@ -17,7 +17,7 @@ varnish v1 \ -cliok "param.set gzip_memlevel 1" \ -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.do_esi = true; } } -start diff --git a/bin/varnishtest/tests/g00003.vtc b/bin/varnishtest/tests/g00003.vtc index 05edb5d..0721dc4 100644 --- a/bin/varnishtest/tests/g00003.vtc +++ b/bin/varnishtest/tests/g00003.vtc @@ -19,7 +19,7 @@ server s1 { varnish v1 -cliok "param.set http_gzip_support true" -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.do_gunzip = true; if (req.url == "/foobar") { set beresp.do_gzip = true; diff --git a/bin/varnishtest/tests/g00004.vtc b/bin/varnishtest/tests/g00004.vtc index 0a23c01..d70e146 100644 --- a/bin/varnishtest/tests/g00004.vtc +++ b/bin/varnishtest/tests/g00004.vtc @@ -19,7 +19,7 @@ server s1 -repeat 2 { varnish v1 \ -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.do_stream = false; if (req.url == "/gunzip") { diff --git a/bin/varnishtest/tests/m00002.vtc b/bin/varnishtest/tests/m00002.vtc index aadbbd0..414bbdb 100644 --- a/bin/varnishtest/tests/m00002.vtc +++ b/bin/varnishtest/tests/m00002.vtc @@ -11,7 +11,7 @@ server s1 { varnish v1 -vcl+backend { import std from "${topbuild}/lib/libvmod_std/.libs/libvmod_std.so" ; - sub vcl_fetch { + sub vcl_response { set beresp.http.rnd1 = std.random(0,1); set beresp.http.rnd2 = std.random(0,10); set beresp.http.rnd3 = std.random(8,10); diff --git a/bin/varnishtest/tests/m00006.vtc b/bin/varnishtest/tests/m00006.vtc index 123d8fd..72b7e7f 100644 --- a/bin/varnishtest/tests/m00006.vtc +++ b/bin/varnishtest/tests/m00006.vtc @@ -21,7 +21,7 @@ varnish v1 -vcl+backend { sub vcl_miss { std.collect(bereq.http.baz); } - sub vcl_fetch { + sub vcl_response { std.collect(beresp.http.bar); } sub vcl_deliver { diff --git a/bin/varnishtest/tests/p00005.vtc b/bin/varnishtest/tests/p00005.vtc index cb0c4e2..ef2b5a1 100644 --- a/bin/varnishtest/tests/p00005.vtc +++ b/bin/varnishtest/tests/p00005.vtc @@ -11,7 +11,7 @@ varnish v1 \ -storage "-spersistent,${tmpdir}/_.per,10m" \ -arg "-pban_lurker_sleep=0" \ -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.ttl = 3s; } } -start @@ -37,7 +37,7 @@ server s1 -wait { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.ttl = 3s; } } -start diff --git a/bin/varnishtest/tests/p00008.vtc b/bin/varnishtest/tests/p00008.vtc index e2ab62f..395f9c6 100644 --- a/bin/varnishtest/tests/p00008.vtc +++ b/bin/varnishtest/tests/p00008.vtc @@ -18,7 +18,7 @@ varnish v1 \ -arg "-pban_lurker_sleep=0" \ -storage "-sper1=persistent,${tmpdir}/_.per1,10m -sper2=persistent,${tmpdir}/_.per2,10m" \ -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.storage = "per1"; if (req.url ~ "silo2") { set beresp.storage = "per2"; diff --git a/bin/varnishtest/tests/r00251.vtc b/bin/varnishtest/tests/r00251.vtc index e93eb00..6794c24 100644 --- a/bin/varnishtest/tests/r00251.vtc +++ b/bin/varnishtest/tests/r00251.vtc @@ -9,7 +9,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.http.Snafu1 = "zoom" + regsub(beresp.http.Foomble, "ar", "\0\0") + diff --git a/bin/varnishtest/tests/r00318.vtc b/bin/varnishtest/tests/r00318.vtc index 4e66fad..bdcdb2f 100644 --- a/bin/varnishtest/tests/r00318.vtc +++ b/bin/varnishtest/tests/r00318.vtc @@ -6,7 +6,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.do_esi = true; set beresp.do_pass = true; } diff --git a/bin/varnishtest/tests/r00326.vtc b/bin/varnishtest/tests/r00326.vtc index 0a7aa04..f37d656 100644 --- a/bin/varnishtest/tests/r00326.vtc +++ b/bin/varnishtest/tests/r00326.vtc @@ -8,7 +8,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.do_esi = true; } } -start diff --git a/bin/varnishtest/tests/r00345.vtc b/bin/varnishtest/tests/r00345.vtc index 6ebbc99..6cdfe1d 100644 --- a/bin/varnishtest/tests/r00345.vtc +++ b/bin/varnishtest/tests/r00345.vtc @@ -10,7 +10,7 @@ server s1 { } -start varnish v1 -arg "-p debug=+workspace" -vcl+backend { - sub vcl_fetch { + sub vcl_response { if (req.url == "/") { set beresp.do_esi = true; } diff --git a/bin/varnishtest/tests/r00386.vtc b/bin/varnishtest/tests/r00386.vtc index c2fcc53..21d944a 100644 --- a/bin/varnishtest/tests/r00386.vtc +++ b/bin/varnishtest/tests/r00386.vtc @@ -10,7 +10,7 @@ server s1 { } -start varnish v1 -arg "-p debug=+workspace" -vcl+backend { - sub vcl_fetch { + sub vcl_response { if (req.url == "/") { set beresp.do_esi = true; } diff --git a/bin/varnishtest/tests/r00387.vtc b/bin/varnishtest/tests/r00387.vtc index d4a32f9..eb6a366 100644 --- a/bin/varnishtest/tests/r00387.vtc +++ b/bin/varnishtest/tests/r00387.vtc @@ -12,7 +12,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.do_stream = false; } } -start diff --git a/bin/varnishtest/tests/r00411.vtc b/bin/varnishtest/tests/r00411.vtc index 5677fc3..67479d3 100644 --- a/bin/varnishtest/tests/r00411.vtc +++ b/bin/varnishtest/tests/r00411.vtc @@ -17,7 +17,7 @@ varnish v1 -vcl+backend { return (restart); } } - sub vcl_fetch { + sub vcl_response { if (beresp.status == 303) { set beresp.ttl = 3m; set beresp.http.X-Magic-Redirect = "1"; diff --git a/bin/varnishtest/tests/r00412.vtc b/bin/varnishtest/tests/r00412.vtc index 8e28262..2b0082a 100644 --- a/bin/varnishtest/tests/r00412.vtc +++ b/bin/varnishtest/tests/r00412.vtc @@ -11,7 +11,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { if (beresp.status == 303) { set beresp.ttl = 60 s; set beresp.http.X-Magic-Redirect = "1"; diff --git a/bin/varnishtest/tests/r00427.vtc b/bin/varnishtest/tests/r00427.vtc index 963b7fe..3d8c9ce 100644 --- a/bin/varnishtest/tests/r00427.vtc +++ b/bin/varnishtest/tests/r00427.vtc @@ -24,7 +24,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.do_esi = true; } } -start diff --git a/bin/varnishtest/tests/r00433.vtc b/bin/varnishtest/tests/r00433.vtc index 1bcefa8..d0e6ba8 100644 --- a/bin/varnishtest/tests/r00433.vtc +++ b/bin/varnishtest/tests/r00433.vtc @@ -31,7 +31,7 @@ varnish v1 -vcl+backend { } } - sub vcl_fetch { + sub vcl_response { set beresp.do_esi = true; } } -start diff --git a/bin/varnishtest/tests/r00445.vtc b/bin/varnishtest/tests/r00445.vtc index 9d29258..535107d 100644 --- a/bin/varnishtest/tests/r00445.vtc +++ b/bin/varnishtest/tests/r00445.vtc @@ -10,7 +10,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.do_esi = true; } } -start diff --git a/bin/varnishtest/tests/r00476.vtc b/bin/varnishtest/tests/r00476.vtc index abf15e6..d9e1c9e 100644 --- a/bin/varnishtest/tests/r00476.vtc +++ b/bin/varnishtest/tests/r00476.vtc @@ -16,7 +16,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.do_esi = true; } } -start diff --git a/bin/varnishtest/tests/r00494.vtc b/bin/varnishtest/tests/r00494.vtc index 1a7fec3..23c5695 100644 --- a/bin/varnishtest/tests/r00494.vtc +++ b/bin/varnishtest/tests/r00494.vtc @@ -9,7 +9,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.http.bar = beresp.http.foo; remove beresp.http.foo; } diff --git a/bin/varnishtest/tests/r00524.vtc b/bin/varnishtest/tests/r00524.vtc index cd43e97..d52e331 100644 --- a/bin/varnishtest/tests/r00524.vtc +++ b/bin/varnishtest/tests/r00524.vtc @@ -18,7 +18,7 @@ varnish v1 -vcl+backend { sub vcl_recv { // return (pass); } - sub vcl_fetch { + sub vcl_response { set beresp.do_esi = true; } } -cliok "param.set timeout_idle 60" -start diff --git a/bin/varnishtest/tests/r00590.vtc b/bin/varnishtest/tests/r00590.vtc index d865fe9..74d77bc 100644 --- a/bin/varnishtest/tests/r00590.vtc +++ b/bin/varnishtest/tests/r00590.vtc @@ -60,7 +60,7 @@ varnish v1 -vcl+backend { sub vcl_recv { return (pass); } - sub vcl_fetch { + sub vcl_response { set beresp.do_esi = true; } } -start diff --git a/bin/varnishtest/tests/r00612.vtc b/bin/varnishtest/tests/r00612.vtc index defaeca..189b720 100644 --- a/bin/varnishtest/tests/r00612.vtc +++ b/bin/varnishtest/tests/r00612.vtc @@ -36,7 +36,7 @@ varnish v1 -vcl+backend { sub vcl_recv { return (pass); } - sub vcl_fetch { + sub vcl_response { set beresp.do_esi = true; } } -start diff --git a/bin/varnishtest/tests/r00641.vtc b/bin/varnishtest/tests/r00641.vtc index da54121..94a15b9 100644 --- a/bin/varnishtest/tests/r00641.vtc +++ b/bin/varnishtest/tests/r00641.vtc @@ -15,7 +15,7 @@ varnish v1 -vcl+backend { sub vcl_recv { // return (pass); } - sub vcl_fetch { + sub vcl_response { set beresp.do_esi = true; } } -cliok "param.set timeout_idle 60" -start diff --git a/bin/varnishtest/tests/r00667.vtc b/bin/varnishtest/tests/r00667.vtc index 1555df1..f428e6a 100644 --- a/bin/varnishtest/tests/r00667.vtc +++ b/bin/varnishtest/tests/r00667.vtc @@ -16,7 +16,7 @@ server s1 { varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.ttl = 0s; } } -start diff --git a/bin/varnishtest/tests/r00702.vtc b/bin/varnishtest/tests/r00702.vtc index 5075c16..9ac03cf 100644 --- a/bin/varnishtest/tests/r00702.vtc +++ b/bin/varnishtest/tests/r00702.vtc @@ -6,7 +6,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.do_stream = false; } } -start diff --git a/bin/varnishtest/tests/r00704.vtc b/bin/varnishtest/tests/r00704.vtc index 806fc82..5d0585c 100644 --- a/bin/varnishtest/tests/r00704.vtc +++ b/bin/varnishtest/tests/r00704.vtc @@ -6,7 +6,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.do_stream = false; } } -start diff --git a/bin/varnishtest/tests/r00769.vtc b/bin/varnishtest/tests/r00769.vtc index b464914..1f75ad9 100644 --- a/bin/varnishtest/tests/r00769.vtc +++ b/bin/varnishtest/tests/r00769.vtc @@ -11,7 +11,7 @@ varnish v1 -vcl+backend { error 700; } } - sub vcl_fetch { + sub vcl_response { set beresp.status = 404; set beresp.http.X-status = beresp.status; return (deliver); diff --git a/bin/varnishtest/tests/r00801.vtc b/bin/varnishtest/tests/r00801.vtc index 3309f22..d7b293f 100644 --- a/bin/varnishtest/tests/r00801.vtc +++ b/bin/varnishtest/tests/r00801.vtc @@ -11,7 +11,7 @@ server s1 { varnish v1 -vcl+backend { sub vcl_recv { return (pass); } - sub vcl_fetch { + sub vcl_response { set beresp.do_stream = false; } } -start diff --git a/bin/varnishtest/tests/r00861.vtc b/bin/varnishtest/tests/r00861.vtc index 8a3e8a0..cfdaca0 100644 --- a/bin/varnishtest/tests/r00861.vtc +++ b/bin/varnishtest/tests/r00861.vtc @@ -23,7 +23,7 @@ server s1 { varnish v1 \ -vcl+backend { - sub vcl_fetch { + sub vcl_response { if (req.url == "/1" || req.url == "/2") { set beresp.do_esi = true; set beresp.do_gzip = true; diff --git a/bin/varnishtest/tests/r00873.vtc b/bin/varnishtest/tests/r00873.vtc index 56afc19..00e1413 100644 --- a/bin/varnishtest/tests/r00873.vtc +++ b/bin/varnishtest/tests/r00873.vtc @@ -9,7 +9,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.do_esi = true; set beresp.do_gzip = true; } diff --git a/bin/varnishtest/tests/r00894.vtc b/bin/varnishtest/tests/r00894.vtc index d3b9856..23f0cb4 100644 --- a/bin/varnishtest/tests/r00894.vtc +++ b/bin/varnishtest/tests/r00894.vtc @@ -6,7 +6,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.do_esi = true; } } -start diff --git a/bin/varnishtest/tests/r00913.vtc b/bin/varnishtest/tests/r00913.vtc index e310360..6d5a54c 100644 --- a/bin/varnishtest/tests/r00913.vtc +++ b/bin/varnishtest/tests/r00913.vtc @@ -7,7 +7,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { if (beresp.http.bar ~ "$") { set beresp.http.foo = regsub(beresp.http.bar, "$", "XXX"); } diff --git a/bin/varnishtest/tests/r00915.vtc b/bin/varnishtest/tests/r00915.vtc index 266c6b7..1c0c21c 100644 --- a/bin/varnishtest/tests/r00915.vtc +++ b/bin/varnishtest/tests/r00915.vtc @@ -12,7 +12,7 @@ varnish v1 \ -storage "-spersistent,${tmpdir}/_.per,10m" \ -vcl+backend { - sub vcl_fetch { + sub vcl_response { error(751); } } -start diff --git a/bin/varnishtest/tests/r00916.vtc b/bin/varnishtest/tests/r00916.vtc index 27f3f1a..51339b4 100644 --- a/bin/varnishtest/tests/r00916.vtc +++ b/bin/varnishtest/tests/r00916.vtc @@ -9,7 +9,7 @@ varnish v1 -errvcl {Symbol not found: 's-1' (expected type BACKEND)} { backend b { .host = "127.0.0.1"; } sub s1 { } - sub vcl_fetch { + sub vcl_response { if (req.backend == s-1){ set req.backend = s-1; } diff --git a/bin/varnishtest/tests/r00941.vtc b/bin/varnishtest/tests/r00941.vtc index 1028e2d..f6ee1a6 100644 --- a/bin/varnishtest/tests/r00941.vtc +++ b/bin/varnishtest/tests/r00941.vtc @@ -8,7 +8,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.ttl = 1000s; } } -start diff --git a/bin/varnishtest/tests/r00942.vtc b/bin/varnishtest/tests/r00942.vtc index 1506709..ffde262 100644 --- a/bin/varnishtest/tests/r00942.vtc +++ b/bin/varnishtest/tests/r00942.vtc @@ -26,7 +26,7 @@ server s1 { varnish v1 \ -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.do_stream = false; } } diff --git a/bin/varnishtest/tests/r00956.vtc b/bin/varnishtest/tests/r00956.vtc index c98996d..a41c25a 100644 --- a/bin/varnishtest/tests/r00956.vtc +++ b/bin/varnishtest/tests/r00956.vtc @@ -6,7 +6,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.ttl = 10s; set req.http.foo = beresp.ttl; set req.http.bar = "xxx"; diff --git a/bin/varnishtest/tests/r00961.vtc b/bin/varnishtest/tests/r00961.vtc index b162379..7f7c4f7 100644 --- a/bin/varnishtest/tests/r00961.vtc +++ b/bin/varnishtest/tests/r00961.vtc @@ -36,7 +36,7 @@ varnish v1 -vcl+backend { sub vcl_recv { return (pass); } - sub vcl_fetch { + sub vcl_response { set beresp.do_esi = true; } } -start diff --git a/bin/varnishtest/tests/r00962.vtc b/bin/varnishtest/tests/r00962.vtc index 4331cd0..77ea57e 100644 --- a/bin/varnishtest/tests/r00962.vtc +++ b/bin/varnishtest/tests/r00962.vtc @@ -14,7 +14,7 @@ varnish v1 \ -arg "-pfeature=+wait_silo" \ -storage "-spersistent,${tmpdir}/_.per1,10m -spersistent,${tmpdir}/_.per2,10m" \ -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.storage = "s0"; } } -start diff --git a/bin/varnishtest/tests/r00972.vtc b/bin/varnishtest/tests/r00972.vtc index ed3a916..f6d071c 100644 --- a/bin/varnishtest/tests/r00972.vtc +++ b/bin/varnishtest/tests/r00972.vtc @@ -6,7 +6,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.do_stream = true; } } -start diff --git a/bin/varnishtest/tests/r01029.vtc b/bin/varnishtest/tests/r01029.vtc index 2817bba..8e3064c 100644 --- a/bin/varnishtest/tests/r01029.vtc +++ b/bin/varnishtest/tests/r01029.vtc @@ -12,7 +12,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.do_esi = true; if (req.url == "/foo") { set beresp.ttl = 0s; diff --git a/bin/varnishtest/tests/r01030.vtc b/bin/varnishtest/tests/r01030.vtc index 830e465..db58d32 100644 --- a/bin/varnishtest/tests/r01030.vtc +++ b/bin/varnishtest/tests/r01030.vtc @@ -20,7 +20,7 @@ varnish v1 -vcl+backend { } return (lookup); } - sub vcl_fetch { + sub vcl_response { set beresp.http.url = req.url; } } -start diff --git a/bin/varnishtest/tests/r01036.vtc b/bin/varnishtest/tests/r01036.vtc index 1c77919..dfd4402 100644 --- a/bin/varnishtest/tests/r01036.vtc +++ b/bin/varnishtest/tests/r01036.vtc @@ -8,7 +8,7 @@ server s1 { } -start varnish v1 -arg "-smalloc,1M" -arg "-pgzip_level=0" -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.do_stream = false; set beresp.do_gzip = true; } diff --git a/bin/varnishtest/tests/r01037.vtc b/bin/varnishtest/tests/r01037.vtc index acb77d3..46ec9d4 100644 --- a/bin/varnishtest/tests/r01037.vtc +++ b/bin/varnishtest/tests/r01037.vtc @@ -15,7 +15,7 @@ server s1 { } -start varnish v1 -arg "-smalloc,1M" -arg "-pgzip_level=0" -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.do_esi = true; set beresp.do_gzip = true; } diff --git a/bin/varnishtest/tests/r01038.vtc b/bin/varnishtest/tests/r01038.vtc index e10152f..d7d438c 100644 --- a/bin/varnishtest/tests/r01038.vtc +++ b/bin/varnishtest/tests/r01038.vtc @@ -46,7 +46,7 @@ server s1 { } -start varnish v1 -arg "-p workspace_backend=8k" -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.do_esi = true; } } -start diff --git a/bin/varnishtest/tests/r01091.vtc b/bin/varnishtest/tests/r01091.vtc index ae94ca8..2b1fff3 100644 --- a/bin/varnishtest/tests/r01091.vtc +++ b/bin/varnishtest/tests/r01091.vtc @@ -25,7 +25,7 @@ varnish v1 -vcl+backend { sub vcl_recv { set req.backend = f1.backend(); } - sub vcl_fetch { + sub vcl_response { if(req.restarts < 1) { set beresp.saintmode = 1h; return(restart); diff --git a/bin/varnishtest/tests/r01092.vtc b/bin/varnishtest/tests/r01092.vtc index 26b0b9c..4311b73 100644 --- a/bin/varnishtest/tests/r01092.vtc +++ b/bin/varnishtest/tests/r01092.vtc @@ -19,7 +19,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.do_esi = true; } } -start -cliok "param.set esi_syntax 4" diff --git a/bin/varnishtest/tests/r01109.vtc b/bin/varnishtest/tests/r01109.vtc index e6b43e8..479786c 100644 --- a/bin/varnishtest/tests/r01109.vtc +++ b/bin/varnishtest/tests/r01109.vtc @@ -22,7 +22,7 @@ server s1 { } -start varnish v1 -arg "-pfetch_chunksize=4k" -arg "-pgzip_level=0" -arg "-pthread_pool_stack=131072" -vcl+backend { - sub vcl_fetch { + sub vcl_response { if (req.url ~ "/test") { set beresp.do_esi = true; } diff --git a/bin/varnishtest/tests/r01113.vtc b/bin/varnishtest/tests/r01113.vtc index abcee83..23ef6e0 100644 --- a/bin/varnishtest/tests/r01113.vtc +++ b/bin/varnishtest/tests/r01113.vtc @@ -20,7 +20,7 @@ varnish v1 -vcl+backend { return(restart); } } - sub vcl_fetch { + sub vcl_response { if (req.url == "/fetch") { return(restart); } diff --git a/bin/varnishtest/tests/r01123.vtc b/bin/varnishtest/tests/r01123.vtc index 37a9254..6881d60 100644 --- a/bin/varnishtest/tests/r01123.vtc +++ b/bin/varnishtest/tests/r01123.vtc @@ -9,7 +9,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { if (req.url == "/") { set beresp.do_esi = true; } diff --git a/bin/varnishtest/tests/r01157.vtc b/bin/varnishtest/tests/r01157.vtc index 9cecd9a..ae30994 100644 --- a/bin/varnishtest/tests/r01157.vtc +++ b/bin/varnishtest/tests/r01157.vtc @@ -12,7 +12,7 @@ server s1 { varnish v1 -vcl+backend { sub vcl_recv { return (pass); } - sub vcl_fetch { set beresp.do_stream = true; } + sub vcl_response { set beresp.do_stream = true; } } -start client c1 { diff --git a/bin/varnishtest/tests/r01168.vtc b/bin/varnishtest/tests/r01168.vtc index fb0a0c5..52a8827 100644 --- a/bin/varnishtest/tests/r01168.vtc +++ b/bin/varnishtest/tests/r01168.vtc @@ -14,7 +14,7 @@ varnish v1 -vcl+backend { sub vcl_recv { rollback; } - sub vcl_fetch { + sub vcl_response { set beresp.do_esi = true; } } -start diff --git a/bin/varnishtest/tests/r01175.vtc b/bin/varnishtest/tests/r01175.vtc index 67e1354..f5c1c8e 100644 --- a/bin/varnishtest/tests/r01175.vtc +++ b/bin/varnishtest/tests/r01175.vtc @@ -6,7 +6,7 @@ server s1 { } -start varnish v1 -storage "-s test=malloc,1M" -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.storage = "test"; } } -start diff --git a/bin/varnishtest/tests/r01184.vtc b/bin/varnishtest/tests/r01184.vtc index 046b371..5c9de55 100644 --- a/bin/varnishtest/tests/r01184.vtc +++ b/bin/varnishtest/tests/r01184.vtc @@ -32,7 +32,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.do_esi = true; } } -start @@ -64,7 +64,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.do_esi = true; } } @@ -95,7 +95,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.do_esi = true; set beresp.do_gunzip = true; } diff --git a/bin/varnishtest/tests/r01206.vtc b/bin/varnishtest/tests/r01206.vtc index dc403ed..2dc3b6e 100644 --- a/bin/varnishtest/tests/r01206.vtc +++ b/bin/varnishtest/tests/r01206.vtc @@ -39,7 +39,7 @@ client c1 { server s1 -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.do_pass = true; } } diff --git a/bin/varnishtest/tests/r01253.vtc b/bin/varnishtest/tests/r01253.vtc index c1d88ff..869f0a6 100644 --- a/bin/varnishtest/tests/r01253.vtc +++ b/bin/varnishtest/tests/r01253.vtc @@ -1,4 +1,4 @@ -varnishtest "restarting a pass in vcl_fetch should not panic" +varnishtest "restarting a pass in vcl_response should not panic" server s1 { rxreq @@ -12,7 +12,7 @@ varnish v1 -vcl+backend { sub vcl_recv { return (pass); } - sub vcl_fetch { + sub vcl_response { if (beresp.status != 200) { return (restart); } diff --git a/bin/varnishtest/tests/r01283.vtc b/bin/varnishtest/tests/r01283.vtc index 9283209..9d5bd81 100644 --- a/bin/varnishtest/tests/r01283.vtc +++ b/bin/varnishtest/tests/r01283.vtc @@ -11,7 +11,7 @@ varnish v1 -arg "-p nuke_limit=0" -storage "-sTransient=malloc,1m" -vcl+backend error 500; } } - sub vcl_fetch { + sub vcl_response { set beresp.storage = "Transient"; } } -start diff --git a/bin/varnishtest/tests/r01284.vtc b/bin/varnishtest/tests/r01284.vtc index 33a2a08..485a05d 100644 --- a/bin/varnishtest/tests/r01284.vtc +++ b/bin/varnishtest/tests/r01284.vtc @@ -10,7 +10,7 @@ server s1 { } -start varnish v1 -arg "-p nuke_limit=0" -storage "-sTransient=malloc,1m" -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.storage = "Transient"; } } -start diff --git a/bin/varnishtest/tests/s00002.vtc b/bin/varnishtest/tests/s00002.vtc index ab3736e..4759635 100644 --- a/bin/varnishtest/tests/s00002.vtc +++ b/bin/varnishtest/tests/s00002.vtc @@ -47,7 +47,7 @@ varnish v1 -vcl { .initial = 0; } } - sub vcl_fetch { + sub vcl_response { set beresp.ttl = 1s; set beresp.grace = 1m; } diff --git a/bin/varnishtest/tests/s00003.vtc b/bin/varnishtest/tests/s00003.vtc index b7476d7..09f8572 100644 --- a/bin/varnishtest/tests/s00003.vtc +++ b/bin/varnishtest/tests/s00003.vtc @@ -16,7 +16,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.ttl = 1s; set beresp.grace = 10m; if (beresp.http.foo == "2") diff --git a/bin/varnishtest/tests/v00000.vtc b/bin/varnishtest/tests/v00000.vtc index 697dc53..a9a02b1 100644 --- a/bin/varnishtest/tests/v00000.vtc +++ b/bin/varnishtest/tests/v00000.vtc @@ -12,7 +12,7 @@ varnish v1 -vcl+backend { sub vcl_recv { set req.grace += 1 s; } - sub vcl_fetch { + sub vcl_response { set beresp.ttl += 1 m; set beresp.grace += 1 h; } diff --git a/bin/varnishtest/tests/v00001.vtc b/bin/varnishtest/tests/v00001.vtc index 922cd15..3b8492c 100644 --- a/bin/varnishtest/tests/v00001.vtc +++ b/bin/varnishtest/tests/v00001.vtc @@ -26,7 +26,7 @@ varnish v1 -vcl+backend { set bereq.proto = "HTTP/1.2"; set bereq.method = "GET"; } - sub vcl_fetch { + sub vcl_response { set beresp.http.foobar = beresp.proto + beresp.response + beresp.status; set beresp.proto = "HTTP/1.2"; diff --git a/bin/varnishtest/tests/v00010.vtc b/bin/varnishtest/tests/v00010.vtc index 19405cc..d08dcc1 100644 --- a/bin/varnishtest/tests/v00010.vtc +++ b/bin/varnishtest/tests/v00010.vtc @@ -25,7 +25,7 @@ varnish v1 -storage "-smalloc,1m" -vcl+backend { import debug from "${topbuild}/lib/libvmod_debug/.libs/libvmod_debug.so"; - sub vcl_fetch { + sub vcl_response { if (beresp.http.panic == "fetch") { debug.panic("Had Panic header: " + beresp.http.panic); } diff --git a/bin/varnishtest/tests/v00016.vtc b/bin/varnishtest/tests/v00016.vtc index 5b17ed6..50f82d2 100644 --- a/bin/varnishtest/tests/v00016.vtc +++ b/bin/varnishtest/tests/v00016.vtc @@ -60,7 +60,7 @@ varnish v1 -vcl { backend b { .host = "127.0.0.1"; } /* test time and backend comparison */ - sub vcl_fetch { + sub vcl_response { if (beresp.ttl > 1d) { set beresp.ttl = 1d; } @@ -75,12 +75,12 @@ varnish v1 -vcl { varnish v1 -errvcl {Unknown time unit 'k'. Legal are 's', 'm', 'h' and 'd'} { backend b { .host = "127.0.0.1"; } - sub vcl_fetch { set obj.ttl = 1. k; } + sub vcl_response { set obj.ttl = 1. k; } } varnish v1 -errvcl {Expression has type DURATION, expected BOOL} { backend b { .host = "127.0.0.1"; } - sub vcl_fetch { if (obj.ttl *= 2) { } } + sub vcl_response { if (obj.ttl *= 2) { } } } varnish v1 -errvcl {Operator > not possible on BACKEND} { diff --git a/bin/varnishtest/tests/v00018.vtc b/bin/varnishtest/tests/v00018.vtc index 7bc0b05..39d6eec 100644 --- a/bin/varnishtest/tests/v00018.vtc +++ b/bin/varnishtest/tests/v00018.vtc @@ -8,14 +8,14 @@ varnish v1 -vcl { varnish v1 -vcl { backend b { .host = "127.0.0.1"; } - sub vcl_fetch { error beresp.status ; } + sub vcl_response { error beresp.status ; } } varnish v1 -vcl { backend b { .host = "127.0.0.1"; } sub vcl_miss { error 100 req.url ; } sub vcl_pass { error 100 "the butter please" ; } - sub vcl_fetch { error beresp.status req.url; } + sub vcl_response { error beresp.status req.url; } } varnish v1 -errvcl {Variable 'server.port' is read only.} { @@ -25,12 +25,12 @@ varnish v1 -errvcl {Variable 'server.port' is read only.} { varnish v1 -vcl { backend b { .host = "127.0.0.1"; } - sub vcl_fetch { set beresp.ttl /= 2; } + sub vcl_response { set beresp.ttl /= 2; } } varnish v1 -errvcl {Expected '=' got '>>'} { backend b { .host = "127.0.0.1"; } - sub vcl_fetch { set beresp.ttl >>= 2; } + sub vcl_response { set beresp.ttl >>= 2; } } varnish v1 -errvcl {Expected '=' got '+='} { @@ -61,27 +61,27 @@ varnish v1 -vcl { varnish v1 -errvcl {Expected '=' got '+='} { backend b { .host = "127.0.0.1"; } - sub vcl_fetch { set beresp.do_gzip += 1; } + sub vcl_response { set beresp.do_gzip += 1; } } varnish v1 -vcl { backend b { .host = "127.0.0.1"; } - sub vcl_fetch { set beresp.do_gzip = true; } + sub vcl_response { set beresp.do_gzip = true; } } varnish v1 -vcl { backend b { .host = "127.0.0.1"; } - sub vcl_fetch { set beresp.do_gzip = false; } + sub vcl_response { set beresp.do_gzip = false; } } varnish v1 -errvcl {Symbol not found: 'mu' (expected type BOOL):} { backend b { .host = "127.0.0.1"; } - sub vcl_fetch { set beresp.do_gzip = mu; } + sub vcl_response { set beresp.do_gzip = mu; } } varnish v1 -errvcl {Only http header variables can be unset.} { backend b { .host = "127.0.0.1"; } - sub vcl_fetch { unset beresp.do_gzip; } + sub vcl_response { unset beresp.do_gzip; } } varnish v1 -errvcl {Unknown token '<<' when looking for STRING} { diff --git a/bin/varnishtest/tests/v00020.vtc b/bin/varnishtest/tests/v00020.vtc index bcdebac..87227d3 100644 --- a/bin/varnishtest/tests/v00020.vtc +++ b/bin/varnishtest/tests/v00020.vtc @@ -24,7 +24,7 @@ varnish v1 -errvcl {Expected an action, 'if', } " sub vcl_recv { { } { " varnish v1 -vcl { backend b { .host = "127.0.0.1"; } - sub vcl_fetch { + sub vcl_response { set beresp.ttl = 1w; set beresp.ttl *= 1.5; set beresp.ttl = 1.5 s * 2.5; @@ -73,20 +73,20 @@ varnish v1 -errvcl {Operator * not possible on type STRING.} { } varnish v1 -errvcl {DURATION + INT not possible.} { - sub vcl_fetch { + sub vcl_response { set req.http.foo = req.grace + beresp.status; } } varnish v1 -errvcl {'!' must be followed by BOOL, found DURATION.} { - sub vcl_fetch { + sub vcl_response { if (! req.grace) { } } } varnish v1 -errvcl {Operator + not possible on type BOOL.} { - sub vcl_fetch { + sub vcl_response { if (beresp.do_gzip + beresp.do_gunzip) { } } @@ -226,7 +226,7 @@ varnish v1 -errvcl {DURATION + STRING not possible.} { varnish v1 -errvcl {'||' must be followed by BOOL, found DURATION.} { backend b { .host = "127.0.0.1"; } - sub vcl_fetch { + sub vcl_response { if (req.url || beresp.ttl) { } } @@ -234,7 +234,7 @@ varnish v1 -errvcl {'||' must be followed by BOOL, found DURATION.} { varnish v1 -errvcl {'&&' must be followed by BOOL, found DURATION.} { backend b { .host = "127.0.0.1"; } - sub vcl_fetch { + sub vcl_response { if (req.url && beresp.ttl) { } } @@ -242,7 +242,7 @@ varnish v1 -errvcl {'&&' must be followed by BOOL, found DURATION.} { varnish v1 -vcl { backend b { .host = "127.0.0.1"; } - sub vcl_fetch { + sub vcl_response { if (!req.url) { } } diff --git a/bin/varnishtest/tests/v00025.vtc b/bin/varnishtest/tests/v00025.vtc index aab2c83..ab77fdf 100644 --- a/bin/varnishtest/tests/v00025.vtc +++ b/bin/varnishtest/tests/v00025.vtc @@ -16,7 +16,7 @@ sub vcl_deliver { set resp.http.server_port = server.port; } -sub vcl_fetch { +sub vcl_response { if (req.esi) { set beresp.http.esi = "yes"; } diff --git a/bin/varnishtest/tests/v00032.vtc b/bin/varnishtest/tests/v00032.vtc index 8bf4c69..f18adaa 100644 --- a/bin/varnishtest/tests/v00032.vtc +++ b/bin/varnishtest/tests/v00032.vtc @@ -6,7 +6,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.http.has_s0 = storage.s0; set beresp.http.has_foo = storage.foo; set beresp.http.has_Transient = storage.Transient; diff --git a/bin/varnishtest/tests/v00033.vtc b/bin/varnishtest/tests/v00033.vtc index ceb5c12..504ad5a 100644 --- a/bin/varnishtest/tests/v00033.vtc +++ b/bin/varnishtest/tests/v00033.vtc @@ -10,7 +10,7 @@ server s1 { varnish v1 -vcl+backend { - sub vcl_fetch { + sub vcl_response { set beresp.http.foo = storage.nowhere.free_space + 1 B + 1 KB + 1 MB + 1GB + 1TB; diff --git a/etc/zope-plone.vcl b/etc/zope-plone.vcl index 3127f18..de599dd 100644 --- a/etc/zope-plone.vcl +++ b/etc/zope-plone.vcl @@ -90,7 +90,7 @@ sub vcl_miss { # Enforce a minimum TTL, since we can PURGE changed objects actively # from Zope by using the CacheFu product -sub vcl_fetch { +sub vcl_response { if (beresp.ttl < 3600s) { set beresp.ttl = 3600s; } diff --git a/lib/libvcl/generate.py b/lib/libvcl/generate.py index a12f296..51dc8b6 100755 --- a/lib/libvcl/generate.py +++ b/lib/libvcl/generate.py @@ -84,7 +84,7 @@ returns =( ('hash', ('hash',)), ('miss', ('error', 'restart', 'pass', 'fetch',)), ('hit', ('error', 'restart', 'pass', 'deliver',)), - ('fetch', ('error', 'restart', 'deliver',)), + ('response', ('error', 'restart', 'deliver',)), ('deliver', ('restart', 'deliver',)), ('error', ('restart', 'deliver',)), ('init', ('ok',)), @@ -208,8 +208,8 @@ sp_variables = ( ), ('req.esi', 'BOOL', - ( 'recv', 'fetch', 'deliver', 'error',), - ( 'recv', 'fetch', 'deliver', 'error',), + ( 'recv', 'response', 'deliver', 'error',), + ( 'recv', 'response', 'deliver', 'error',), 'struct req *' ), ('req.can_gzip', @@ -238,32 +238,32 @@ sp_variables = ( ), ('bereq.method', 'STRING', - ( 'pipe', 'pass', 'miss', 'fetch',), - ( 'pipe', 'pass', 'miss', 'fetch',), + ( 'pipe', 'pass', 'miss', 'response',), + ( 'pipe', 'pass', 'miss', 'response',), 'const struct req *' ), ('bereq.request', 'STRING', - ( 'pipe', 'pass', 'miss', 'fetch',), - ( 'pipe', 'pass', 'miss', 'fetch',), + ( 'pipe', 'pass', 'miss', 'response',), + ( 'pipe', 'pass', 'miss', 'response',), 'const struct req *' ), ('bereq.url', 'STRING', - ( 'pipe', 'pass', 'miss', 'fetch',), - ( 'pipe', 'pass', 'miss', 'fetch',), + ( 'pipe', 'pass', 'miss', 'response',), + ( 'pipe', 'pass', 'miss', 'response',), 'const struct req *' ), ('bereq.proto', 'STRING', - ( 'pipe', 'pass', 'miss', 'fetch',), - ( 'pipe', 'pass', 'miss', 'fetch',), + ( 'pipe', 'pass', 'miss', 'response',), + ( 'pipe', 'pass', 'miss', 'response',), 'const struct req *' ), ('bereq.http.', 'HEADER', - ( 'pipe', 'pass', 'miss', 'fetch',), - ( 'pipe', 'pass', 'miss', 'fetch',), + ( 'pipe', 'pass', 'miss', 'response',), + ( 'pipe', 'pass', 'miss', 'response',), 'const struct req *' ), ('bereq.connect_timeout', @@ -286,104 +286,104 @@ sp_variables = ( ), ('beresp.proto', 'STRING', - ( 'fetch',), - ( 'fetch',), + ( 'response',), + ( 'response',), 'const struct req *' ), ('beresp.saintmode', 'DURATION', ( ), - ( 'fetch',), + ( 'response',), 'const struct req *' ), ('beresp.status', 'INT', - ( 'fetch',), - ( 'fetch',), + ( 'response',), + ( 'response',), 'const struct req *' ), ('beresp.response', 'STRING', - ( 'fetch',), - ( 'fetch',), + ( 'response',), + ( 'response',), 'const struct req *' ), ('beresp.http.', 'HEADER', - ( 'fetch',), - ( 'fetch',), + ( 'response',), + ( 'response',), 'const struct req *' ), ('beresp.do_esi', 'BOOL', - ( 'fetch',), - ( 'fetch',), + ( 'response',), + ( 'response',), 'const struct req *' ), ('beresp.do_stream', 'BOOL', - ( 'fetch',), - ( 'fetch',), + ( 'response',), + ( 'response',), 'const struct req *' ), ('beresp.do_gzip', 'BOOL', - ( 'fetch',), - ( 'fetch',), + ( 'response',), + ( 'response',), 'const struct req *' ), ('beresp.do_gunzip', 'BOOL', - ( 'fetch',), - ( 'fetch',), + ( 'response',), + ( 'response',), 'const struct req *' ), ('beresp.do_pass', 'BOOL', - ( 'fetch',), - ( 'fetch',), + ( 'response',), + ( 'response',), 'const struct req *' ), ('beresp.ttl', 'DURATION', - ( 'fetch',), - ( 'fetch',), + ( 'response',), + ( 'response',), 'struct req *' ), ('beresp.grace', 'DURATION', - ( 'fetch',), - ( 'fetch',), + ( 'response',), + ( 'response',), 'struct req *' ), ('beresp.keep', 'DURATION', - ( 'fetch',), - ( 'fetch',), + ( 'response',), + ( 'response',), 'struct req *' ), ('beresp.backend.name', 'STRING', - ( 'fetch',), + ( 'response',), ( ), 'const struct req *' ), ('beresp.backend.ip', 'IP', - ( 'fetch',), + ( 'response',), ( ), 'const struct req *' ), ('beresp.backend.port', 'INT', - ( 'fetch',), + ( 'response',), ( ), 'const struct req *' ), ('beresp.storage', 'STRING', - ( 'fetch',), - ( 'fetch',), + ( 'response',), + ( 'response',), 'struct req *' ), ('obj.proto', diff --git a/lib/libvcl/vcc_action.c b/lib/libvcl/vcc_action.c index 7d5ea2e..de899cb 100644 --- a/lib/libvcl/vcc_action.c +++ b/lib/libvcl/vcc_action.c @@ -372,7 +372,7 @@ static struct action_table { } action_table[] = { { "error", parse_error, VCL_MET_RECV | VCL_MET_PIPE | VCL_MET_PASS | VCL_MET_HASH | - VCL_MET_MISS | VCL_MET_HIT | VCL_MET_FETCH + VCL_MET_MISS | VCL_MET_HIT | VCL_MET_RESPONSE }, #define VCL_RET_MAC(l, U, B) \ From phk at varnish-cache.org Wed Mar 20 13:01:53 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Wed, 20 Mar 2013 14:01:53 +0100 Subject: [master] 7fdeea4 Add new vcl_fetch{} and call it before vcl_miss{} and vcl_pass{} as an interrim measure. Message-ID: commit 7fdeea4ca8358a24ca9ec1f11cd2d8d2e1f695d7 Author: Poul-Henning Kamp Date: Wed Mar 20 13:00:58 2013 +0000 Add new vcl_fetch{} and call it before vcl_miss{} and vcl_pass{} as an interrim measure. Use it in a few test-cases where it relates only to the backend fetch (as opposed to pass/purge/restart) diff --git a/bin/varnishd/cache/cache_req_fsm.c b/bin/varnishd/cache/cache_req_fsm.c index 2c65976..fa9de50 100644 --- a/bin/varnishd/cache/cache_req_fsm.c +++ b/bin/varnishd/cache/cache_req_fsm.c @@ -907,6 +907,7 @@ cnt_miss(struct worker *wrk, struct req *req) http_SetHeader(bo->bereq, "Accept-Encoding: gzip"); } + VCL_fetch_method(req); VCL_miss_method(req); if (req->handling == VCL_RET_FETCH) { @@ -971,6 +972,7 @@ cnt_pass(struct worker *wrk, struct req *req) HTTP_Setup(bo->bereq, bo->ws, bo->vsl, HTTP_Bereq); http_FilterReq(req, HTTPH_R_PASS); + VCL_fetch_method(req); VCL_pass_method(req); if (req->handling == VCL_RET_ERROR) { diff --git a/bin/varnishd/default.vcl b/bin/varnishd/default.vcl index 8b90194..986f276 100644 --- a/bin/varnishd/default.vcl +++ b/bin/varnishd/default.vcl @@ -101,6 +101,10 @@ sub vcl_miss { return (fetch); } +sub vcl_fetch { + return (fetch); +} + sub vcl_response { if (beresp.ttl <= 0s || beresp.http.Set-Cookie || diff --git a/bin/varnishtest/tests/b00021.vtc b/bin/varnishtest/tests/b00021.vtc index eedcca2..331635b 100644 --- a/bin/varnishtest/tests/b00021.vtc +++ b/bin/varnishtest/tests/b00021.vtc @@ -10,7 +10,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_miss { + sub vcl_fetch { set bereq.between_bytes_timeout = 2s; } sub vcl_response { diff --git a/bin/varnishtest/tests/b00024.vtc b/bin/varnishtest/tests/b00024.vtc index bbca487..421ed0d 100644 --- a/bin/varnishtest/tests/b00024.vtc +++ b/bin/varnishtest/tests/b00024.vtc @@ -9,7 +9,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_miss { + sub vcl_fetch { set bereq.first_byte_timeout = 1s; } } -start diff --git a/bin/varnishtest/tests/b00026.vtc b/bin/varnishtest/tests/b00026.vtc index 1cc1998..048c58e 100644 --- a/bin/varnishtest/tests/b00026.vtc +++ b/bin/varnishtest/tests/b00026.vtc @@ -34,7 +34,7 @@ varnish v1 -vcl { } set req.backend = b2; } - sub vcl_miss { + sub vcl_fetch { set bereq.first_byte_timeout = 2s; } } -start diff --git a/bin/varnishtest/tests/m00006.vtc b/bin/varnishtest/tests/m00006.vtc index 72b7e7f..b1a57a8 100644 --- a/bin/varnishtest/tests/m00006.vtc +++ b/bin/varnishtest/tests/m00006.vtc @@ -18,7 +18,7 @@ varnish v1 -vcl+backend { sub vcl_recv { std.collect(req.http.foo); } - sub vcl_miss { + sub vcl_fetch { std.collect(bereq.http.baz); } sub vcl_response { diff --git a/bin/varnishtest/tests/r00781.vtc b/bin/varnishtest/tests/r00781.vtc index 94d0132..52738e5 100644 --- a/bin/varnishtest/tests/r00781.vtc +++ b/bin/varnishtest/tests/r00781.vtc @@ -9,7 +9,7 @@ varnish v1 -vcl+backend { sub vcl_recv { set req.url = req.http.foo; } - sub vcl_miss { + sub vcl_fetch { set bereq.url = req.http.foo; } } -start diff --git a/bin/varnishtest/tests/v00001.vtc b/bin/varnishtest/tests/v00001.vtc index 3b8492c..2f0d47c 100644 --- a/bin/varnishtest/tests/v00001.vtc +++ b/bin/varnishtest/tests/v00001.vtc @@ -18,7 +18,7 @@ varnish v1 -vcl+backend { set req.proto = "HTTP/1.2"; set req.method = "GET"; } - sub vcl_miss { + sub vcl_fetch { set bereq.http.foobar = bereq.url + bereq.proto; diff --git a/bin/varnishtest/tests/v00017.vtc b/bin/varnishtest/tests/v00017.vtc index 9c385f5..71d9dd5 100644 --- a/bin/varnishtest/tests/v00017.vtc +++ b/bin/varnishtest/tests/v00017.vtc @@ -67,7 +67,7 @@ varnish v1 -vcl { varnish v1 -vcl { backend b { .host = "127.0.0.1"; } sub vcl_recv { if (client.ip == "127.0.0.1") { return(pass); } } - sub vcl_miss { if (client.ip != "127.0.0.1") { return(pass); } } + sub vcl_fetch { if (client.ip != "127.0.0.1") { return(pass); } } } varnish v1 -errvcl {Operator > not possible on IP} { diff --git a/bin/varnishtest/tests/v00025.vtc b/bin/varnishtest/tests/v00025.vtc index ab77fdf..e7b7675 100644 --- a/bin/varnishtest/tests/v00025.vtc +++ b/bin/varnishtest/tests/v00025.vtc @@ -41,7 +41,7 @@ sub vcl_hit { } } -sub vcl_miss { +sub vcl_fetch { if (bereq.between_bytes_timeout < 10s) { set bereq.http.quick = "please"; } diff --git a/lib/libvcl/generate.py b/lib/libvcl/generate.py index 51dc8b6..af32e23 100755 --- a/lib/libvcl/generate.py +++ b/lib/libvcl/generate.py @@ -84,6 +84,7 @@ returns =( ('hash', ('hash',)), ('miss', ('error', 'restart', 'pass', 'fetch',)), ('hit', ('error', 'restart', 'pass', 'deliver',)), + ('fetch', ('error', 'fetch', 'pass',)), ('response', ('error', 'restart', 'deliver',)), ('deliver', ('restart', 'deliver',)), ('error', ('restart', 'deliver',)), @@ -238,50 +239,50 @@ sp_variables = ( ), ('bereq.method', 'STRING', - ( 'pipe', 'pass', 'miss', 'response',), - ( 'pipe', 'pass', 'miss', 'response',), + ( 'pipe', 'fetch', 'pass', 'miss', 'response',), + ( 'pipe', 'fetch', 'pass', 'miss', 'response',), 'const struct req *' ), ('bereq.request', 'STRING', - ( 'pipe', 'pass', 'miss', 'response',), - ( 'pipe', 'pass', 'miss', 'response',), + ( 'pipe', 'fetch', 'pass', 'miss', 'response',), + ( 'pipe', 'fetch', 'pass', 'miss', 'response',), 'const struct req *' ), ('bereq.url', 'STRING', - ( 'pipe', 'pass', 'miss', 'response',), - ( 'pipe', 'pass', 'miss', 'response',), + ( 'pipe', 'fetch', 'pass', 'miss', 'response',), + ( 'pipe', 'fetch', 'pass', 'miss', 'response',), 'const struct req *' ), ('bereq.proto', 'STRING', - ( 'pipe', 'pass', 'miss', 'response',), - ( 'pipe', 'pass', 'miss', 'response',), + ( 'pipe', 'fetch', 'pass', 'miss', 'response',), + ( 'pipe', 'fetch', 'pass', 'miss', 'response',), 'const struct req *' ), ('bereq.http.', 'HEADER', - ( 'pipe', 'pass', 'miss', 'response',), - ( 'pipe', 'pass', 'miss', 'response',), + ( 'pipe', 'fetch', 'pass', 'miss', 'response',), + ( 'pipe', 'fetch', 'pass', 'miss', 'response',), 'const struct req *' ), ('bereq.connect_timeout', 'DURATION', - ( 'pipe', 'pass', 'miss',), - ( 'pipe', 'pass', 'miss',), + ( 'pipe', 'fetch', 'pass', 'miss',), + ( 'pipe', 'fetch', 'pass', 'miss',), 'struct req *' ), ('bereq.first_byte_timeout', 'DURATION', - ( 'pass', 'miss',), - ( 'pass', 'miss',), + ( 'fetch', 'pass', 'miss',), + ( 'fetch', 'pass', 'miss',), 'struct req *' ), ('bereq.between_bytes_timeout', 'DURATION', - ( 'pass', 'miss',), - ( 'pass', 'miss',), + ( 'fetch', 'pass', 'miss',), + ( 'fetch', 'pass', 'miss',), 'struct req *' ), ('beresp.proto',