Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
libvmod-selector
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
uplex-varnish
libvmod-selector
Commits
70a7fcc9
Commit
70a7fcc9
authored
Jul 07, 2018
by
Geoff Simmons
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add the .create_stats() method.
parent
cacd60f1
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
473 additions
and
7 deletions
+473
-7
.gitignore
.gitignore
+1
-0
README.rst
README.rst
+25
-0
configure.ac
configure.ac
+1
-0
Makefile.am
src/Makefile.am
+9
-2
patricia.c
src/patricia.c
+47
-0
patricia.h
src/patricia.h
+14
-0
selector.vsc
src/selector.vsc
+48
-0
stats.vtc
src/tests/stats.vtc
+199
-0
vmod_selector.c
src/vmod_selector.c
+109
-5
vmod_selector.vcc
src/vmod_selector.vcc
+20
-0
No files found.
.gitignore
View file @
70a7fcc9
...
...
@@ -32,6 +32,7 @@ Makefile.in
/src/vcc_if.c
/src/vcc_if.h
/src/vmod_*rst
/src/VSC_selector.*
/src/tests/*.log
/src/tests/*.trs
...
...
README.rst
View file @
70a7fcc9
...
...
@@ -26,6 +26,7 @@ CONTENTS
* :ref:`obj_set`
* :ref:`func_set.add`
* :ref:`func_set.backend`
* :ref:`func_set.create_stats`
* :ref:`func_set.debug`
* :ref:`func_set.element`
* :ref:`func_set.hasprefix`
...
...
@@ -310,6 +311,25 @@ Example::
}
.. _func_set.create_stats:
VOID xset.create_stats()
------------------------
Creates statistics counters for this object that are displayed by
tools such as varnishstat(1).
Example::
sub vcl_init {
new myset = selector.set();
set.add("foo");
set.add("bar");
set.add("baz");
set.create_stats();
}
.. _func_set.debug:
STRING xset.debug()
...
...
@@ -332,6 +352,11 @@ Example::
std.log("Using VMOD selector version: " + selector.version());
STATISTICS
==========
XXX ...
REQUIREMENTS
============
...
...
configure.ac
View file @
70a7fcc9
...
...
@@ -39,6 +39,7 @@ m4_ifndef([VARNISH_PREREQ], AC_MSG_ERROR([Need varnish.m4 -- see README.rst]))
VARNISH_PREREQ([6.0.0])
VARNISH_VMODS([selector])
VARNISH_COUNTERS([selector])
VMOD_TESTS="$(cd $srcdir/src && echo tests/*.vtc)"
AC_SUBST(VMOD_TESTS)
...
...
src/Makefile.am
View file @
70a7fcc9
...
...
@@ -12,10 +12,14 @@ libvmod_selector_la_SOURCES = \
nodist_libvmod_selector_la_SOURCES
=
\
vcc_if.c
\
vcc_if.h
vcc_if.h
\
VSC_selector.c
\
VSC_selector.h
dist_man_MANS
=
vmod_selector.3
@BUILD_VSC_SELECTOR@
vmod_selector.c patricia.c
:
patricia.h
vmod_selector.lo
:
$(nodist_libvmod_selector_la_SOURCES)
...
...
@@ -43,6 +47,7 @@ TESTS = @VMOD_TESTS@
EXTRA_DIST
=
\
vmod_selector.vcc
\
selector.vsc
\
$(VMOD_TESTS)
CLEANFILES
=
\
...
...
@@ -50,4 +55,6 @@ CLEANFILES = \
$(builddir)
/vcc_if.h
\
$(builddir)
/vmod_selector.rst
\
$(builddir)
/vmod_selector.man.rst
\
$(builddir)
/vmod_selector.3
$(builddir)
/vmod_selector.3
\
$(builddir)
/VSC_selector.c
\
$(builddir)
/VSC_selector.h
src/patricia.c
View file @
70a7fcc9
...
...
@@ -364,3 +364,50 @@ PT_Dump(struct pt_y *root, char **strings)
VSB_finish
(
sb
);
return
(
sb
);
}
void
pt_stats
(
const
struct
pt_y
*
const
restrict
y
,
char
*
const
restrict
*
const
restrict
strings
,
struct
pt_stats
*
const
restrict
stats
,
unsigned
depth
)
{
if
(
y
==
NULL
)
return
;
CHECK_OBJ
(
y
,
PT_Y_MAGIC
);
depth
++
;
stats
->
nodes
++
;
if
(
strings
[
y
->
idx
][
y
->
off
+
y
->
len
]
==
'\0'
)
{
if
(
depth
<
stats
->
dmin
)
stats
->
dmin
=
depth
;
if
(
depth
>
stats
->
dmax
)
stats
->
dmax
=
depth
;
stats
->
davg
+=
(
depth
-
stats
->
davg
)
/
(
stats
->
terms
+
1
.);
stats
->
terms
++
;
}
if
(
y
->
leaf
[
0
]
==
NULL
&&
y
->
leaf
[
1
]
==
NULL
)
{
stats
->
leaves
++
;
return
;
}
pt_stats
(
y
->
leaf
[
0
],
strings
,
stats
,
depth
);
pt_stats
(
y
->
leaf
[
1
],
strings
,
stats
,
depth
);
}
void
PT_Stats
(
const
struct
pt_y
*
const
restrict
root
,
char
*
const
restrict
*
const
restrict
strings
,
struct
pt_stats
*
const
restrict
stats
)
{
CHECK_OBJ_NOTNULL
(
stats
,
PT_STATS_MAGIC
);
stats
->
nodes
=
0
;
stats
->
leaves
=
0
;
stats
->
terms
=
0
;
stats
->
dmin
=
UINT64_MAX
;
stats
->
dmax
=
0
;
stats
->
davg
=
0
.;
pt_stats
(
root
,
strings
,
stats
,
0
);
}
src/patricia.h
View file @
70a7fcc9
...
...
@@ -45,6 +45,17 @@ struct match_data {
unsigned
max
;
};
struct
pt_stats
{
unsigned
magic
;
#define PT_STATS_MAGIC 0xf1c1114e
uint64_t
nodes
;
uint64_t
leaves
;
uint64_t
terms
;
uint64_t
dmin
;
uint64_t
dmax
;
double
davg
;
};
void
PT_Init
(
void
);
int
PT_Inited
(
void
);
int
PT_Insert
(
struct
pt_y
*
*
restrict
root
,
unsigned
idx
,
...
...
@@ -56,5 +67,8 @@ int PT_Prefixes(const struct pt_y * const restrict root,
char
*
const
restrict
*
const
restrict
strings
,
const
char
*
const
restrict
subject
,
struct
match_data
*
const
restrict
match
);
void
PT_Stats
(
const
struct
pt_y
*
const
restrict
root
,
char
*
const
restrict
*
const
restrict
strings
,
struct
pt_stats
*
const
restrict
stats
);
void
PT_Free
(
struct
pt_y
*
y
);
struct
vsb
*
PT_Dump
(
struct
pt_y
*
root
,
char
**
strings
);
src/selector.vsc
0 → 100644
View file @
70a7fcc9
..
This is *NOT* a RST file but the syntax has been chosen so
that it may become an RST file at some later date.
.. varnish_vsc_begin:: selector
:oneliner: VMOD selector set object stats
:order: 90
.. varnish_vsc:: elements
:type: gauge
:oneliner: Elements
Number of elements (strings) in the set.
.. varnish_vsc:: nodes
:type: gauge
:oneliner: Nodes
Total number of nodes in the internal data structure.
.. varnish_vsc:: leaves
:type: gauge
:oneliner: Leaf nodes
Number of leaf nodes in the internal data structure.
.. varnish_vsc:: dmin
:type: gauge
:oneliner: Minimum terminating node depth
Minimum depth of a node in the internal data structure at
which an element of the set may be found.
.. varnish_vsc:: dmax
:type: gauge
:oneliner: Maximum terminating node depth
Maximum depth of a node in the internal data structure at
which an element of the set may be found.
.. varnish_vsc:: davg
:type: gauge
:oneliner: Average terminating node depth
Average depth of nodes in the internal data structure at which
an element of the set may be found, rounded to the nearest integer.
.. varnish_vsc_end:: selector
src/tests/stats.vtc
0 → 100644
View file @
70a7fcc9
# looks like -*- vcl -*-
varnishtest ".create_stats() method"
varnish v1 -vcl {
import ${vmod_selector};
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new s = selector.set();
s.add("foo");
s.add("bar");
s.add("baz");
s.add("quux");
s.create_stats();
}
} -start
varnish v1 -vsc SELECTOR.*
varnish v1 -expect SELECTOR.vcl1.s.elements == 4
varnish v1 -expect SELECTOR.vcl1.s.nodes > 0
varnish v1 -expect SELECTOR.vcl1.s.leaves <= 4
varnish v1 -expect SELECTOR.vcl1.s.dmin > 0
varnish v1 -expect SELECTOR.vcl1.s.dmax > 0
varnish v1 -expect SELECTOR.vcl1.s.davg > 0
varnish v1 -vcl {
import ${vmod_selector};
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new p = selector.set();
p.add("foo");
p.add("foobar");
p.add("foobarbaz");
p.add("foobarbazquux");
p.create_stats();
# No .create_stats() call.
new n = selector.set();
n.add("foo");
n.add("bar");
n.add("baz");
n.add("quux");
}
}
# Stats for vc1.s and vcl2.p appear, but not for vcl2.n.
varnish v1 -vsc SELECTOR.*
varnish v1 -expect SELECTOR.vcl2.p.elements == 4
varnish v1 -expect SELECTOR.vcl2.p.nodes > 0
varnish v1 -expect SELECTOR.vcl2.p.leaves <= 4
varnish v1 -expect SELECTOR.vcl2.p.dmin > 0
varnish v1 -expect SELECTOR.vcl2.p.dmax > 0
varnish v1 -expect SELECTOR.vcl2.p.davg > 0
# When vcl1 is set to cold, stats for vcl2.p but not vcl1.s appear.
varnish v1 -cliok "vcl.state vcl1 cold"
varnish v1 -vsc SELECTOR.*
# When vcl1 is set back to warm, stats for vcl2.p and vcl1.s appear.
varnish v1 -cliok "vcl.state vcl1 warm"
varnish v1 -vsc SELECTOR.*
varnish v1 -expect SELECTOR.vcl1.s.elements == 4
varnish v1 -expect SELECTOR.vcl1.s.nodes > 0
varnish v1 -expect SELECTOR.vcl1.s.leaves <= 4
varnish v1 -expect SELECTOR.vcl1.s.dmin > 0
varnish v1 -expect SELECTOR.vcl1.s.dmax > 0
varnish v1 -expect SELECTOR.vcl1.s.davg > 0
# The same 100 words from /usr/share/dict/words as in match.vtc
varnish v1 -vcl {
import ${vmod_selector};
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new words = selector.set();
words.add("trustee's");
words.add("Marc");
words.add("remover's");
words.add("brutishly");
words.add("Blythe");
words.add("tastier");
words.add("backed");
words.add("rain");
words.add("banality");
words.add("unstrung");
words.add("barnyards");
words.add("paperweight");
words.add("Kazan's");
words.add("fanfares");
words.add("Donny's");
words.add("faze");
words.add("redefinition");
words.add("Schulz");
words.add("Lanai's");
words.add("bastions");
words.add("kicker's");
words.add("Denny");
words.add("disgraced");
words.add("downswings");
words.add("pullback's");
words.add("Gregorio's");
words.add("spillways");
words.add("puller");
words.add("basilica's");
words.add("serviced");
words.add("insistently");
words.add("Frisian's");
words.add("question");
words.add("mien");
words.add("rockier");
words.add("indivisible");
words.add("megahertzes");
words.add("Oldfield's");
words.add("accusatory");
words.add("Mabel");
words.add("magnetize");
words.add("Philly");
words.add("Katheryn's");
words.add("policewoman's");
words.add("ashcan");
words.add("deviousness's");
words.add("suspends");
words.add("furnishings");
words.add("compiler's");
words.add("Claudio");
words.add("zestfully");
words.add("laughter's");
words.add("Manuel");
words.add("palatal's");
words.add("eminent");
words.add("strongboxes");
words.add("pinafores");
words.add("Glendale");
words.add("dethronement");
words.add("chlorinate");
words.add("Souths");
words.add("tilting");
words.add("trenched");
words.add("run");
words.add("initialized");
words.add("breakfast");
words.add("winning's");
words.add("mediates");
words.add("triads");
words.add("verdict");
words.add("Irish");
words.add("Jeremy");
words.add("handouts");
words.add("Billie's");
words.add("romanticist's");
words.add("descanting");
words.add("bidders");
words.add("play");
words.add("navigability's");
words.add("leapfrogging");
words.add("Libby");
words.add("smelter's");
words.add("hermit's");
words.add("Tabatha's");
words.add("churlish");
words.add("spuriousness's");
words.add("Salish's");
words.add("Curry");
words.add("hula");
words.add("ruse's");
words.add("bureaucratic");
words.add("Moseley");
words.add("confluence");
words.add("inseams");
words.add("producers");
words.add("cozier");
words.add("augur's");
words.add("electrode's");
words.add("disposition");
words.add("Rena's");
words.create_stats();
}
}
varnish v1 -expect SELECTOR.vcl3.words.elements == 100
varnish v1 -expect SELECTOR.vcl3.words.nodes > 0
varnish v1 -expect SELECTOR.vcl3.words.leaves <= 100
varnish v1 -expect SELECTOR.vcl3.words.dmin > 0
varnish v1 -expect SELECTOR.vcl3.words.dmax > 0
varnish v1 -expect SELECTOR.vcl3.words.davg > 0
varnish v1 -cliok "vcl.state vcl1 cold"
varnish v1 -cli "vcl.discard vcl1"
# No stats for vcl1 appear after discard.
varnish v1 -vsc SELECTOR.vc1.*
# The same for vcl2 after discard.
varnish v1 -cli "vcl.discard vcl2"
varnish v1 -vsc SELECTOR.vc2.*
src/vmod_selector.c
View file @
70a7fcc9
...
...
@@ -43,6 +43,7 @@
#include "vcc_if.h"
#include "patricia.h"
#include "VSC_selector.h"
#define VFAIL(ctx, fmt, ...) \
VRT_fail((ctx), "vmod selector failure: " fmt, __VA_ARGS__)
...
...
@@ -89,17 +90,67 @@ struct vmod_selector_set {
VCL_BOOL
case_sensitive
;
};
struct
vsc_entry
{
unsigned
magic
;
#define VMOD_SELECTOR_VSC_MAGIC 0x4b99b64a
VSLIST_ENTRY
(
vsc_entry
)
list
;
struct
vsc_seg
*
vsc_seg
;
};
VSLIST_HEAD
(
vsc_head
,
vsc_entry
);
/* Event function */
int
event
(
VRT_CTX
,
struct
vmod_priv
*
priv
,
enum
vcl_event_e
e
)
{
(
void
)
ctx
;
(
void
)
priv
;
struct
vsc_head
*
vsc_head
;
struct
vsc_entry
*
vsc_entry
;
if
(
e
==
VCL_EVENT_LOAD
&&
!
PT_Inited
())
PT_Init
();
return
0
;
ASSERT_CLI
();
CHECK_OBJ_NOTNULL
(
ctx
,
VRT_CTX_MAGIC
);
AN
(
priv
);
if
(
priv
->
priv
==
NULL
)
{
vsc_head
=
malloc
(
sizeof
(
*
vsc_head
));
AN
(
vsc_head
);
priv
->
priv
=
vsc_head
;
VSLIST_INIT
(
vsc_head
);
}
else
vsc_head
=
priv
->
priv
;
switch
(
e
)
{
case
VCL_EVENT_LOAD
:
if
(
!
PT_Inited
())
PT_Init
();
break
;
case
VCL_EVENT_DISCARD
:
while
(
!
VSLIST_EMPTY
(
vsc_head
))
{
vsc_entry
=
VSLIST_FIRST
(
vsc_head
);
CHECK_OBJ_NOTNULL
(
vsc_entry
,
VMOD_SELECTOR_VSC_MAGIC
);
VSC_selector_Destroy
(
&
vsc_entry
->
vsc_seg
);
VSLIST_REMOVE_HEAD
(
vsc_head
,
list
);
FREE_OBJ
(
vsc_entry
);
}
free
(
vsc_head
);
break
;
case
VCL_EVENT_WARM
:
VSLIST_FOREACH
(
vsc_entry
,
vsc_head
,
list
)
{
CHECK_OBJ_NOTNULL
(
vsc_entry
,
VMOD_SELECTOR_VSC_MAGIC
);
VRT_VSC_Reveal
(
vsc_entry
->
vsc_seg
);
}
break
;
case
VCL_EVENT_COLD
:
VSLIST_FOREACH
(
vsc_entry
,
vsc_head
,
list
)
{
CHECK_OBJ_NOTNULL
(
vsc_entry
,
VMOD_SELECTOR_VSC_MAGIC
);
VRT_VSC_Hide
(
vsc_entry
->
vsc_seg
);
}
break
;
default:
WRONG
(
"illegal event enum"
);
}
return
0
;
}
/* Object regex */
...
...
@@ -695,6 +746,59 @@ vmod_set_debug(VRT_CTX, struct vmod_selector_set *set)
return
output
;
}
VCL_VOID
vmod_set_create_stats
(
VRT_CTX
,
struct
vmod_selector_set
*
set
,
struct
vmod_priv
*
priv
)
{
struct
pt_stats
stats
=
{
.
magic
=
PT_STATS_MAGIC
};
struct
VSC_selector
*
vsc
;
struct
vsc_seg
*
vsc_seg
;
struct
vsc_head
*
vsc_head
;
struct
vsc_entry
*
vsc_entry
;
CHECK_OBJ_NOTNULL
(
ctx
,
VRT_CTX_MAGIC
);
CHECK_OBJ_NOTNULL
(
set
,
VMOD_SELECTOR_SET_MAGIC
);
if
((
ctx
->
method
&
VCL_MET_INIT
)
==
0
)
{
VFAIL
(
ctx
,
"%s.add() may only be called in vcl_init"
,
set
->
vcl_name
);
return
;
}
AN
(
priv
);
AN
(
priv
->
priv
);
vsc_head
=
priv
->
priv
;
if
(
set
->
nmembers
==
0
)
memset
(
&
stats
,
0
,
sizeof
(
stats
));
else
{
char
**
members
=
set
->
members
;
if
(
!
set
->
case_sensitive
)
members
=
set
->
lomembers
;
AN
(
members
);
PT_Stats
(
set
->
origo
,
members
,
&
stats
);
assert
(
stats
.
terms
==
set
->
nmembers
);
assert
(
stats
.
leaves
<=
stats
.
terms
);
assert
(
stats
.
terms
<=
stats
.
nodes
);
assert
(
stats
.
dmin
<=
stats
.
dmax
);
assert
(
stats
.
dmin
<=
stats
.
davg
);
assert
(
stats
.
davg
<=
stats
.
dmax
);
}
vsc
=
VSC_selector_New
(
NULL
,
&
vsc_seg
,
"%s.%s"
,
VCL_Name
(
ctx
->
vcl
),
set
->
vcl_name
);
vsc
->
elements
=
set
->
nmembers
;
vsc
->
nodes
=
stats
.
nodes
;
vsc
->
leaves
=
stats
.
leaves
;
vsc
->
dmin
=
stats
.
dmin
;
vsc
->
dmax
=
stats
.
dmax
;
vsc
->
davg
=
(
uint64_t
)(
stats
.
davg
+
0
.
5
);
ALLOC_OBJ
(
vsc_entry
,
VMOD_SELECTOR_VSC_MAGIC
);
AN
(
vsc_entry
);
vsc_entry
->
vsc_seg
=
vsc_seg
;
VSLIST_INSERT_HEAD
(
vsc_head
,
vsc_entry
,
list
);
}
VCL_STRING
vmod_version
(
VRT_CTX
)
{
...
...
src/vmod_selector.vcc
View file @
70a7fcc9
...
...
@@ -177,6 +177,21 @@ Example::
# ...
}
$Method VOID .create_stats(PRIV_VCL)
Creates statistics counters for this object that are displayed by
tools such as varnishstat(1).
Example::
sub vcl_init {
new myset = selector.set();
set.add("foo");
set.add("bar");
set.add("baz");
set.create_stats();
}
$Method STRING .debug()
Intentionally not documented.
...
...
@@ -189,6 +204,11 @@ Example::
std.log("Using VMOD selector version: " + selector.version());
STATISTICS
==========
XXX ...
REQUIREMENTS
============
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment