unsigned vdir_remove_backend(struct vdir *vd, VCL_BACKEND be) { unsigned u, n; CHECK_OBJ_NOTNULL(vd, VDIR_MAGIC); if (be == NULL) return (vd->n_backend); CHECK_OBJ(be, DIRECTOR_MAGIC); vdir_wrlock(vd); for (u = 0; u < vd->n_backend; u++) if (vd->backend[u] == be) break; if (u == vd->n_backend) { vdir_unlock(vd); return (vd->n_backend); } vd->total_weight -= vd->weight[u]; n = (vd->n_backend - u) - 1; memmove(&vd->backend[u], &vd->backend[u+1], n * sizeof(vd->backend[0])); memmove(&vd->weight[u], &vd->weight[u+1], n * sizeof(vd->weight[0])); vd->n_backend--; vdir_unlock(vd); return (vd->n_backend); }
unsigned vdir_any_healthy(struct vdir *vd, const struct busyobj *bo, double *changed) { unsigned retval = 0; VCL_BACKEND be; unsigned u; double c; CHECK_OBJ_NOTNULL(vd, VDIR_MAGIC); CHECK_OBJ_ORNULL(bo, BUSYOBJ_MAGIC); vdir_lock(vd); if (changed != NULL) *changed = 0; for (u = 0; u < vd->n_backend; u++) { be = vd->backend[u]; CHECK_OBJ_NOTNULL(be, DIRECTOR_MAGIC); retval = be->healthy(be, bo, &c); if (changed != NULL && c > *changed) *changed = c; if (retval) break; } vdir_unlock(vd); return (retval); }
VCL_BACKEND vdir_pick_be(struct vdir *vd, const struct busyobj *bo, 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 <nloops; l++) { u = vdir_pick_by_weight(vd, w * tw, vbm); be = vd->backend[u]; CHECK_OBJ_NOTNULL(be, DIRECTOR_MAGIC); if (be->healthy(be, bo->digest)) 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); }
VCL_BOOL vdir_any_healthy(VRT_CTX, struct vdir *vd, VCL_TIME *changed) { unsigned retval = 0; VCL_BACKEND be; unsigned u; vtim_real c; CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); CHECK_OBJ_NOTNULL(vd, VDIR_MAGIC); vdir_rdlock(vd); if (changed != NULL) *changed = 0; for (u = 0; u < vd->n_backend; u++) { be = vd->backend[u]; CHECK_OBJ_NOTNULL(be, DIRECTOR_MAGIC); retval = VRT_Healthy(ctx, be, &c); if (changed != NULL && c > *changed) *changed = c; if (retval) break; } vdir_unlock(vd); return (retval); }
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; vd->total_weight += weight; vdir_unlock(vd); return (u); }
VCL_BACKEND vdir_pick_be(VRT_CTX, struct vdir *vd, double w) { unsigned u; VCL_BACKEND be = NULL; CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); CHECK_OBJ_NOTNULL(vd, VDIR_MAGIC); vdir_wrlock(vd); vdir_update_health(ctx, vd); if (vd->total_weight > 0.0) { u = vdir_pick_by_weight(vd, w * vd->total_weight); assert(u < vd->n_backend); be = vd->backend[u]; CHECK_OBJ_NOTNULL(be, DIRECTOR_MAGIC); } vdir_unlock(vd); return (be); }
unsigned vdir_any_healthy(struct vdir *vd, const uint8_t *digest) { 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, digest)) { retval = 1; break; } } vdir_unlock(vd); return (retval); }
void vdir_add_backend(VRT_CTX, struct vdir *vd, VCL_BACKEND be, double weight) { unsigned u; CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); CHECK_OBJ_NOTNULL(vd, VDIR_MAGIC); if (be == NULL) { VRT_fail(ctx, "%s: NULL backend cannot be added", VRT_BACKEND_string(vd->dir)); return; } AN(be); vdir_wrlock(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); }
VCL_BACKEND vdir_pick_be(struct vdir *vd, double w, const struct busyobj *bo) { unsigned u; double tw = 0.0; VCL_BACKEND be = NULL; vdir_lock(vd); for (u = 0; u < vd->n_backend; u++) { if (vd->backend[u]->healthy(vd->backend[u], bo, NULL)) { vbit_clr(vd->vbm, u); tw += vd->weight[u]; } else vbit_set(vd->vbm, u); } if (tw > 0.0) { u = vdir_pick_by_weight(vd, w * tw, vd->vbm); assert(u < vd->n_backend); be = vd->backend[u]; CHECK_OBJ_NOTNULL(be, DIRECTOR_MAGIC); } vdir_unlock(vd); return (be); }
void vdir_list(VRT_CTX, struct vdir *vd, struct vsb *vsb, int pflag, int jflag, int weight) { VCL_BACKEND be; VCL_BOOL h; unsigned u, nh; double w; CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); CHECK_OBJ_NOTNULL(vd, VDIR_MAGIC); if (pflag) { if (jflag) { VSB_cat(vsb, "{\n"); VSB_indent(vsb, 2); if (weight) VSB_printf(vsb, "\"total_weight\": %f,\n", vd->total_weight); VSB_cat(vsb, "\"backends\": {\n"); VSB_indent(vsb, 2); } else { VSB_cat(vsb, "\n\n\tBackend\tWeight\tHealth\n"); } } vdir_rdlock(vd); vdir_update_health(ctx, vd); for (u = 0; pflag && u < vd->n_backend; u++) { be = vd->backend[u]; CHECK_OBJ_NOTNULL(be, DIRECTOR_MAGIC); h = vbit_test(vd->healthy, u); w = h ? vd->weight[u] : 0.0; if (jflag) { if (u) VSB_cat(vsb, ",\n"); VSB_printf(vsb, "\"%s\": {\n", be->vcl_name); VSB_indent(vsb, 2); if (weight) VSB_printf(vsb, "\"weight\": %f,\n", w); if (h) VSB_cat(vsb, "\"health\": \"healthy\"\n"); else VSB_cat(vsb, "\"health\": \"sick\"\n"); VSB_indent(vsb, -2); VSB_cat(vsb, "}"); } else { VSB_cat(vsb, "\t"); VSB_cat(vsb, be->vcl_name); if (weight) VSB_printf(vsb, "\t%6.2f%%\t", 100 * w / vd->total_weight); else VSB_cat(vsb, "\t-\t"); VSB_cat(vsb, h ? "healthy" : "sick"); VSB_cat(vsb, "\n"); } } nh = vd->n_healthy; u = vd->n_backend; vdir_unlock(vd); if (jflag && (pflag)) { VSB_cat(vsb, "\n"); VSB_indent(vsb, -2); VSB_cat(vsb, "}\n"); VSB_indent(vsb, -2); VSB_cat(vsb, "},\n"); } if (pflag) return; if (jflag) VSB_printf(vsb, "[%u, %u, \"%s\"]", nh, u, nh ? "healthy" : "sick"); else VSB_printf(vsb, "%u/%u\t%s", nh, u, nh ? "healthy" : "sick"); }