[master] 7c513b1 Polish the new BAN code

Poul-Henning Kamp phk at varnish-cache.org
Sat May 14 19:53:33 CEST 2011


commit 7c513b1033d5f6d15f4280e0bcc6d54344035670
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Sat May 14 17:53:18 2011 +0000

    Polish the new BAN code

diff --git a/bin/varnishd/cache_ban.c b/bin/varnishd/cache_ban.c
index 3c58afd..3593490 100644
--- a/bin/varnishd/cache_ban.c
+++ b/bin/varnishd/cache_ban.c
@@ -69,6 +69,14 @@ struct ban {
 	uint8_t			*spec;
 };
 
+struct ban_test {
+	uint8_t			arg1;
+	const char		*arg1_spec;
+	uint8_t			oper;
+	const char		*arg2;
+	const void		*arg2_spec;
+};
+
 static VTAILQ_HEAD(banhead_s,ban) ban_head = VTAILQ_HEAD_INITIALIZER(ban_head);
 static struct lock ban_mtx;
 static struct ban *ban_magic;
@@ -76,20 +84,6 @@ static pthread_t ban_thread;
 static struct ban * volatile ban_start;
 
 /*--------------------------------------------------------------------
- * Variables we can purge on
- */
-
-static const struct pvar {
-	const char		*name;
-	unsigned		flag;
-} pvars[] = {
-#define PVAR(a, b, c)	{ (a), (b) },
-#include "ban_vars.h"
-#undef PVAR
-	{ 0, 0}
-};
-
-/*--------------------------------------------------------------------
  * BAN string magic markers
  */
 
@@ -103,6 +97,21 @@ static const struct pvar {
 #define BAN_ARG_OBJHTTP	0x1a
 
 /*--------------------------------------------------------------------
+ * Variables we can purge on
+ */
+
+static const struct pvar {
+	const char		*name;
+	unsigned		flag;
+	uint8_t			tag;
+} pvars[] = {
+#define PVAR(a, b, c)	{ (a), (b), (c) },
+#include "ban_vars.h"
+#undef PVAR
+	{ 0, 0, 0}
+};
+
+/*--------------------------------------------------------------------
  * Storage handling of bans
  */
 
@@ -156,8 +165,8 @@ ban_CheckLast(void)
 }
 
 /*--------------------------------------------------------------------
- * Get & Release a tail reference, used to hold the list stable while
- * persistent storage loads.
+ * Get & Release a tail reference, used to hold the list stable for
+ * traversals etc.
  */
 
 struct ban *
@@ -237,6 +246,26 @@ ban_get_lump(const uint8_t **bs)
 }
 
 /*--------------------------------------------------------------------
+ * Pick a test apart from a spec string
+ */
+
+static void
+ban_iter(const uint8_t **bs, struct ban_test *bt)
+{
+
+	memset(bt, 0, sizeof *bt);
+	bt->arg1 = *(*bs)++;
+	if (bt->arg1 == BAN_ARG_REQHTTP || bt->arg1 == BAN_ARG_OBJHTTP) {
+		bt->arg1_spec = (char *)*bs;
+		(*bs) += (*bs)[0] + 2;
+	}
+	bt->arg2 = ban_get_lump(bs);
+	bt->oper = *(*bs)++;
+	if (bt->oper == BAN_OPER_MATCH || bt->oper == BAN_OPER_NMATCH) 
+		bt->arg2_spec = ban_get_lump(bs);
+}
+
+/*--------------------------------------------------------------------
  * Parse and add a http argument specification
  * Output something which HTTP_GetHdr understands
  */
@@ -303,36 +332,25 @@ BAN_AddTest(struct cli *cli, struct ban *b, const char *a1, const char *a2,
 	if (pv->flag & PVAR_REQ)
 		b->flags |= BAN_F_REQ;
 
-	if (pv->flag == PVAR_REQ) {
-		vsb_putc(b->vsb, BAN_ARG_URL);
-	} else if (pv->flag == (PVAR_REQ|PVAR_HTTP)) {
-		vsb_putc(b->vsb, BAN_ARG_REQHTTP);
+	vsb_putc(b->vsb, pv->tag);
+	if (pv->flag & PVAR_HTTP)
 		ban_parse_http(b, a1 + strlen(pv->name));
-	} else if (pv->flag == PVAR_HTTP) {
-		vsb_putc(b->vsb, BAN_ARG_OBJHTTP);
-		ban_parse_http(b, a1 + strlen(pv->name));
-	} else {
-		INCOMPL();
-	}
 
+	ban_add_lump(b, a3, strlen(a3) + 1);
 	if (!strcmp(a2, "~")) {
 		vsb_putc(b->vsb, BAN_OPER_MATCH);
-		ban_add_lump(b, a3, strlen(a3) + 1);
 		i = ban_parse_regexp(cli, b, a3);
 		if (i)
 			return (i);
 	} else if (!strcmp(a2, "!~")) {
 		vsb_putc(b->vsb, BAN_OPER_NMATCH);
-		ban_add_lump(b, a3, strlen(a3) + 1);
 		i = ban_parse_regexp(cli, b, a3);
 		if (i)
 			return (i);
 	} else if (!strcmp(a2, "==")) {
 		vsb_putc(b->vsb, BAN_OPER_EQ);
-		ban_add_lump(b, a3, strlen(a3) + 1);
 	} else if (!strcmp(a2, "!=")) {
 		vsb_putc(b->vsb, BAN_OPER_NEQ);
-		ban_add_lump(b, a3, strlen(a3) + 1);
 	} else {
 		cli_out(cli,
 		    "expected conditional (~, !~, == or !=) got \"%s\"", a2);
@@ -367,18 +385,16 @@ BAN_Insert(struct ban *b)
 	XXXAN(b->spec);
 
 	t0 = TIM_real();
-	assert(sizeof t0 == 8);
 	memcpy(b->spec, &t0, sizeof t0);
 
 	vbe32enc(b->spec + 8, ln + 12);
 
 	memcpy(b->spec + 12, vsb_data(b->vsb), ln);
+	ln += 12;
 
 	vsb_delete(b->vsb);
 	b->vsb = NULL;
 
-	ln += 12;
-
 	Lck_Lock(&ban_mtx);
 	VTAILQ_INSERT_HEAD(&ban_head, b, list);
 	ban_start = b;
@@ -499,29 +515,22 @@ BAN_Reload(const uint8_t *ban, unsigned len)
 {
 	struct ban *b, *b2;
 	int gone = 0;
-	double t0, t1, t2;
-	unsigned ln;
+	double t0, t1, t2 = 9e99;
 
 	ASSERT_CLI();
 
 	t0 = ban_time(ban);
-	ln = ban_len(ban);
-	assert(ln == len);
-
-	t2 = 9e99;
+	assert(len == ban_len(ban));
 	VTAILQ_FOREACH(b, &ban_head, list) {
 		t1 = ban_time(b->spec);
 		assert (t1 < t2);
 		t2 = t1;
-		
-		if (!memcmp(b->spec + 8, ban + 8, ln - 8)) {
-			if (t1 == t0)
-				return;
-			if (t1 > t0)
-				gone |= BAN_F_GONE;
-		}
+		if (t1 == t0)
+			return;
 		if (t1 < t0)
 			break;
+		if (!memcmp(b->spec + 8, ban + 8, len - 8))
+			gone |= BAN_F_GONE;
 	}
 
 	VSC_main->n_ban++;
@@ -529,9 +538,9 @@ BAN_Reload(const uint8_t *ban, unsigned len)
 
 	b2 = BAN_New();
 	AN(b2);
-	b2->spec = malloc(ln);
+	b2->spec = malloc(len);
 	AN(b2->spec);
-	memcpy(b2->spec, ban, ln);
+	memcpy(b2->spec, ban, len);
 	b2->flags |= gone;
 	if (b == NULL)
 		VTAILQ_INSERT_TAIL(&ban_head, b2, list);
@@ -542,15 +551,9 @@ BAN_Reload(const uint8_t *ban, unsigned len)
 	for (b = VTAILQ_NEXT(b2, list); b != NULL; b = VTAILQ_NEXT(b, list)) {
 		if (b->flags & BAN_F_GONE)
 			continue;
-		if (!memcmp(b->spec + 8, ban + 8, ln - 8))
+		if (!memcmp(b->spec + 8, ban + 8, len - 8))
 			b->flags |= BAN_F_GONE;
 	}
-	t2 = 9e99;
-	VTAILQ_FOREACH(b, &ban_head, list) {
-		t1 = ban_time(b->spec);
-		assert (t1 < t2);
-		t2 = t1;
-	}
 }
 
 /*--------------------------------------------------------------------
@@ -578,6 +581,10 @@ BAN_Compile(void)
 
 	ASSERT_CLI();
 
+	/*
+	 * XXX: we need to derive the BAN_F_REQ flag from all the
+	 * XXX: all the loaded bans
+	 */
 	SMP_NewBan(ban_magic->spec, ban_len(ban_magic->spec));
 	ban_start = VTAILQ_FIRST(&ban_head);
 }
@@ -590,65 +597,52 @@ static int
 ban_evaluate(const uint8_t *bs, const struct http *objhttp,
     const struct http *reqhttp, unsigned *tests)
 {
+	struct ban_test bt;
 	const uint8_t *be;
-	uint8_t op;
 	char *arg1;
-	const void *arg2;
-	int i;
-
-	(void)objhttp;
-	(void)reqhttp;
 
 	be = bs + ban_len(bs);
 	bs += 12;
 	while (bs < be) {
 		(*tests)++;
+		ban_iter(&bs, &bt);
 		arg1 = NULL;
-		switch (*bs) {
+		switch (bt.arg1) {
 		case BAN_ARG_URL:
 			arg1 = reqhttp->hd[HTTP_HDR_URL].b;
-			bs++;
 			break;
 		case BAN_ARG_REQHTTP:
-			(void)http_GetHdr(reqhttp,
-			    (const char *)(bs + 1), &arg1);
-			bs += bs[1] + 3;
+			(void)http_GetHdr(reqhttp, bt.arg1_spec, &arg1);
 			break;
 		case BAN_ARG_OBJHTTP:
-			(void)http_GetHdr(objhttp,
-			    (const char *)(bs + 1), &arg1);
-			bs += bs[1] + 3;
+			(void)http_GetHdr(objhttp, bt.arg1_spec, &arg1);
 			break;
 		default:
 			INCOMPL();
 		}
-		op = *bs++;
 
-		arg2 = ban_get_lump(&bs);
-
-		if (op == BAN_OPER_EQ) {
-			if (arg1 == NULL || strcmp(arg1, arg2))
+		switch (bt.oper) {
+		case BAN_OPER_EQ:
+			if (arg1 == NULL || strcmp(arg1, bt.arg2))
 				return (0);
-			continue;
-		} else if (op == BAN_OPER_NEQ) {
-			if (arg1 != NULL && !strcmp(arg1, arg2))
+			break;
+		case BAN_OPER_NEQ:
+			if (arg1 != NULL && !strcmp(arg1, bt.arg2))
 				return (0);
-			continue;
-		}
-
-		arg2 = ban_get_lump(&bs);
-
-		if (op == BAN_OPER_MATCH) {
-			i = pcre_exec(arg2, NULL, arg1, strlen(arg1),
-			    0, 0, NULL, 0);
-			if (i < 0)
+			break;
+		case BAN_OPER_MATCH:
+			if (arg1 == NULL ||
+			    pcre_exec(bt.arg2_spec, NULL, arg1, strlen(arg1),
+			    0, 0, NULL, 0) < 0)
 				return (0);
-		} else if (op == BAN_OPER_NMATCH) {
-			i = pcre_exec(arg2, NULL, arg1, strlen(arg1),
-			    0, 0, NULL, 0);
-			if (i >= 0)
+			break;
+		case BAN_OPER_NMATCH:
+			if (arg1 != NULL &&
+			    pcre_exec(bt.arg2_spec, NULL, arg1, strlen(arg1),
+			    0, 0, NULL, 0) >= 0)
 				return (0);
-		} else {
+			break;
+		default:
 			INCOMPL();
 		}
 	}
@@ -897,54 +891,40 @@ ccf_ban_url(struct cli *cli, const char * const *av, void *priv)
 static void
 ban_render(struct cli *cli, const uint8_t *bs)
 {
+	struct ban_test bt;
 	const uint8_t *be;
-	const void *arg2;
-	uint8_t op;
 
 	be = bs + ban_len(bs);
 	bs += 12;
 	while (bs < be) {
-		switch (*bs) {
+		ban_iter(&bs, &bt);
+		switch (bt.arg1) {
 		case BAN_ARG_URL:
 			cli_out(cli, "req.url");
-			bs++;
 			break;
 		case BAN_ARG_REQHTTP:
-			cli_out(cli, "req.http.%.*s", bs[1] - 1, bs + 2);
-			bs += bs[1] + 3;
+			cli_out(cli, "req.http.%.*s",
+			    bt.arg1_spec[0] - 1, bt.arg1_spec + 1);
 			break;
 		case BAN_ARG_OBJHTTP:
-			cli_out(cli, "obj.http.%.*s", bs[1] - 1, bs + 2);
-			bs += bs[1] + 3;
+			cli_out(cli, "obj.http.%.*s",
+			    bt.arg1_spec[0] - 1, bt.arg1_spec + 1);
 			break;
 		default:
 			INCOMPL();
 		}
-		op = *bs++;
-		arg2 = ban_get_lump(&bs);
-		switch (op) {
-		case BAN_OPER_EQ:
-			cli_out(cli, " == ");
-			break;
-		case BAN_OPER_NEQ:
-			cli_out(cli, " != ");
-			break;
-		case BAN_OPER_MATCH:
-			cli_out(cli, " ~ ");
-			(void)ban_get_lump(&bs);
-			break;
-		case BAN_OPER_NMATCH:
-			cli_out(cli, " !~ ");
-			(void)ban_get_lump(&bs);
-			break;
+		switch (bt.oper) {
+		case BAN_OPER_EQ:	cli_out(cli, " == "); break;
+		case BAN_OPER_NEQ:	cli_out(cli, " != "); break;
+		case BAN_OPER_MATCH:	cli_out(cli, " ~ "); break;
+		case BAN_OPER_NMATCH:	cli_out(cli, " !~ "); break;
 		default:
 			INCOMPL();
 		}
-		cli_out(cli, "%s", arg2);
+		cli_out(cli, "%s", bt.arg2);
 		if (bs < be)
 			cli_out(cli, " && ");
 	}
-	cli_out(cli, "\n");
 }
 
 static void
@@ -965,6 +945,7 @@ ccf_ban_list(struct cli *cli, const char * const *av, void *priv)
 		    bl == b ? b->refcount - 1 : b->refcount,
 		    b->flags & BAN_F_GONE ? "G" : " ");
 		ban_render(cli, b->spec);
+		cli_out(cli, "\n");
 	}
 
 	BAN_TailDeref(&bl);
diff --git a/include/ban_vars.h b/include/ban_vars.h
index 2ba0930..df94d15 100644
--- a/include/ban_vars.h
+++ b/include/ban_vars.h
@@ -32,6 +32,6 @@
 #define PVAR_HTTP	1
 #define PVAR_REQ	2
 
-PVAR("req.url",		PVAR_REQ,		ban_cond_url)
-PVAR("req.http.",	PVAR_REQ|PVAR_HTTP,	ban_cond_req_http)
-PVAR("obj.http.",	PVAR_HTTP,		ban_cond_obj_http)
+PVAR("req.url",		PVAR_REQ,		BAN_ARG_URL)
+PVAR("req.http.",	PVAR_REQ|PVAR_HTTP,	BAN_ARG_REQHTTP)
+PVAR("obj.http.",	PVAR_HTTP,		BAN_ARG_OBJHTTP)



More information about the varnish-commit mailing list