[4.1] c8bfb6e Introduce a `vxid` LHS for VSL queries

Martin Blix Grydeland martin at varnish-software.com
Thu Apr 6 14:56:05 CEST 2017


commit c8bfb6e92b3281e3005cf3283454ce52b41c6c3f
Author: Dridi Boukelmoune <dridi.boukelmoune at gmail.com>
Date:   Thu Feb 2 11:04:37 2017 +0100

    Introduce a `vxid` LHS for VSL queries
    
    It shares a lot of parsing infrastructure with log records, but doesn't
    support the taglist syntax. Only a verbatim `vxid` token can be used as
    the LHS, and only integer operators are supported.

diff --git a/bin/varnishtest/tests/b00050.vtc b/bin/varnishtest/tests/b00050.vtc
new file mode 100644
index 0000000..399df82
--- /dev/null
+++ b/bin/varnishtest/tests/b00050.vtc
@@ -0,0 +1,61 @@
+varnishtest "VXID log filtering"
+
+server s1 {
+	rxreq
+	txresp
+} -start
+
+varnish v1 -arg "-p thread_pools=1" -vcl+backend { } -start
+
+logexpect l1 -v v1 -q "vxid == 1001" {
+	expect 0 1001 Begin "req 1000 rxreq"
+} -start
+
+client c1 {
+	txreq
+	rxresp
+} -run
+
+logexpect -wait
+
+# vxid only supports integer operations
+
+shell -err -expect "Expected vxid operator got '~'" {
+	varnishlog -n ${v1_name} -d -q 'vxid ~ 1001'
+}
+
+shell -err -expect "Expected vxid operator got '!~'" {
+	varnishlog -n ${v1_name} -d -q 'vxid !~ 1001'
+}
+
+shell -err -expect "Expected vxid operator got 'eq'" {
+	varnishlog -n ${v1_name} -d -q 'vxid eq 1001'
+}
+
+shell -err -expect "Expected vxid operator got 'ne'" {
+	varnishlog -n ${v1_name} -d -q 'vxid ne 1001'
+}
+
+# vxid only supports integer operands
+
+shell -err -expect "Expected integer got '1001.5'" {
+	varnishlog -n ${v1_name} -d -q 'vxid != 1001.5'
+}
+
+# vxid doesn't support taglist selection
+
+shell -err -expect "Unexpected taglist selection for vxid" {
+	varnishlog -n ${v1_name} -d -q 'vxid[1] >= 1001'
+}
+
+shell -err -expect "Unexpected taglist selection for vxid" {
+	varnishlog -n ${v1_name} -d -q '{1}vxid <= 1001'
+}
+
+shell -err -expect "Unexpected taglist selection for vxid" {
+	varnishlog -n ${v1_name} -d -q 'vxid,Link > 1001'
+}
+
+shell -err -expect "Unexpected taglist selection for vxid" {
+	varnishlog -n ${v1_name} -d -q 'vxid,vxid < 1001'
+}
diff --git a/lib/libvarnishapi/generate.py b/lib/libvarnishapi/generate.py
index 00205cd..053a1e4 100755
--- a/lib/libvarnishapi/generate.py
+++ b/lib/libvarnishapi/generate.py
@@ -71,6 +71,7 @@ tokens = {
 
 	# Special
 	"T_TRUE":       None,
+	"VXID":         "vxid",
 }
 
 #######################################################################
diff --git a/lib/libvarnishapi/vsl_query.c b/lib/libvarnishapi/vsl_query.c
index 0159429..5f6a84d 100644
--- a/lib/libvarnishapi/vsl_query.c
+++ b/lib/libvarnishapi/vsl_query.c
@@ -74,6 +74,48 @@ struct vslq_query {
 	}
 
 static int
+vslq_test_vxid(const struct vex *vex, const struct VSL_transaction *trans)
+{
+	const struct vex_rhs *rhs;
+
+	AN(vex);
+	AN(trans);
+
+	rhs = vex->rhs;
+	CHECK_OBJ_NOTNULL(rhs, VEX_RHS_MAGIC);
+
+	/* Prepare */
+	switch (vex->tok) {
+	case T_EQ:		/* == */
+	case T_NEQ:		/* != */
+	case '<':
+	case '>':
+	case T_LEQ:		/* <= */
+	case T_GEQ:		/* >= */
+		if (rhs->type != VEX_INT)
+			WRONG("Wrong RHS type for vxid");
+		/* FALLTHROUGH */
+	default:
+		break;
+	}
+
+	/* Compare */
+	switch (vex->tok) {
+	#define VXID_TEST_NUMOP(OP) return (trans->vxid OP rhs->val_int);
+	case T_EQ:	VXID_TEST_NUMOP(==);
+	case T_NEQ:	VXID_TEST_NUMOP(!=);
+	case '<':	VXID_TEST_NUMOP(<);
+	case '>':	VXID_TEST_NUMOP(>);
+	case T_LEQ:	VXID_TEST_NUMOP(<=);
+	case T_GEQ:	VXID_TEST_NUMOP(>=);
+	#undef VXID_TEST_NUMOP
+	default:	WRONG("Bad vxid expression token");
+	}
+
+	NEEDLESS(return (0));
+}
+
+static int
 vslq_test_rec(const struct vex *vex, const struct VSLC_ptr *rec)
 {
 	const struct vex_rhs *rhs;
@@ -226,6 +268,17 @@ vslq_test(const struct vex *vex, struct VSL_transaction * const ptrans[])
 	CHECK_OBJ_NOTNULL(vex, VEX_MAGIC);
 	CHECK_OBJ_NOTNULL(vex->lhs, VEX_LHS_MAGIC);
 	AN(vex->lhs->tags);
+	assert(vex->lhs->vxid <= 1);
+
+	if (vex->lhs->vxid) {
+		AZ(vex->lhs->taglist);
+		for (t = ptrans[0]; t != NULL; t = *++ptrans)
+			if (vslq_test_vxid(vex, t))
+				return (1);
+		return (0);
+	}
+
+	AN(vex->lhs->taglist);
 
 	for (t = ptrans[0]; t != NULL; t = *++ptrans) {
 		if (vex->lhs->level >= 0) {
diff --git a/lib/libvarnishapi/vxp.h b/lib/libvarnishapi/vxp.h
index afed0d0..c7a0981 100644
--- a/lib/libvarnishapi/vxp.h
+++ b/lib/libvarnishapi/vxp.h
@@ -86,6 +86,8 @@ struct vex_lhs {
 	int			field;
 	int			level;
 	int			level_pm;
+	unsigned		taglist;
+	unsigned		vxid;
 };
 
 enum vex_rhs_e {
diff --git a/lib/libvarnishapi/vxp_parse.c b/lib/libvarnishapi/vxp_parse.c
index 7ec8865..0e32afc 100644
--- a/lib/libvarnishapi/vxp_parse.c
+++ b/lib/libvarnishapi/vxp_parse.c
@@ -112,14 +112,19 @@ vxp_expr_lhs(struct vxp *vxp, struct vex_lhs **plhs)
 
 	while (1) {
 		/* The tags this expression applies to */
-		if (vxp->t->tok != VAL) {
+		if (vxp->t->tok == VXID) {
+			(*plhs)->vxid++;
+			i = 0;
+		} else if (vxp->t->tok != VAL) {
 			VSB_printf(vxp->sb, "Expected VSL tag name got '%.*s' ",
 			    PF(vxp->t));
 			vxp_ErrWhere(vxp, vxp->t, -1);
 			return;
+		} else {
+			(*plhs)->taglist++;
+			i = VSL_Glob2Tags(vxp->t->dec, -1, vsl_vbm_bitset,
+			    (*plhs)->tags);
 		}
-		i = VSL_Glob2Tags(vxp->t->dec, -1, vsl_vbm_bitset,
-		    (*plhs)->tags);
 		if (i == -1) {
 			VSB_printf(vxp->sb, "Tag name matches zero tags ");
 			vxp_ErrWhere(vxp, vxp->t, -1);
@@ -135,7 +140,7 @@ vxp_expr_lhs(struct vxp *vxp, struct vex_lhs **plhs)
 			vxp_ErrWhere(vxp, vxp->t, -1);
 			return;
 		}
-		assert(i > 0);
+		assert(i > 0 || vxp->t->tok == VXID);
 		vxp_NextToken(vxp);
 		if (vxp->t->tok != ',')
 			break;
@@ -177,10 +182,20 @@ vxp_expr_lhs(struct vxp *vxp, struct vex_lhs **plhs)
 		ExpectErr(vxp, ']');
 		vxp_NextToken(vxp);
 	}
+
+	if ((*plhs)->vxid == 0)
+		return;
+
+	if ((*plhs)->vxid > 1 || (*plhs)->level >= 0 ||
+	    (*plhs)->field > 0 || (*plhs)->prefixlen > 0 ||
+	    (*plhs)->taglist > 0) {
+		VSB_printf(vxp->sb, "Unexpected taglist selection for vxid ");
+		vxp_ErrWhere(vxp, vxp->t, -1);
+	}
 }
 
 static void
-vxp_expr_num(struct vxp *vxp, struct vex_rhs **prhs)
+vxp_expr_num(struct vxp *vxp, struct vex_rhs **prhs, int vxid)
 {
 	char *endptr;
 
@@ -213,6 +228,12 @@ vxp_expr_num(struct vxp *vxp, struct vex_rhs **prhs)
 			return;
 		}
 	}
+	if (vxid && (*prhs)->type != VEX_INT) {
+		VSB_printf(vxp->sb, "Expected integer got '%.*s' ",
+		    PF(vxp->t));
+		vxp_ErrWhere(vxp, vxp->t, 0);
+		return;
+	}
 	vxp_NextToken(vxp);
 }
 
@@ -269,6 +290,28 @@ vxp_expr_regex(struct vxp *vxp, struct vex_rhs **prhs)
 	vxp_NextToken(vxp);
 }
 
+static void
+vxp_vxid_cmp(struct vxp *vxp)
+{
+
+	switch (vxp->t->tok) {
+	/* Valid operators */
+	case T_EQ:		/* == */
+	case '<':		/* < */
+	case '>':		/* > */
+	case T_GEQ:		/* >= */
+	case T_LEQ:		/* <= */
+	case T_NEQ:		/* != */
+		break;
+
+	/* Error */
+	default:
+		VSB_printf(vxp->sb, "Expected vxid operator got '%.*s' ",
+		    PF(vxp->t));
+		vxp_ErrWhere(vxp, vxp->t, -1);
+	}
+}
+
 /*
  * SYNTAX:
  *   expr_cmp:
@@ -287,6 +330,11 @@ vxp_expr_cmp(struct vxp *vxp, struct vex **pvex)
 	vxp_expr_lhs(vxp, &(*pvex)->lhs);
 	ERRCHK(vxp);
 
+	if ((*pvex)->lhs->vxid) {
+		vxp_vxid_cmp(vxp);
+		ERRCHK(vxp);
+	}
+
 	/* Test operator */
 	switch (vxp->t->tok) {
 
@@ -333,7 +381,7 @@ vxp_expr_cmp(struct vxp *vxp, struct vex **pvex)
 	case T_GEQ:		/* >= */
 	case T_LEQ:		/* <= */
 	case T_NEQ:		/* != */
-		vxp_expr_num(vxp, &(*pvex)->rhs);
+		vxp_expr_num(vxp, &(*pvex)->rhs, (*pvex)->lhs->vxid);
 		break;
 	case T_SEQ:		/* eq */
 	case T_SNEQ:		/* ne */



More information about the varnish-commit mailing list