Update vdir.[ch] from varnish-cache

parent e85e0c83
/*-
* Copyright (c) 2013-2015 Varnish Software AS
* Copyright 2019 UPLEX - Nils Goroll Systemoptimierung
* All rights reserved.
*
* Author: Poul-Henning Kamp <phk@FreeBSD.org>
* Author: Nils Goroll <nils.goroll@uplex.de>
*
* SPDX-License-Identifier: BSD-2-Clause
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
......@@ -29,10 +33,13 @@
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include "cache/cache.h"
#include "vbm.h"
#include "vcl.h"
#include "vsb.h"
#include "vdir.h"
......@@ -45,6 +52,9 @@ vdir_expand(struct vdir *vd, unsigned n)
AN(vd->backend);
vd->weight = realloc(vd->weight, n * sizeof *vd->weight);
AN(vd->weight);
if (n > vd->healthy->nbits)
vbit_expand(vd->healthy, n);
AN(vd->healthy);
vd->l_backend = n;
}
......@@ -64,8 +74,8 @@ vdir_new(VRT_CTX, struct vdir **vdp, const char *vcl_name,
*vdp = vd;
AZ(pthread_rwlock_init(&vd->mtx, NULL));
vd->dir = VRT_AddDirector(ctx, m, priv, "%s", vcl_name);
vd->vbm = vbit_new(8);
AN(vd->vbm);
vd->healthy = vbit_new(8);
AN(vd->healthy);
}
void
......@@ -82,7 +92,7 @@ vdir_delete(struct vdir **vdp)
free(vd->backend);
free(vd->weight);
AZ(pthread_rwlock_destroy(&vd->mtx));
vbit_destroy(vd->vbm);
vbit_destroy(vd->healthy);
FREE_OBJ(vd);
}
......@@ -116,7 +126,7 @@ vdir_add_backend(VRT_CTX, struct vdir *vd, VCL_BACKEND be, double weight)
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_fail(ctx, "%s: None backend cannot be added",
VRT_BACKEND_string(vd->dir));
return;
}
......@@ -126,6 +136,7 @@ vdir_add_backend(VRT_CTX, struct vdir *vd, VCL_BACKEND be, double weight)
vdir_expand(vd, vd->l_backend + 16);
assert(vd->n_backend < vd->l_backend);
u = vd->n_backend++;
vd->backend[u] = NULL;
VRT_Assign_Backend(&vd->backend[u], be);
vd->weight[u] = weight;
vd->total_weight += weight;
......@@ -140,7 +151,7 @@ vdir_remove_backend(VRT_CTX, struct vdir *vd, VCL_BACKEND be, unsigned *cur)
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
CHECK_OBJ_NOTNULL(vd, VDIR_MAGIC);
if (be == NULL) {
VRT_fail(ctx, "%s: NULL backend cannot be removed",
VRT_fail(ctx, "%s: None backend cannot be removed",
VRT_BACKEND_string(vd->dir));
return;
}
......@@ -176,7 +187,7 @@ vdir_any_healthy(VRT_CTX, struct vdir *vd, VCL_TIME *changed)
unsigned retval = 0;
VCL_BACKEND be;
unsigned u;
double c;
vtim_real c;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
CHECK_OBJ_NOTNULL(vd, VDIR_MAGIC);
......@@ -196,19 +207,152 @@ vdir_any_healthy(VRT_CTX, struct vdir *vd, VCL_TIME *changed)
return (retval);
}
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");
}
/*
* 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;
}
static unsigned
vdir_pick_by_weight(const struct vdir *vd, double w,
const struct vbitmap *blacklist)
vdir_pick_by_weight(const struct vdir *vd, double w)
{
const struct vbitmap *healthy = vd->healthy;
double a = 0.0;
VCL_BACKEND be = NULL;
unsigned u;
AN(blacklist);
AN(healthy);
for (u = 0; u < vd->n_backend; u++) {
be = vd->backend[u];
CHECK_OBJ_NOTNULL(be, DIRECTOR_MAGIC);
if (vbit_test(blacklist, u))
if (! vbit_test(healthy, u))
continue;
a += vd->weight[u];
if (w < a)
......@@ -221,21 +365,14 @@ VCL_BACKEND
vdir_pick_be(VRT_CTX, struct vdir *vd, double w)
{
unsigned u;
double tw = 0.0;
VCL_BACKEND be = NULL;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
CHECK_OBJ_NOTNULL(vd, VDIR_MAGIC);
vdir_wrlock(vd);
for (u = 0; u < vd->n_backend; u++) {
if (VRT_Healthy(ctx, vd->backend[u], 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);
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);
......
......@@ -4,6 +4,8 @@
*
* Author: Poul-Henning Kamp <phk@FreeBSD.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
......@@ -31,14 +33,15 @@ struct vbitmap;
struct vdir {
unsigned magic;
#define VDIR_MAGIC 0x99f4b726
pthread_rwlock_t mtx;
unsigned n_backend;
unsigned l_backend;
unsigned n_healthy;
pthread_rwlock_t mtx;
VCL_BACKEND *backend;
double *weight;
double total_weight;
VCL_BACKEND dir;
struct vbitmap *vbm;
struct vbitmap *healthy;
};
void vdir_new(VRT_CTX, struct vdir **vdp, const char *vcl_name,
......@@ -50,4 +53,6 @@ void vdir_unlock(struct vdir *vd);
void vdir_add_backend(VRT_CTX, struct vdir *, VCL_BACKEND, double weight);
void vdir_remove_backend(VRT_CTX, struct vdir *, VCL_BACKEND, unsigned *cur);
VCL_BOOL vdir_any_healthy(VRT_CTX, struct vdir *, VCL_TIME *);
void vdir_list(VRT_CTX, struct vdir *, struct vsb *, int, int, int);
void vdir_update_health(VRT_CTX, struct vdir *);
VCL_BACKEND vdir_pick_be(VRT_CTX, struct vdir *, double w);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment