diff --git a/bin/varnishd/cache/cache_backend.c b/bin/varnishd/cache/cache_backend.c index 0235194a5fb..7ca57d50d71 100644 --- a/bin/varnishd/cache/cache_backend.c +++ b/bin/varnishd/cache/cache_backend.c @@ -433,6 +433,23 @@ vbe_list(const struct director *d, struct vsb *vsb, int vflag, int pflag) VSB_printf(vsb, "%-10s", d->health ? "healthy" : "sick"); } +/*-------------------------------------------------------------------- + */ + +static const struct director_methods vbe_methods[1] = {{ + .magic = DIRECTOR_METHODS_MAGIC, + .type = "backend", + .http1pipe = vbe_dir_http1pipe, + .healthy = vbe_dir_healthy, + .gethdrs = vbe_dir_gethdrs, + .getip = vbe_dir_getip, + .finish = vbe_dir_finish, + .event = vbe_dir_event, + .destroy = vbe_destroy, + .panic = vbe_panic, + .list = vbe_list, +}}; + /*-------------------------------------------------------------------- * Create a new static or dynamic director::backend instance. */ @@ -481,17 +498,8 @@ VRT_new_backend_clustered(VRT_CTX, struct vsmw_cluster *vc, d = be->director; INIT_OBJ(d, DIRECTOR_MAGIC); d->priv = be; - d->name = "backend"; d->vcl_name = be->vcl_name; - d->http1pipe = vbe_dir_http1pipe; - d->healthy = vbe_dir_healthy; - d->gethdrs = vbe_dir_gethdrs; - d->getip = vbe_dir_getip; - d->finish = vbe_dir_finish; - d->event = vbe_dir_event; - d->panic = vbe_panic; - d->list = vbe_list; - d->destroy = vbe_destroy; + d->methods = vbe_methods; d->health = 1; d->health_changed = VTIM_real(); diff --git a/bin/varnishd/cache/cache_director.c b/bin/varnishd/cache/cache_director.c index cd99f1aeda4..952506f6871 100644 --- a/bin/varnishd/cache/cache_director.c +++ b/bin/varnishd/cache/cache_director.c @@ -85,9 +85,10 @@ vdi_resolve(struct worker *wrk, struct busyobj *bo) CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC); - for (d = bo->director_req; d != NULL && d->resolve != NULL; d = d2) { + for (d = bo->director_req; d != NULL && + d->methods->resolve != NULL; d = d2) { CHECK_OBJ_NOTNULL(d, DIRECTOR_MAGIC); - d2 = d->resolve(d, wrk, bo); + d2 = d->methods->resolve(d, wrk, bo); if (d2 == NULL) VSLb(bo->vsl, SLT_FetchError, "Director %s returned no backend", d->vcl_name); @@ -112,9 +113,9 @@ VDI_GetHdr(struct worker *wrk, struct busyobj *bo) d = vdi_resolve(wrk, bo); if (d != NULL) { - AN(d->gethdrs); + AN(d->methods->gethdrs); bo->director_state = DIR_S_HDRS; - i = d->gethdrs(d, wrk, bo); + i = d->methods->gethdrs(d, wrk, bo); } if (i) bo->director_state = DIR_S_NULL; @@ -133,13 +134,13 @@ VDI_GetBody(struct worker *wrk, struct busyobj *bo) d = bo->director_resp; CHECK_OBJ_NOTNULL(d, DIRECTOR_MAGIC); - AZ(d->resolve); + AZ(d->methods->resolve); assert(bo->director_state == DIR_S_HDRS); bo->director_state = DIR_S_BODY; - if (d->getbody == NULL) + if (d->methods->getbody == NULL) return (0); - return (d->getbody(d, wrk, bo)); + return (d->methods->getbody(d, wrk, bo)); } /* Get IP number (if any ) -------------------------------------------*/ @@ -156,10 +157,10 @@ VDI_GetIP(struct worker *wrk, struct busyobj *bo) CHECK_OBJ_NOTNULL(d, DIRECTOR_MAGIC); assert(bo->director_state == DIR_S_HDRS || bo->director_state == DIR_S_BODY); - AZ(d->resolve); - if (d->getip == NULL) + AZ(d->methods->resolve); + if (d->methods->getip == NULL) return (NULL); - return (d->getip(d, wrk, bo)); + return (d->methods->getip(d, wrk, bo)); } /* Finish fetch ------------------------------------------------------*/ @@ -175,11 +176,11 @@ VDI_Finish(struct worker *wrk, struct busyobj *bo) d = bo->director_resp; CHECK_OBJ_NOTNULL(d, DIRECTOR_MAGIC); - AZ(d->resolve); - AN(d->finish); + AZ(d->methods->resolve); + AN(d->methods->finish); assert(bo->director_state != DIR_S_NULL); - d->finish(d, wrk, bo); + d->methods->finish(d, wrk, bo); bo->director_state = DIR_S_NULL; } @@ -194,11 +195,11 @@ VDI_Http1Pipe(struct req *req, struct busyobj *bo) CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC); d = vdi_resolve(req->wrk, bo); - if (d == NULL || d->http1pipe == NULL) { + if (d == NULL || d->methods->http1pipe == NULL) { VSLb(bo->vsl, SLT_VCL_Error, "Backend does not support pipe"); return (SC_TX_ERROR); } - return (d->http1pipe(d, req, bo)); + return (d->methods->http1pipe(d, req, bo)); } /* Check health -------------------------------------------------------- @@ -216,9 +217,9 @@ VRT_Healthy(VRT_CTX, VCL_BACKEND d) CHECK_OBJ_NOTNULL(d, DIRECTOR_MAGIC); if (!VDI_Healthy(d, NULL)) return (0); - if (d->healthy == NULL) + if (d->methods->healthy == NULL) return (1); - return (d->healthy(d, ctx->bo, NULL)); + return (d->methods->healthy(d, ctx->bo, NULL)); } /* Send Event ---------------------------------------------------------- @@ -229,8 +230,8 @@ VDI_Event(const struct director *d, enum vcl_event_e ev) { CHECK_OBJ_NOTNULL(d, DIRECTOR_MAGIC); - if (d->event != NULL) - d->event(d, ev); + if (d->methods->event != NULL) + d->methods->event(d, ev); } /* Dump panic info ----------------------------------------------------- @@ -247,10 +248,10 @@ VDI_Panic(const struct director *d, struct vsb *vsb, const char *nm) VSB_printf(vsb, "health = %s,\n", d->health ? "healthy" : "sick"); VSB_printf(vsb, "admin_health = %s, changed = %f,\n", VDI_Ahealth(d), d->health_changed); - VSB_printf(vsb, "type = %s {\n", d->name); + VSB_printf(vsb, "type = %s {\n", d->methods->type); VSB_indent(vsb, 2); - if (d->panic != NULL) - d->panic(d, vsb); + if (d->methods->panic != NULL) + d->methods->panic(d, vsb); VSB_indent(vsb, -2); VSB_printf(vsb, "},\n"); VSB_indent(vsb, -2); @@ -299,15 +300,15 @@ do_list(struct cli *cli, struct director *d, void *priv) VCLI_Out(cli, "\n%-30s %-7s ", d->cli_name, VDI_Ahealth(d)); - if (d->list != NULL) - d->list(d, cli->sb, 0, 0); + if (d->methods->list != NULL) + d->methods->list(d, cli->sb, 0, 0); else VCLI_Out(cli, "%-10s", d->health ? "healthy" : "sick"); VTIM_format(d->health_changed, time_str); VCLI_Out(cli, " %s", time_str); - if (la->p || la->v) - d->list(d, cli->sb, la->p, la->v); + if ((la->p || la->v) && d->methods->list != NULL) + d->methods->list(d, cli->sb, la->p, la->v); return (0); } diff --git a/bin/varnishd/cache/cache_director.h b/bin/varnishd/cache/cache_director.h index 43e7e4b5586..6004a09e8d3 100644 --- a/bin/varnishd/cache/cache_director.h +++ b/bin/varnishd/cache/cache_director.h @@ -64,11 +64,10 @@ typedef void vdi_panic_f(const struct director *, struct vsb *); typedef void vdi_list_f(const struct director *, struct vsb *, int, int); -struct director { +struct director_methods { unsigned magic; -#define DIRECTOR_MAGIC 0x3336351d - const char *name; - char *vcl_name; +#define DIRECTOR_METHODS_MAGIC 0x4ec0c4bb + const char *type; vdi_http1pipe_f *http1pipe; vdi_healthy_f *healthy; vdi_resolve_f *resolve; @@ -80,6 +79,13 @@ struct director { vdi_destroy_f *destroy; vdi_panic_f *panic; vdi_list_f *list; +}; + +struct director { + unsigned magic; +#define DIRECTOR_MAGIC 0x3336351d + const struct director_methods *methods; + char *vcl_name; void *priv; const void *priv2; diff --git a/bin/varnishd/cache/cache_vcl.c b/bin/varnishd/cache/cache_vcl.c index 7ca458c3b94..178ae2ce7c6 100644 --- a/bin/varnishd/cache/cache_vcl.c +++ b/bin/varnishd/cache/cache_vcl.c @@ -309,8 +309,8 @@ vcl_KillBackends(struct vcl *vcl) break; VTAILQ_REMOVE(&vcl->director_list, vdir, list); REPLACE(vdir->dir->cli_name, NULL); - AN(vdir->dir->destroy); - vdir->dir->destroy(vdir->dir); + AN(vdir->dir->methods->destroy); + vdir->dir->methods->destroy(vdir->dir); FREE_OBJ(vdir); } } diff --git a/bin/varnishd/cache/cache_vcl_vrt.c b/bin/varnishd/cache/cache_vcl_vrt.c index 0848a56043b..0d32de6b297 100644 --- a/bin/varnishd/cache/cache_vcl_vrt.c +++ b/bin/varnishd/cache/cache_vcl_vrt.c @@ -135,7 +135,8 @@ VRT_AddDirector(VRT_CTX, struct director *d, const char *vcl_name) CHECK_OBJ_NOTNULL(d, DIRECTOR_MAGIC); vcl = ctx->vcl; CHECK_OBJ_NOTNULL(vcl, VCL_MAGIC); - AN(d->destroy); + CHECK_OBJ_NOTNULL(d->methods, DIRECTOR_METHODS_MAGIC); + AN(d->methods->destroy); AZ(errno=pthread_rwlock_rdlock(&vcl->temp_rwl)); if (vcl->temp == VCL_TEMP_COOLING) { @@ -191,9 +192,9 @@ VRT_DelDirector(VRT_CTX, struct director *d) if (VCL_WARM(vcl)) VDI_Event(d, VCL_EVENT_COLD); AZ(errno=pthread_rwlock_unlock(&vcl->temp_rwl)); - AN(d->destroy); + AN(d->methods->destroy); REPLACE(d->cli_name, NULL); - d->destroy(d); + d->methods->destroy(d); FREE_OBJ(vdir); } diff --git a/lib/libvmod_directors/fall_back.c b/lib/libvmod_directors/fall_back.c index 8ae3ddc3019..2b7367d6691 100644 --- a/lib/libvmod_directors/fall_back.c +++ b/lib/libvmod_directors/fall_back.c @@ -75,7 +75,7 @@ vmod_fallback_resolve(const struct director *dir, struct worker *wrk, for (u = 0; u < fb->vd->n_backend; u++) { be = fb->vd->backend[fb->cur]; CHECK_OBJ_NOTNULL(be, DIRECTOR_MAGIC); - if (be->healthy(be, bo, NULL)) + if (be->methods->healthy(be, bo, NULL)) break; if (++fb->cur == fb->vd->n_backend) fb->cur = 0; @@ -86,6 +86,14 @@ vmod_fallback_resolve(const struct director *dir, struct worker *wrk, return (be); } +static const struct director_methods vmod_fallback_methods[1] = {{ + .magic = DIRECTOR_METHODS_MAGIC, + .type = "fallback", + .healthy = vmod_fallback_healthy, + .resolve = vmod_fallback_resolve, +}}; + + VCL_VOID v_matchproto_() vmod_fallback__init(VRT_CTX, struct vmod_directors_fallback **fbp, const char *vcl_name, VCL_BOOL sticky) @@ -98,8 +106,7 @@ vmod_fallback__init(VRT_CTX, ALLOC_OBJ(fb, VMOD_DIRECTORS_FALLBACK_MAGIC); AN(fb); *fbp = fb; - vdir_new(ctx, &fb->vd, "fallback", vcl_name, vmod_fallback_healthy, - vmod_fallback_resolve, fb); + vdir_new(ctx, &fb->vd, vcl_name, vmod_fallback_methods, fb); fb->st = sticky; } diff --git a/lib/libvmod_directors/hash.c b/lib/libvmod_directors/hash.c index a05308195d9..50d4ce94aab 100644 --- a/lib/libvmod_directors/hash.c +++ b/lib/libvmod_directors/hash.c @@ -47,6 +47,12 @@ struct vmod_directors_hash { struct vdir *vd; }; +static const struct director_methods vmod_hash_methods[1] = {{ + .magic = DIRECTOR_METHODS_MAGIC, + .type = "hash", +}}; + + VCL_VOID v_matchproto_() vmod_hash__init(VRT_CTX, struct vmod_directors_hash **rrp, const char *vcl_name) @@ -59,7 +65,7 @@ vmod_hash__init(VRT_CTX, struct vmod_directors_hash **rrp, ALLOC_OBJ(rr, VMOD_DIRECTORS_HASH_MAGIC); AN(rr); *rrp = rr; - vdir_new(ctx, &rr->vd, "hash", vcl_name, NULL, NULL, rr); + vdir_new(ctx, &rr->vd, vcl_name, vmod_hash_methods, rr); } VCL_VOID v_matchproto_() diff --git a/lib/libvmod_directors/random.c b/lib/libvmod_directors/random.c index 4ce6328f3a2..2fd6a35a2d9 100644 --- a/lib/libvmod_directors/random.c +++ b/lib/libvmod_directors/random.c @@ -74,6 +74,14 @@ vmod_random_resolve(const struct director *dir, struct worker *wrk, return (be); } +static const struct director_methods vmod_random_methods[1] = {{ + .magic = DIRECTOR_METHODS_MAGIC, + .type = "random", + .healthy = vmod_random_healthy, + .resolve = vmod_random_resolve, +}}; + + VCL_VOID v_matchproto_() vmod_random__init(VRT_CTX, struct vmod_directors_random **rrp, const char *vcl_name) @@ -86,8 +94,7 @@ vmod_random__init(VRT_CTX, struct vmod_directors_random **rrp, ALLOC_OBJ(rr, VMOD_DIRECTORS_RANDOM_MAGIC); AN(rr); *rrp = rr; - vdir_new(ctx, &rr->vd, "random", vcl_name, vmod_random_healthy, - vmod_random_resolve, rr); + vdir_new(ctx, &rr->vd, vcl_name, vmod_random_methods, rr); } VCL_VOID v_matchproto_() diff --git a/lib/libvmod_directors/round_robin.c b/lib/libvmod_directors/round_robin.c index 7e888f365ca..1199abbb1ab 100644 --- a/lib/libvmod_directors/round_robin.c +++ b/lib/libvmod_directors/round_robin.c @@ -74,7 +74,7 @@ vmod_rr_resolve(const struct director *dir, struct worker *wrk, rr->nxt = nxt + 1; be = rr->vd->backend[nxt]; CHECK_OBJ_NOTNULL(be, DIRECTOR_MAGIC); - if (be->healthy(be, bo, NULL)) + if (be->methods->healthy(be, bo, NULL)) break; } vdir_unlock(rr->vd); @@ -83,6 +83,13 @@ vmod_rr_resolve(const struct director *dir, struct worker *wrk, return (be); } +static const struct director_methods vmod_rr_methods[1] = {{ + .magic = DIRECTOR_METHODS_MAGIC, + .type = "round-robin", + .healthy = vmod_rr_healthy, + .resolve = vmod_rr_resolve, +}}; + VCL_VOID v_matchproto_() vmod_round_robin__init(VRT_CTX, struct vmod_directors_round_robin **rrp, const char *vcl_name) @@ -95,8 +102,7 @@ vmod_round_robin__init(VRT_CTX, ALLOC_OBJ(rr, VMOD_DIRECTORS_ROUND_ROBIN_MAGIC); AN(rr); *rrp = rr; - vdir_new(ctx, &rr->vd, "round-robin", vcl_name, vmod_rr_healthy, - vmod_rr_resolve, rr); + vdir_new(ctx, &rr->vd, vcl_name, vmod_rr_methods, rr); } VCL_VOID v_matchproto_() diff --git a/lib/libvmod_directors/shard_dir.c b/lib/libvmod_directors/shard_dir.c index 7a667c36865..259496286bc 100644 --- a/lib/libvmod_directors/shard_dir.c +++ b/lib/libvmod_directors/shard_dir.c @@ -189,7 +189,7 @@ shard_next(struct shard_state *state, VCL_INT skip, VCL_BOOL healthy) sbe = NULL; be = state->shardd->backend[c].backend; AN(be); - if (be->healthy(be, state->ctx->bo, &changed)) { + if (be->methods->healthy(be, state->ctx->bo, &changed)) { if (skip-- == 0) { chosen = c; sbe = &state->last; @@ -326,7 +326,7 @@ sharddir_any_healthy(struct sharddir *shardd, const struct busyobj *bo, for (u = 0; u < shardd->n_backend; u++) { be = shardd->backend[u].backend; CHECK_OBJ_NOTNULL(be, DIRECTOR_MAGIC); - retval = be->healthy(be, bo, &c); + retval = be->methods->healthy(be, bo, &c); if (changed != NULL && c > *changed) *changed = c; if (retval) diff --git a/lib/libvmod_directors/vdir.c b/lib/libvmod_directors/vdir.c index 95cc9dfa41b..f57e30336aa 100644 --- a/lib/libvmod_directors/vdir.c +++ b/lib/libvmod_directors/vdir.c @@ -50,13 +50,13 @@ vdir_expand(struct vdir *vd, unsigned n) } void -vdir_new(VRT_CTX, struct vdir **vdp, const char *name, const char *vcl_name, - vdi_healthy_f *healthy, vdi_resolve_f *resolve, void *priv) +vdir_new(VRT_CTX, struct vdir **vdp, const char *vcl_name, + const struct director_methods *m, void *priv) { struct vdir *vd; AN(ctx); - AN(name); + CHECK_OBJ_NOTNULL(m, DIRECTOR_METHODS_MAGIC); AN(vcl_name); AN(vdp); AZ(*vdp); @@ -67,11 +67,9 @@ vdir_new(VRT_CTX, struct vdir **vdp, const char *name, const char *vcl_name, ALLOC_OBJ(vd->dir, DIRECTOR_MAGIC); AN(vd->dir); - vd->dir->name = name; + vd->dir->methods = m; REPLACE(vd->dir->vcl_name, vcl_name); vd->dir->priv = priv; - vd->dir->healthy = healthy; - vd->dir->resolve = resolve; vd->dir->admin_health = VDI_AH_HEALTHY; vd->vbm = vbit_new(8); AN(vd->vbm); @@ -188,7 +186,7 @@ vdir_any_healthy(struct vdir *vd, const struct busyobj *bo, double *changed) for (u = 0; u < vd->n_backend; u++) { be = vd->backend[u]; CHECK_OBJ_NOTNULL(be, DIRECTOR_MAGIC); - retval = be->healthy(be, bo, &c); + retval = be->methods->healthy(be, bo, &c); if (changed != NULL && c > *changed) *changed = c; if (retval) @@ -228,7 +226,7 @@ vdir_pick_be(struct vdir *vd, double w, const struct busyobj *bo) vdir_wrlock(vd); for (u = 0; u < vd->n_backend; u++) { - if (vd->backend[u]->healthy(vd->backend[u], bo, NULL)) { + if (vd->backend[u]->methods->healthy(vd->backend[u], bo, NULL)) { vbit_clr(vd->vbm, u); tw += vd->weight[u]; } else diff --git a/lib/libvmod_directors/vdir.h b/lib/libvmod_directors/vdir.h index afdc4217752..4e7d9e699aa 100644 --- a/lib/libvmod_directors/vdir.h +++ b/lib/libvmod_directors/vdir.h @@ -41,9 +41,8 @@ struct vdir { struct vbitmap *vbm; }; -void vdir_new(VRT_CTX, struct vdir **vdp, const char *name, - const char *vcl_name, - vdi_healthy_f *healthy, vdi_resolve_f *resolve, void *priv); +void vdir_new(VRT_CTX, struct vdir **vdp, const char *vcl_name, + const struct director_methods *, void *priv); void vdir_delete(struct vdir **vdp); void vdir_rdlock(struct vdir *vd); void vdir_wrlock(struct vdir *vd); diff --git a/lib/libvmod_directors/vmod_shard.c b/lib/libvmod_directors/vmod_shard.c index 1d6877ea36d..58830b2715e 100644 --- a/lib/libvmod_directors/vmod_shard.c +++ b/lib/libvmod_directors/vmod_shard.c @@ -196,6 +196,14 @@ shard__assert(void) assert(t2a == t2b); } +static const struct director_methods vmod_shard_methods[1] = {{ + .magic = DIRECTOR_METHODS_MAGIC, + .type = "shard", + .resolve = vmod_shard_resolve, + .healthy = vmod_shard_healthy, +}}; + + VCL_VOID v_matchproto_(td_directors_shard__init) vmod_shard__init(VRT_CTX, struct vmod_directors_shard **vshardp, const char *vcl_name) @@ -217,8 +225,7 @@ vmod_shard__init(VRT_CTX, struct vmod_directors_shard **vshardp, AN(vshard->dir); REPLACE(vshard->dir->vcl_name, vcl_name); vshard->dir->priv = vshard; - vshard->dir->resolve = vmod_shard_resolve; - vshard->dir->healthy = vmod_shard_healthy; + vshard->dir->methods = vmod_shard_methods; vshard->dir->admin_health = VDI_AH_HEALTHY; }