/* * iterate backends and update * - healthy bitmap * - number of healthy backends * - total_weight * - last change time of the VCL_BACKEND * * must be called under the vdir lock (read or write). * * A write lock is required if consistency between the individual attributes is * a must, e.g. when total_weight is required to be the exact sum of the weights * * The read lock is safe because add_backend expands the healthy bitmap and all * other members are atomic and may be used if consistency is not required. */ void vdir_update_health(VRT_CTX, struct vdir *vd) { VCL_TIME c, changed = 0; VCL_BOOL h; VCL_BACKEND be; unsigned u, nh = 0; double tw = 0.0; struct vbitmap *healthy; CHECK_OBJ_NOTNULL(vd, VDIR_MAGIC); healthy = vd->healthy; for (u = 0; u < vd->n_backend; u++) { be = vd->backend[u]; CHECK_OBJ_NOTNULL(be, DIRECTOR_MAGIC); c = 0; h = VRT_Healthy(ctx, vd->backend[u], &c); if (h) { nh++; tw += vd->weight[u]; } if (c > changed) changed = c; if (h != vbit_test(healthy, u)) { if (h) vbit_set(healthy, u); else vbit_clr(healthy, u); } } VRT_SetChanged(vd->dir, changed); vd->total_weight = tw; vd->n_healthy = nh; }
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); }
/* basically same as vdir_any_healthy * - XXX we should embed a vdir * - XXX should we return the health state of the actual backend * for healthy=IGNORE ? */ VCL_BOOL sharddir_any_healthy(VRT_CTX, struct sharddir *shardd, VCL_TIME *changed) { unsigned retval = 0; VCL_BACKEND be; unsigned u; vtim_real c; CHECK_OBJ_NOTNULL(shardd, SHARDDIR_MAGIC); sharddir_rdlock(shardd); if (changed != NULL) *changed = 0; for (u = 0; u < shardd->n_backend; u++) { be = shardd->backend[u].backend; CHECK_OBJ_NOTNULL(be, DIRECTOR_MAGIC); retval = VRT_Healthy(ctx, be, &c); if (changed != NULL && c > *changed) *changed = c; if (retval) break; } sharddir_unlock(shardd); return (retval); }
static int shard_next(struct shard_state *state, VCL_INT skip, VCL_BOOL healthy) { int c, chosen = -1; uint32_t ringsz; VCL_BACKEND be; vtim_real changed; struct shard_be_info *sbe; AN(state); assert(state->idx >= 0); CHECK_OBJ_NOTNULL(state->shardd, SHARDDIR_MAGIC); if (state->pickcount >= state->shardd->n_backend) return -1; ringsz = state->shardd->n_backend * state->shardd->replicas; while (state->pickcount < state->shardd->n_backend && skip >= 0) { c = state->shardd->hashcircle[state->idx].host; if (!vbit_test(state->picklist, c)) { vbit_set(state->picklist, c); state->pickcount++; sbe = NULL; be = state->shardd->backend[c].backend; AN(be); if (VRT_Healthy(state->ctx, be, &changed)) { if (skip-- == 0) { chosen = c; sbe = &state->last; } else { sbe = &state->previous; } } else if (!healthy && skip-- == 0) { chosen = c; sbe = &state->last; } if (sbe == &state->last && state->last.hostid != -1) memcpy(&state->previous, &state->last, sizeof(state->previous)); if (sbe) { sbe->hostid = c; sbe->healthy = 1; sbe->changed = changed; } if (chosen != -1) break; } if (++(state->idx) == ringsz) state->idx = 0; } return chosen; }
vmod_healthy(VRT_CTX, VCL_BACKEND be) { CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); CHECK_OBJ_ORNULL(be, DIRECTOR_MAGIC); return (VRT_Healthy(ctx, be)); }