[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