static int vsl_ix_arg(struct VSL_data *vd, const char *opt, int arg) { int i, j, l; const char *b, *e, *p, *q; CHECK_OBJ_NOTNULL(vd, VSL_MAGIC); /* If first option is 'i', set all bits for supression */ if (arg == 'i' && !(vd->flags & F_SEEN_IX)) for (i = 0; i < 256; i++) vbit_set(vd->vbm_supress, i); vd->flags |= F_SEEN_IX; for (b = opt; *b; b = e) { while (isspace(*b)) b++; e = strchr(b, ','); if (e == NULL) e = strchr(b, '\0'); l = e - b; if (*e == ',') e++; while (isspace(b[l - 1])) l--; for (i = 0; i < 256; i++) { if (VSL_tags[i] == NULL) continue; p = VSL_tags[i]; q = b; for (j = 0; j < l; j++) if (tolower(*q++) != tolower(*p++)) break; if (j != l || *p != '\0') continue; if (arg == 'x') vbit_set(vd->vbm_supress, i); else vbit_clr(vd->vbm_supress, i); break; } if (i == 256) { fprintf(stderr, "Could not match \"%*.*s\" to any tag\n", l, l, b); return (-1); } } return (1); }
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); }
/* * 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; }
void VSL_Select(struct VSL_data *vd, unsigned tag) { CHECK_OBJ_NOTNULL(vd, VSL_MAGIC); vbit_set(vd->vbm_select, tag); }
static int vsl_ix_arg(struct VSL_data *vsl, int opt, const char *arg) { int i, l; const char *b, *e; CHECK_OBJ_NOTNULL(vsl, VSL_MAGIC); /* If first option is 'i', set all bits for supression */ if (opt == 'i' && !(vsl->flags & F_SEEN_ix)) for (i = 0; i < 256; i++) vbit_set(vsl->vbm_supress, i); vsl->flags |= F_SEEN_ix; for (b = arg; *b; b = e) { while (isspace(*b)) b++; e = strchr(b, ','); if (e == NULL) e = strchr(b, '\0'); l = e - b; if (*e == ',') e++; while (isspace(b[l - 1])) l--; i = VSL_Name2Tag(b, l); if (i >= 0) { if (opt == 'x') vbit_set(vsl->vbm_supress, i); else vbit_clr(vsl->vbm_supress, i); } else if (i == -2) { return (vsl_diag(vsl, "-%c: \"%*.*s\" matches multiple tags\n", (char)opt, l, l, b)); } else { return (vsl_diag(vsl, "-%c: Could not match \"%*.*s\" to any tag\n", (char)opt, l, l, b)); } } return (1); }
void mgt_child_inherit(int fd, const char *what) { assert(fd >= 0); if (fd_map == NULL) fd_map = vbit_init(128); AN(fd_map); if (what != NULL) vbit_set(fd_map, fd); else vbit_clr(fd_map, fd); }
int VSL_Arg(struct VSL_data *vsl, int opt, const char *arg) { int i; char *p; double d; long l; CHECK_OBJ_NOTNULL(vsl, VSL_MAGIC); /* If first option is 'i', set all bits for supression */ if ((opt == 'i' || opt == 'I') && !(vsl->flags & F_SEEN_ixIX)) for (i = 0; i < SLT__MAX; i++) vbit_set(vsl->vbm_supress, i); switch (opt) { case 'b': vsl->b_opt = 1; return (1); case 'c': vsl->c_opt = 1; return (1); case 'C': /* Caseless regular expressions */ vsl->C_opt = 1; return (1); case 'i': case 'x': return (vsl_ix_arg(vsl, opt, arg)); case 'I': case 'X': return (vsl_IX_arg(vsl, opt, arg)); case 'L': l = strtol(arg, &p, 0); while (isspace(*p)) p++; if (*p != '\0') return (vsl_diag(vsl, "-L: Syntax error")); if (l < 0 || l > INT_MAX) return (vsl_diag(vsl, "-L: Range error")); vsl->L_opt = (int)l; return (1); case 'T': d = strtod(arg, &p); while (isspace(*p)) p++; if (*p != '\0') return (vsl_diag(vsl, "-P: Syntax error")); if (d < 0.) return (vsl_diag(vsl, "-L: Range error")); vsl->T_opt = d; return (1); case 'v': vsl->v_opt = 1; return (1); default: return (0); } }
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); }
vsl_vbm_bitset(int bit, void *priv) { vbit_set((struct vbitmap *)priv, bit); }
static int shard_next(struct shard_state *state, VCL_INT skip, VCL_BOOL healthy) { int c, chosen = -1; uint32_t ringsz; VCL_BACKEND be; double 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 (be->healthy(be, state->ctx->bo, &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; }
int VSL_NextLog(struct VSL_data *vd, unsigned char **pp) { unsigned char *p, t; unsigned u, l; int i; CHECK_OBJ_NOTNULL(vd, VSL_MAGIC); while (1) { i = vsl_nextlog(vd, &p); if (i != 1) return (i); u = SHMLOG_ID(p); l = SHMLOG_LEN(p); (void)l; switch(p[SHMLOG_TAG]) { case SLT_SessionOpen: case SLT_ReqStart: vbit_set(vd->vbm_client, u); vbit_clr(vd->vbm_backend, u); break; case SLT_BackendOpen: case SLT_BackendXID: vbit_clr(vd->vbm_client, u); vbit_set(vd->vbm_backend, u); break; default: break; } if (vd->skip) { --vd->skip; continue; } else if (vd->keep) { if (--vd->keep == 0) return (-1); } t = p[SHMLOG_TAG]; if (vbit_test(vd->vbm_select, t)) { *pp = p; return (1); } if (vbit_test(vd->vbm_supress, t)) continue; if (vd->b_opt && !vbit_test(vd->vbm_backend, u)) continue; if (vd->c_opt && !vbit_test(vd->vbm_client, u)) continue; if (vd->regincl != NULL) { i = VRE_exec(vd->regincl, (char *)p + SHMLOG_DATA, SHMLOG_LEN(p), /* Length */ 0, 0, NULL, 0); if (i == VRE_ERROR_NOMATCH) continue; } if (vd->regexcl != NULL) { i = VRE_exec(vd->regexcl, (char *)p + SHMLOG_DATA, SHMLOG_LEN(p), /* Length */ 0, 0, NULL, 0); if (i != VRE_ERROR_NOMATCH) continue; } *pp = p; return (1); } }