r3084 - trunk/varnish-cache/bin/varnishd
phk at projects.linpro.no
phk at projects.linpro.no
Tue Aug 12 14:57:00 CEST 2008
Author: phk
Date: 2008-08-12 14:57:00 +0200 (Tue, 12 Aug 2008)
New Revision: 3084
Modified:
trunk/varnish-cache/bin/varnishd/cache.h
trunk/varnish-cache/bin/varnishd/cache_backend_poll.c
trunk/varnish-cache/bin/varnishd/cache_main.c
Log:
Snapshot the backend polling code without the advanced math.
Presently we only record th state of the last 64 tries to poll the
backend in a shift register, which can be show with the interrim
CLI command "debug.health":
Health stats for backend b0
Oldest __________________________________________________ Newest
4444444444444444444444444444444444444444444444444444444444444444 Good IPv4
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX Good Xmit
SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS Good Shut
RR-RR-R-RRRR---RR-RR-R-R-R-R-R-RRRR-RR-----RR--RRRR--RRR-R-----R Good Recv
More to follow.
Modified: trunk/varnish-cache/bin/varnishd/cache.h
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache.h 2008-08-12 12:28:38 UTC (rev 3083)
+++ trunk/varnish-cache/bin/varnishd/cache.h 2008-08-12 12:57:00 UTC (rev 3084)
@@ -427,6 +427,9 @@
void VBE_SelectBackend(struct sess *sp);
struct backend *VBE_AddBackend(struct cli *cli, const struct vrt_backend *vb);
+/* cache_backend_poll.c */
+void VBP_Init(void);
+
/* cache_ban.c */
int BAN_Add(struct cli *cli, const char *regexp, int hash);
void BAN_Init(void);
Modified: trunk/varnish-cache/bin/varnishd/cache_backend_poll.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache_backend_poll.c 2008-08-12 12:28:38 UTC (rev 3083)
+++ trunk/varnish-cache/bin/varnishd/cache_backend_poll.c 2008-08-12 12:57:00 UTC (rev 3084)
@@ -40,6 +40,7 @@
#include "config.h"
#include <stdio.h>
+#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
@@ -48,37 +49,276 @@
#include <sys/socket.h>
#include "shmlog.h"
+#include "cli_priv.h"
#include "cache.h"
#include "vrt.h"
#include "cache_backend.h"
+static MTX vbp_mtx;
+
struct vbp_target {
unsigned magic;
#define VBP_TARGET_MAGIC 0x6b7cb656
struct backend *backend;
+ struct vrt_backend_probe probe;
struct workreq wrq;
int stop;
+ int req_len;
+
+ /* Collected statistics */
+#define BITMAP(n, c, t, b) uint64_t n;
+#include "cache_backend_poll.h"
+#undef BITMAP
+
+ VTAILQ_ENTRY(vbp_target) list;
};
+static VTAILQ_HEAD(, vbp_target) vbp_list =
+ VTAILQ_HEAD_INITIALIZER(vbp_list);
+
+static char default_request[] =
+ "GET / HTTP/1.1\r\n"
+ "Connection: close\r\n"
+ "\r\n";
+
static void
+dsleep(double t)
+{
+ if (t > 10.0)
+ (void)sleep((int)round(t));
+ else
+ (void)usleep((int)round(t * 1e6));
+}
+
+/*--------------------------------------------------------------------
+ * Poke one backend, once, but possibly at both IPv4 and IPv6 addresses.
+ *
+ * We do deliberately not use the stuff in cache_backend.c, because we
+ * want to measure the backends response without local distractions.
+ */
+
+static int
+vbp_connect(int pf, const struct sockaddr *sa, socklen_t salen, int tmo)
+{
+ int s, i;
+
+ s = socket(pf, SOCK_STREAM, 0);
+ if (s < 0)
+ return (s);
+
+ i = TCP_connect(s, sa, salen, tmo);
+ if (i == 0)
+ return (s);
+ TCP_close(&s);
+ return (-1);
+}
+
+static int
+vbp_poke(struct vbp_target *vt)
+{
+ int s, tmo, i;
+ double t_start, t_now, t_end, rlen;
+ struct backend *bp;
+ char buf[8192];
+ struct pollfd pfda[1], *pfd = pfda;
+
+ bp = vt->backend;
+ CHECK_OBJ_NOTNULL(bp, BACKEND_MAGIC);
+
+ t_start = t_now = TIM_real();
+ t_end = t_start + vt->probe.timeout;
+ tmo = (int)round((t_end - t_now) * 1e3);
+
+ s = -1;
+ if (params->prefer_ipv6 && bp->ipv6 != NULL) {
+ s = vbp_connect(PF_INET6, bp->ipv6, bp->ipv6len, tmo);
+ t_now = TIM_real();
+ tmo = (int)round((t_end - t_now) * 1e3);
+ if (s >= 0)
+ vt->good_ipv6 |= 1;
+ }
+ if (tmo > 0 && s < 0 && bp->ipv4 != NULL) {
+ s = vbp_connect(PF_INET, bp->ipv4, bp->ipv4len, tmo);
+ t_now = TIM_real();
+ tmo = (int)round((t_end - t_now) * 1e3);
+ if (s >= 0)
+ vt->good_ipv4 |= 1;
+ }
+ if (tmo > 0 && s < 0 && bp->ipv6 != NULL) {
+ s = vbp_connect(PF_INET6, bp->ipv6, bp->ipv6len, tmo);
+ t_now = TIM_real();
+ tmo = (int)round((t_end - t_now) * 1e3);
+ if (s >= 0)
+ vt->good_ipv6 |= 1;
+ }
+ if (s < 0) {
+ /* Got no connection: failed */
+ return (0);
+ }
+
+ i = write(s, vt->probe.request, vt->req_len);
+ if (i != vt->req_len) {
+ if (i < 0)
+ vt->err_xmit |= 1;
+ TCP_close(&s);
+ return (0);
+ }
+ vt->good_xmit |= 1;
+ i = shutdown(s, SHUT_WR);
+ if (i != 0) {
+ vt->err_shut |= 1;
+ TCP_close(&s);
+ return (0);
+ }
+ vt->good_shut |= 1;
+
+ t_now = TIM_real();
+ tmo = (int)round((t_end - t_now) * 1e3);
+ if (tmo < 0) {
+ TCP_close(&s);
+ return (0);
+ }
+
+ pfd->fd = s;
+ rlen = 0;
+ do {
+ pfd->events = POLLIN;
+ pfd->revents = 0;
+ tmo = (int)round((t_end - t_now) * 1e3);
+ if (tmo > 0)
+ i = poll(pfd, 1, tmo);
+ if (i == 0 || tmo <= 0) {
+ TCP_close(&s);
+ return (0);
+ }
+ i = read(s, buf, sizeof buf);
+ rlen += i;
+ } while (i > 0);
+
+ if (i < 0) {
+ vt->err_recv |= 1;
+ TCP_close(&s);
+ return (0);
+ }
+
+ TCP_close(&s);
+ t_now = TIM_real();
+ vt->good_recv |= 1;
+ return (1);
+}
+
+/*--------------------------------------------------------------------
+ * One thread per backend to be poked.
+ */
+
+static void
vbp_wrk_poll_backend(struct worker *w, void *priv)
{
struct vbp_target *vt;
(void)w;
- CAST_OBJ_NOTNULL(vt, priv, VBP_TARGET_MAGIC);
THR_SetName("backend poll");
+ CAST_OBJ_NOTNULL(vt, priv, VBP_TARGET_MAGIC);
+
+ LOCK(&vbp_mtx);
+ VTAILQ_INSERT_TAIL(&vbp_list, vt, list);
+ UNLOCK(&vbp_mtx);
+
+ /* Establish defaults (XXX: Should they go in VCC instead ?) */
+ if (vt->probe.request == NULL)
+ vt->probe.request = default_request;
+ if (vt->probe.timeout == 0.0)
+ vt->probe.timeout = 2.0;
+ if (vt->probe.interval == 0.0)
+ vt->probe.timeout = 5.0;
+
+ printf("Probe(\"%s\", %g, %g)\n",
+ vt->probe.request,
+ vt->probe.timeout,
+ vt->probe.interval);
+
+ vt->req_len = strlen(vt->probe.request);
+
+ /*lint -e{525} indent */
while (!vt->stop) {
- printf("Poke backend %s\n", vt->backend->vcl_name);
- sleep(1);
+#define BITMAP(n, c, t, b) vt->n <<= 1;
+#include "cache_backend_poll.h"
+#undef BITMAP
+ vbp_poke(vt);
+ dsleep(vt->probe.interval);
}
+ LOCK(&vbp_mtx);
+ VTAILQ_REMOVE(&vbp_list, vt, list);
+ UNLOCK(&vbp_mtx);
vt->backend->probe = NULL;
FREE_OBJ(vt);
THR_SetName("cache-worker");
}
+/*--------------------------------------------------------------------
+ * Cli functions
+ */
+
+static void
+vbp_bitmap(struct cli *cli, const char *s, uint64_t map, const char *lbl)
+{
+ int i;
+ uint64_t u = (1ULL << 63);
+
+ for (i = 0; i < 64; i++) {
+ if (map & u)
+ cli_out(cli, s);
+ else
+ cli_out(cli, "-");
+ map <<= 1;
+ }
+ cli_out(cli, " %s\n", lbl);
+}
+
+/*lint -e{506} constant value boolean */
+/*lint -e{774} constant value boolean */
+static void
+vbp_health_one(struct cli *cli, struct vbp_target *vt)
+{
+
+ cli_out(cli, "Health stats for backend %s\n",
+ vt->backend->vcl_name);
+ cli_out(cli,
+ "Oldest ______________________"
+ "____________________________ Newest\n");
+
+#define BITMAP(n, c, t, b) \
+ if ((vt->n != 0) || (b)) \
+ vbp_bitmap(cli, (c), vt->n, (t));
+#include "cache_backend_poll.h"
+#undef BITMAP
+}
+
+static void
+vbp_health(struct cli *cli, const char * const *av, void *priv)
+{
+ struct vbp_target *vt;
+
+ (void)av;
+ (void)priv;
+
+ VTAILQ_FOREACH(vt, &vbp_list, list)
+ vbp_health_one(cli, vt);
+}
+
+static struct cli_proto debug_cmds[] = {
+ { "debug.health", "debug.health",
+ "\tDump backend health stuff\n",
+ 0, 0, vbp_health },
+ { NULL }
+};
+
+/*--------------------------------------------------------------------
+ * Start/Stop called from cache_backend_cfg.c
+ */
+
void
VBP_Start(struct backend *b, struct vrt_backend_probe const *p)
{
@@ -86,13 +326,14 @@
ASSERT_CLI();
- /* Is probing even configured ? */
- if (p->request == NULL)
- return;
-
ALLOC_OBJ(vt, VBP_TARGET_MAGIC);
AN(vt);
+ if (!memcmp(&vt->probe, p, sizeof *p)) {
+ FREE_OBJ(vt);
+ return;
+ }
vt->backend = b;
+ vt->probe = *p;
b->probe = vt;
vt->wrq.func = vbp_wrk_poll_backend;
@@ -111,3 +352,16 @@
return;
b->probe->stop = 1;
}
+
+/*--------------------------------------------------------------------
+ * Initialize the backend probe subsystem
+ */
+
+void
+VBP_Init(void)
+{
+
+ MTX_INIT(&vbp_mtx);
+
+ CLI_AddFuncs(DEBUG_CLI, debug_cmds);
+}
Modified: trunk/varnish-cache/bin/varnishd/cache_main.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache_main.c 2008-08-12 12:28:38 UTC (rev 3083)
+++ trunk/varnish-cache/bin/varnishd/cache_main.c 2008-08-12 12:57:00 UTC (rev 3084)
@@ -112,6 +112,7 @@
SES_Init();
VBE_Init();
+ VBP_Init();
VSL_Init();
WRK_Init();
More information about the varnish-commit
mailing list