예제 #1
0
/*
 * 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;
}
예제 #2
0
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);
}
예제 #3
0
/* 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);
}
예제 #4
0
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;
}
예제 #5
0
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));
}