Commit 7be8dd9f authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

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...
parent 16c8251d
......@@ -35,7 +35,7 @@ varnish v1 -vcl+backend {
}
sub vcl_recv {
set req.backend = rr.select();
set req.backend = rr.backend();
}
} -start
......
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
......@@ -38,5 +38,5 @@ Object obj(STRING) {
Object rr() {
Method VOID .add_backend(BACKEND)
Method BACKEND .select()
Method BACKEND .backend()
}
......@@ -31,6 +31,7 @@
#include <stdlib.h>
#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);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment