Commit 18be02e3 authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

Add a new director method "->resolve" which returns another backend to use.

This is called recursively until we get to the bottom of the pile.

Doing it this way means that "pick one" directors dont need to know
about other methods on directors and can concentrate on just picking.

It also prevents us from eating up a lot of stack.
parent 9618aa15
......@@ -441,11 +441,16 @@ VDI_GetHdr(struct worker *wrk, struct busyobj *bo)
}
CHECK_OBJ_NOTNULL(bo->director, DIRECTOR_MAGIC);
while (bo->director != NULL && bo->director->resolve != NULL)
bo->director = bo->director->resolve(bo->director, wrk, bo);
if (bo->director->gethdrs != NULL)
return (bo->director->gethdrs(bo->director, wrk, bo));
else
return (vdi_simple_gethdrs(bo->director, wrk, bo));
if (bo->director == NULL) {
VSLb(bo->vsl, SLT_FetchError, "Backend selection failed");
return (-1);
}
AN(bo->director->gethdrs);
return (bo->director->gethdrs(bo->director, wrk, bo));
}
/*--------------------------------------------------------------------*/
......
......@@ -77,6 +77,8 @@ struct vrt_backend_probe;
typedef struct vbc *vdi_getfd_f(const struct director *, struct busyobj *);
typedef unsigned vdi_healthy_f(const struct director *, double *changed);
typedef struct director *vdi_resolve_f(const struct director *,
struct worker *, struct busyobj *);
typedef int vdi_gethdrs_f(const struct director *, struct worker *,
struct busyobj *);
......@@ -87,6 +89,7 @@ struct director {
char *vcl_name;
vdi_getfd_f *getfd;
vdi_healthy_f *healthy;
vdi_resolve_f *resolve;
vdi_gethdrs_f *gethdrs;
void *priv;
};
......
......@@ -45,7 +45,7 @@ struct vmod_directors_fallback {
};
static unsigned __match_proto__(vdi_healthy)
vmod_rr_healthy(const struct director *dir, double *changed)
vmod_fallback_healthy(const struct director *dir, double *changed)
{
struct vmod_directors_fallback *rr;
......@@ -53,13 +53,17 @@ vmod_rr_healthy(const struct director *dir, double *changed)
return (vdir_any_healthy(rr->vd, changed));
}
static struct vbc * __match_proto__(vdi_getfd_f)
vmod_rr_getfd(const struct director *dir, struct busyobj *bo)
static struct director * __match_proto__(vdi_resolve_f)
vmod_fallback_resolve(const struct director *dir, struct worker *wrk,
struct busyobj *bo)
{
struct vmod_directors_fallback *rr;
unsigned u;
VCL_BACKEND be = NULL;
CHECK_OBJ_NOTNULL(dir, DIRECTOR_MAGIC);
CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
CAST_OBJ_NOTNULL(rr, dir->priv, VMOD_DIRECTORS_FALLBACK_MAGIC);
vdir_lock(rr->vd);
for (u = 0; u < rr->vd->n_backend; u++) {
......@@ -69,9 +73,9 @@ vmod_rr_getfd(const struct director *dir, struct busyobj *bo)
break;
}
vdir_unlock(rr->vd);
if (u == rr->vd->n_backend || be == NULL)
return (NULL);
return (be->getfd(be, bo));
if (u == rr->vd->n_backend)
be = NULL;
return (be);
}
VCL_VOID __match_proto__()
......@@ -86,7 +90,8 @@ vmod_fallback__init(const struct vrt_ctx *ctx,
ALLOC_OBJ(rr, VMOD_DIRECTORS_FALLBACK_MAGIC);
AN(rr);
*rrp = rr;
vdir_new(&rr->vd, vcl_name, vmod_rr_healthy, vmod_rr_getfd, rr);
vdir_new(&rr->vd, vcl_name, vmod_fallback_healthy,
vmod_fallback_resolve, rr);
}
VCL_VOID __match_proto__()
......
......@@ -50,7 +50,7 @@ struct vmod_directors_random {
};
static unsigned __match_proto__(vdi_healthy)
vmod_rr_healthy(const struct director *dir, double *changed)
vmod_random_healthy(const struct director *dir, double *changed)
{
struct vmod_directors_random *rr;
......@@ -58,20 +58,22 @@ vmod_rr_healthy(const struct director *dir, double *changed)
return (vdir_any_healthy(rr->vd, changed));
}
static struct vbc * __match_proto__(vdi_getfd_f)
vmod_rr_getfd(const struct director *dir, struct busyobj *bo)
static struct director * __match_proto__(vdi_resolve_f)
vmod_random_resolve(const struct director *dir, struct worker *wrk,
struct busyobj *bo)
{
struct vmod_directors_random *rr;
VCL_BACKEND be;
double r;
CHECK_OBJ_NOTNULL(dir, DIRECTOR_MAGIC);
CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
CAST_OBJ_NOTNULL(rr, dir->priv, VMOD_DIRECTORS_RANDOM_MAGIC);
r = scalbn(random(), -31);
assert(r >= 0 && r < 1.0);
be = vdir_pick_be(rr->vd, r, rr->n_backend);
if (be == NULL)
return (NULL);
return (be->getfd(be, bo));
return (be);
}
VCL_VOID __match_proto__()
......@@ -88,7 +90,8 @@ vmod_random__init(const struct vrt_ctx *ctx, struct vmod_directors_random **rrp,
rr->vbm = vbit_init(8);
AN(rr->vbm);
*rrp = rr;
vdir_new(&rr->vd, vcl_name, vmod_rr_healthy, vmod_rr_getfd, rr);
vdir_new(&rr->vd, vcl_name, vmod_random_healthy, vmod_random_resolve,
rr);
}
VCL_VOID __match_proto__()
......
......@@ -54,13 +54,17 @@ vmod_rr_healthy(const struct director *dir, double *changed)
return (vdir_any_healthy(rr->vd, changed));
}
static struct vbc * __match_proto__(vdi_getfd_f)
vmod_rr_getfd(const struct director *dir, struct busyobj *bo)
static struct director * __match_proto__(vdi_resolve_f)
vmod_rr_resolve(const struct director *dir, struct worker *wrk,
struct busyobj *bo)
{
struct vmod_directors_round_robin *rr;
unsigned u;
VCL_BACKEND be = NULL;
CHECK_OBJ_NOTNULL(dir, DIRECTOR_MAGIC);
CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
CAST_OBJ_NOTNULL(rr, dir->priv, VMOD_DIRECTORS_ROUND_ROBIN_MAGIC);
vdir_lock(rr->vd);
for (u = 0; u < rr->vd->n_backend; u++) {
......@@ -72,9 +76,9 @@ vmod_rr_getfd(const struct director *dir, struct busyobj *bo)
break;
}
vdir_unlock(rr->vd);
if (u == rr->vd->n_backend || be == NULL)
return (NULL);
return (be->getfd(be, bo));
if (u == rr->vd->n_backend)
be = NULL;
return (be);
}
VCL_VOID __match_proto__()
......@@ -89,7 +93,7 @@ vmod_round_robin__init(const struct vrt_ctx *ctx,
ALLOC_OBJ(rr, VMOD_DIRECTORS_ROUND_ROBIN_MAGIC);
AN(rr);
*rrp = rr;
vdir_new(&rr->vd, vcl_name, vmod_rr_healthy, vmod_rr_getfd, rr);
vdir_new(&rr->vd, vcl_name, vmod_rr_healthy, vmod_rr_resolve, rr);
}
VCL_VOID __match_proto__()
......
......@@ -52,7 +52,7 @@ vdir_expand(struct vdir *vd, unsigned n)
void
vdir_new(struct vdir **vdp, const char *vcl_name, vdi_healthy_f *healthy,
vdi_getfd_f *getfd, void *priv)
vdi_resolve_f *resolve, void *priv)
{
struct vdir *vd;
......@@ -69,7 +69,7 @@ vdir_new(struct vdir **vdp, const char *vcl_name, vdi_healthy_f *healthy,
REPLACE(vd->dir->vcl_name, vcl_name);
vd->dir->priv = priv;
vd->dir->healthy = healthy;
vd->dir->getfd = getfd;
vd->dir->resolve = resolve;
vd->vbm = vbit_init(8);
AN(vd->vbm);
}
......
......@@ -42,7 +42,7 @@ struct vdir {
};
void vdir_new(struct vdir **vdp, const char *vcl_name, vdi_healthy_f *healthy,
vdi_getfd_f *getfd, void *priv);
vdi_resolve_f *resolve, void *priv);
void vdir_delete(struct vdir **vdp);
void vdir_lock(struct vdir *vd);
void vdir_unlock(struct vdir *vd);
......
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