Commit 749b0a4a authored by Geoff Simmons's avatar Geoff Simmons

Set compilation and stats creation now done by vcl_init PRIV_TASK fini.

.compile() is still legal, but unnecessary and will be deprecated.

.create_stats() just sets a flag in the PRIV_TASK that stats should
be created by the fini method. If .compile() is called, .create_stats()
is now legal before or after .compile().
parent 12889755
......@@ -13,7 +13,6 @@ varnish v1 -vcl {
t.add("baz");
t.add("quux");
t.add("foobar");
t.compile();
}
sub vcl_recv {
......@@ -69,7 +68,6 @@ varnish v1 -vcl {
t.add("études");
t.add("étude's");
t.add("étude");
t.compile();
}
sub vcl_recv {
......@@ -202,7 +200,6 @@ varnish v1 -vcl {
s.add("electrode's");
s.add("disposition");
s.add("Rena's");
s.compile();
}
sub vcl_recv {
......@@ -829,7 +826,6 @@ varnish v1 -vcl {
sub vcl_init {
new s = selector.set();
s.add("foo");
s.compile();
}
sub vcl_recv {
......@@ -894,7 +890,6 @@ varnish v1 -vcl {
sub vcl_init {
new s = selector.set();
s.add("foo");
s.compile();
}
sub vcl_recv {
......@@ -921,18 +916,29 @@ logexpect l1 -v v1 -d 1 -g vxid -q "VCL_Error" {
expect * = End
} -run
varnish v1 -errvcl {vmod selector failure: t.compile(): "foo" added more than once} {
# .compile() is still legal, but unnecessary and deprecated.
varnish v1 -vcl {
import ${vmod_selector};
backend b None;
sub vcl_init {
new t = selector.set();
t.add("foo");
t.add("foo");
t.compile();
}
}
varnish v1 -errvcl {vmod selector failure: t set initialization: "foo" added more than once} {
import ${vmod_selector};
backend b None;
sub vcl_init {
new t = selector.set();
t.add("foo");
t.add("foo");
}
}
varnish v1 -errvcl {vmod selector failure: s.compile(): set was already compiled} {
import ${vmod_selector};
backend b None;
......@@ -990,6 +996,7 @@ logexpect l1 -wait
logexpect l1 -v v1 -d 0 -g raw -q "vxid == 0 and VCL_Error" {
expect 0 0 VCL_Error {^VCL \S+ vmod selector n\.compile\(\): no entries were added, nothing to compile, n\.match\(\) will always fail}
expect 0 0 VCL_Error {^VCL \S+ vmod selector s set initialization: no entries were added, nothing to compile, s\.match\(\) will always fail}
} -start
varnish v1 -vcl {
......@@ -999,13 +1006,11 @@ varnish v1 -vcl {
sub vcl_init {
new t = selector.set();
t.add("foo");
t.compile();
new n = selector.set();
n.compile();
new s = selector.set();
s.add("foo");
}
sub vcl_recv {
......@@ -1020,9 +1025,6 @@ varnish v1 -vcl {
if (req.http.Nil) {
set resp.http.Nil = n.match("foo");
}
if (req.http.Not-Compiled) {
set resp.http.Not-Compiled = s.match("foo");
}
return (deliver);
}
}
......@@ -1054,11 +1056,6 @@ logexpect l1 -v v1 -d 0 -g vxid -q "VCL_Error" {
expect * = VCL_Error {^vmod selector failure: n\.match\(\): no entries were added$}
expect * = VCL_return fail
expect * = End
expect 0 * Begin req
expect * = VCL_Error {^vmod selector failure: s\.match\(\): set was not compiled$}
expect * = VCL_return fail
expect * = End
} -start
client c1 {
......@@ -1073,11 +1070,6 @@ client c1 {
expect_close
} -run
client c1 {
txreq -hdr "Not-Compiled: not-compiled"
expect_close
} -run
logexpect l1 -wait
# Call vcl.discard to exercise set object finalization.
......
......@@ -13,7 +13,6 @@ varnish v1 -vcl {
s.add("bar");
s.add("baz");
s.add("quux");
s.compile();
}
sub vcl_recv {
......@@ -146,7 +145,6 @@ varnish v1 -vcl {
s.add("foobarbaz");
s.add("foobar");
s.add("foo");
s.compile();
}
sub vcl_recv {
......@@ -327,7 +325,6 @@ varnish v1 -vcl {
s.add("foobar");
s.add("foobarbaz");
s.add("foobarbazquux");
s.compile();
}
sub vcl_recv {
......@@ -584,6 +581,7 @@ varnish v1 -vcl {
s.add("plaintiffs"); # 75
s.add("plainer"); # 76
s.add("plainest"); # 77
# .compile() still legal, but unnecessary and deprecated.
s.compile();
}
......@@ -1466,13 +1464,8 @@ varnish v1 -vcl {
sub vcl_init {
new t = selector.set();
t.add("foo");
t.compile();
new n = selector.set();
n.compile();
new c = selector.set();
c.add("bar");
}
sub vcl_recv {
......@@ -1484,9 +1477,6 @@ varnish v1 -vcl {
if (req.http.Nil) {
set resp.http.Nil = n.hasprefix("foo");
}
if (req.http.Not-Compiled) {
set resp.http.Not-Compiled = c.hasprefix("bar");
}
return (deliver);
}
}
......@@ -1511,11 +1501,6 @@ logexpect l1 -v v1 -d 0 -g vxid -q "VCL_Error" {
expect * = VCL_Error {^vmod selector failure: n\.hasprefix\(\): no entries were added$}
expect * = VCL_return fail
expect * = End
expect 0 * Begin req
expect * = VCL_Error {^vmod selector failure: c\.hasprefix\(\): set was not compiled$}
expect * = VCL_return fail
expect * = End
} -start
client c1 {
......@@ -1523,11 +1508,6 @@ client c1 {
expect_close
} -run
client c1 {
txreq -hdr "Not-Compiled: not-compiled"
expect_close
} -run
logexpect l1 -wait
varnish v1 -vcl {
......@@ -1538,7 +1518,6 @@ varnish v1 -vcl {
sub vcl_init {
new s = selector.set();
s.add("foo");
s.compile();
}
sub vcl_recv {
......
......@@ -12,7 +12,6 @@ varnish v1 -vcl {
s.add("bar");
s.add("baz");
s.add("quux");
s.compile();
s.create_stats();
}
} -start
......@@ -55,7 +54,6 @@ varnish v1 -vcl {
p.add("foobar");
p.add("foobarbaz");
p.add("foobarbazquux");
p.compile();
p.create_stats();
# No .create_stats() call.
......@@ -68,7 +66,6 @@ varnish v1 -vcl {
# Calling .create_stats() on an empty set is
# pointless, but not an error.
new e = selector.set();
e.compile();
e.create_stats();
}
}
......@@ -303,7 +300,7 @@ 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.*
varnish v1 -vsc SELECTOR.vcl1.*
# The same for vcl2 after discard.
varnish v1 -cli "vcl.discard vcl2"
......@@ -341,14 +338,73 @@ logexpect l1 -v v1 -d 1 -g vxid -q "VCL_Error" {
expect * = End
} -run
varnish v1 -errvcl {vmod selector failure: s.create_stats(): set was not compiled} {
# .compile() still legal, although unnecessary and deprecated.
# Any order before or after .create_stats() is legal.
varnish v1 -vcl {
import ${vmod_selector};
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new s = selector.set();
s.add("foo");
s.create_stats();
s.compile();
s.create_stats();
new t = selector.set();
t.add("bar");
t.create_stats();
t.compile();
}
}
varnish v1 -expect SELECTOR.vcl5.s.elements == 1
varnish v1 -expect SELECTOR.vcl5.s.setsz > 0
varnish v1 -expect SELECTOR.vcl5.s.minlen == 3
varnish v1 -expect SELECTOR.vcl5.s.maxlen == 3
varnish v1 -expect SELECTOR.vcl5.s.trie_nodes > 0
varnish v1 -expect SELECTOR.vcl5.s.trie_nodesz > 0
varnish v1 -expect SELECTOR.vcl5.s.trie_leaves <= 1
varnish v1 -expect SELECTOR.vcl5.s.trie_depth_min > 0
varnish v1 -expect SELECTOR.vcl5.s.trie_depth_max > 0
varnish v1 -expect SELECTOR.vcl5.s.trie_depth_avg > 0
varnish v1 -expect SELECTOR.vcl5.s.trie_fanout_min >= 0
varnish v1 -expect SELECTOR.vcl5.s.trie_fanout_max >= 0
varnish v1 -expect SELECTOR.vcl5.s.trie_fanout_avg >= 0
varnish v1 -expect SELECTOR.vcl5.s.hash_buckets >= 1
varnish v1 -expect SELECTOR.vcl5.s.hash_collisions >= 0
varnish v1 -expect SELECTOR.vcl5.s.hash_keylen > 0
varnish v1 -expect SELECTOR.vcl5.s.hash_h2_buckets_min >= 0
varnish v1 -expect SELECTOR.vcl5.s.hash_h2_buckets_max >= 0
varnish v1 -expect SELECTOR.vcl5.s.hash_h2_buckets_avg >= 0
varnish v1 -expect SELECTOR.vcl5.s.hash_h2_strings_min >= 0
varnish v1 -expect SELECTOR.vcl5.s.hash_h2_strings_max >= 0
varnish v1 -expect SELECTOR.vcl5.s.hash_h2_strings_avg >= 0
varnish v1 -expect SELECTOR.vcl5.s.hash_h2_klen_min >= 0
varnish v1 -expect SELECTOR.vcl5.s.hash_h2_klen_max >= 0
varnish v1 -expect SELECTOR.vcl5.s.hash_h2_klen_avg >= 0
varnish v1 -expect SELECTOR.vcl5.t.elements == 1
varnish v1 -expect SELECTOR.vcl5.t.setsz > 0
varnish v1 -expect SELECTOR.vcl5.t.minlen == 3
varnish v1 -expect SELECTOR.vcl5.t.maxlen == 3
varnish v1 -expect SELECTOR.vcl5.t.trie_nodes > 0
varnish v1 -expect SELECTOR.vcl5.t.trie_nodesz > 0
varnish v1 -expect SELECTOR.vcl5.t.trie_leaves <= 1
varnish v1 -expect SELECTOR.vcl5.t.trie_depth_min > 0
varnish v1 -expect SELECTOR.vcl5.t.trie_depth_max > 0
varnish v1 -expect SELECTOR.vcl5.t.trie_depth_avg > 0
varnish v1 -expect SELECTOR.vcl5.t.trie_fanout_min >= 0
varnish v1 -expect SELECTOR.vcl5.t.trie_fanout_max >= 0
varnish v1 -expect SELECTOR.vcl5.t.trie_fanout_avg >= 0
varnish v1 -expect SELECTOR.vcl5.t.hash_buckets >= 1
varnish v1 -expect SELECTOR.vcl5.t.hash_collisions >= 0
varnish v1 -expect SELECTOR.vcl5.t.hash_keylen > 0
varnish v1 -expect SELECTOR.vcl5.t.hash_h2_buckets_min >= 0
varnish v1 -expect SELECTOR.vcl5.t.hash_h2_buckets_max >= 0
varnish v1 -expect SELECTOR.vcl5.t.hash_h2_buckets_avg >= 0
varnish v1 -expect SELECTOR.vcl5.t.hash_h2_strings_min >= 0
varnish v1 -expect SELECTOR.vcl5.t.hash_h2_strings_max >= 0
varnish v1 -expect SELECTOR.vcl5.t.hash_h2_strings_avg >= 0
varnish v1 -expect SELECTOR.vcl5.t.hash_h2_klen_min >= 0
varnish v1 -expect SELECTOR.vcl5.t.hash_h2_klen_max >= 0
varnish v1 -expect SELECTOR.vcl5.t.hash_h2_klen_avg >= 0
......@@ -103,6 +103,17 @@ struct vsc_entry {
VSLIST_HEAD(vsc_head, vsc_entry);
struct set_init_task {
unsigned magic;
#define SET_INIT_TASK_MAGIC 0xeae8c785
VSLIST_ENTRY(set_init_task) list;
struct vmod_selector_set *set;
struct vsc_head *vsc_head;
unsigned create_stats;
};
VSLIST_HEAD(set_init_head, set_init_task);
/* Event function */
int
......@@ -160,16 +171,222 @@ vmod_event(VRT_CTX, struct vmod_priv *priv, enum vcl_event_e e)
/* Object regex */
struct memberidx {
char *member;
unsigned n;
};
static int
cmp(const void *a, const void *b)
{
const struct memberidx *aa = a, *bb = b;
return( strcmp(aa->member, bb->member) );
}
static int
compile(VRT_CTX, struct VPFX(selector_set) *set, const char *method)
{
char **members;
struct memberidx *idx;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
CHECK_OBJ_NOTNULL(set, VMOD_SELECTOR_SET_MAGIC);
members = set->members;
if (!set->case_sensitive)
members = set->lomembers;
if (members == NULL || set->nmembers == 0) {
CHECK_OBJ_NOTNULL(ctx->msg, VSB_MAGIC);
VSL(SLT_VCL_Error, 0, "VCL %s vmod selector %s%s: "
"no entries were added, nothing to compile, "
"%s.match() will always fail\n", VCL_Name(ctx->vcl),
set->vcl_name, method, set->vcl_name);
return 0;
}
idx = malloc(set->nmembers * sizeof(*idx));
if (idx == NULL) {
VFAIL(ctx, "%s%s: out of memory", set->vcl_name, method);
return -1;
}
for (unsigned i = 0; i < set->nmembers; i++) {
idx[i].n = i;
idx[i].member = members[i];
}
qsort(idx, set->nmembers, sizeof(*idx), cmp);
for (unsigned i = 0; i < set->nmembers; i++) {
errno = 0;
if (QP_Insert(&set->origo, idx[i].n, members,
set->allow_overlaps) != 0) {
if (errno == EINVAL)
VFAIL(ctx, "%s%s: \"%s\" added more than once",
set->vcl_name, method, members[i]);
else if (errno == EPERM)
VFAIL(ctx, "%s%s: allow_overlaps is false but "
"strings with common prefixes were added",
set->vcl_name, method);
else
VFAIL(ctx, "%s%s member \"%s\" failed: %s",
set->vcl_name, method, members[i],
strerror(errno));
free(idx);
return -1;
}
}
free(idx);
errno = 0;
if ((set->hash = PH_Generate(members, set->nmembers)) == NULL) {
if (errno == ERANGE)
VFAIL(ctx, "%s%s: too many strings in the set",
set->vcl_name, method);
else
VFAIL(ctx, "%s%s failed: %s", set->vcl_name, method,
strerror(errno));
}
return 0;
}
static void
create_stats(VRT_CTX, struct vmod_selector_set *set, struct vsc_head *vsc_head)
{
struct qp_stats qp_stats = { .magic = QP_STATS_MAGIC };
struct ph_stats ph_stats = { .magic = PH_STATS_MAGIC };
struct VSC_selector *vsc;
struct vsc_seg *vsc_seg;
struct vsc_entry *vsc_entry;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
CHECK_OBJ_NOTNULL(set, VMOD_SELECTOR_SET_MAGIC);
AN(vsc_head);
if (set->nmembers == 0) {
memset(&qp_stats, 0, sizeof(qp_stats));
memset(&ph_stats, 0, sizeof(ph_stats));
}
else if (set->origo == NULL) {
VFAIL(ctx, "%s.create_stats(): set was not compiled",
set->vcl_name);
return;
}
else {
char **members = set->members;
if (!set->case_sensitive)
members = set->lomembers;
AN(members);
QP_Stats(set->origo, members, &qp_stats);
assert(qp_stats.terms == set->nmembers);
assert(qp_stats.leaves <= qp_stats.terms);
assert(qp_stats.terms <= qp_stats.nodes);
assert(qp_stats.dmin <= qp_stats.dmax);
assert(qp_stats.dmin <= qp_stats.davg);
assert(qp_stats.davg <= qp_stats.dmax);
assert(qp_stats.fmin <= qp_stats.fmax);
assert(qp_stats.fmin <= qp_stats.favg);
assert(qp_stats.favg <= qp_stats.fmax);
assert(qp_stats.nodesz > 0);
PH_Stats(set->hash, members, &ph_stats);
assert(ph_stats.buckets >= set->nmembers);
assert(ph_stats.collisions <= ph_stats.buckets);
assert(ph_stats.minlen <= ph_stats.maxlen);
assert(ph_stats.klen == ((ph_stats.maxlen + 7) / 8) * 2);
assert(ph_stats.h2buckets_min <= ph_stats.h2buckets_max);
assert(ph_stats.h2buckets_min <= ph_stats.h2buckets_avg);
assert(ph_stats.h2buckets_avg <= ph_stats.h2buckets_max);
assert(ph_stats.h2strings_min <= ph_stats.h2strings_max);
assert(ph_stats.h2strings_min <= ph_stats.h2strings_avg);
assert(ph_stats.h2strings_avg <= ph_stats.h2strings_max);
assert(ph_stats.h2klen_min <= ph_stats.h2klen_max);
assert(ph_stats.h2klen_min <= ph_stats.h2klen_avg);
assert(ph_stats.h2klen_avg <= ph_stats.h2klen_max);
}
vsc = VSC_selector_New(NULL, &vsc_seg, "%s.%s", VCL_Name(ctx->vcl),
set->vcl_name);
vsc->elements = set->nmembers;
for (unsigned i = 0; i < set->nmembers; i++)
vsc->setsz += strlen(set->members[i]) + 1;
vsc->minlen = ph_stats.minlen;
vsc->maxlen = ph_stats.maxlen;
vsc->trie_nodes = qp_stats.nodes;
vsc->trie_nodesz = qp_stats.nodesz;
vsc->trie_leaves = qp_stats.leaves;
vsc->trie_depth_min = qp_stats.dmin;
vsc->trie_depth_max = qp_stats.dmax;
vsc->trie_depth_avg = (uint64_t)(qp_stats.davg + 0.5);
vsc->trie_fanout_min = qp_stats.fmin;
vsc->trie_fanout_max = qp_stats.fmax;
vsc->trie_fanout_avg = (uint64_t)(qp_stats.favg + 0.5);
vsc->hash_buckets = ph_stats.buckets;
vsc->hash_collisions = ph_stats.collisions;
vsc->hash_keylen = ph_stats.klen;
vsc->hash_h2_buckets_min = ph_stats.h2buckets_min;
vsc->hash_h2_buckets_max = ph_stats.h2buckets_max;
vsc->hash_h2_buckets_avg = (uint64_t)(ph_stats.h2buckets_avg + 0.5);
vsc->hash_h2_strings_min = ph_stats.h2strings_min;
vsc->hash_h2_strings_max = ph_stats.h2strings_max;
vsc->hash_h2_strings_avg = (uint64_t)(ph_stats.h2strings_avg + 0.5);
vsc->hash_h2_klen_min = ph_stats.h2klen_min;
vsc->hash_h2_klen_max = ph_stats.h2klen_max;
vsc->hash_h2_klen_avg = (uint64_t)(ph_stats.h2klen_avg + 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);
}
static void
set_complete_init(VRT_CTX, void *priv)
{
struct set_init_head *head;
struct set_init_task *task;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
AN(priv);
head = priv;
AZ(VSLIST_EMPTY(head));
VSLIST_FOREACH(task, head, list) {
CHECK_OBJ_NOTNULL(task, SET_INIT_TASK_MAGIC);
CHECK_OBJ_NOTNULL(task->set, VMOD_SELECTOR_SET_MAGIC);
AN(task->vsc_head);
if (task->set->hash == NULL)
if (compile(ctx, task->set, " set initialization") != 0)
return;
if (task->create_stats)
create_stats(ctx, task->set, task->vsc_head);
}
}
static const struct vmod_priv_methods set_init[1] = {{
.magic = VMOD_PRIV_METHODS_MAGIC,
.type = "vmod_selector_set_init",
.fini = set_complete_init,
}};
VCL_VOID
vmod_set__init(VRT_CTX, struct vmod_selector_set **setp, const char *vcl_name,
struct vmod_priv *priv_vcl, struct vmod_priv *priv_task,
VCL_BOOL case_sensitive, VCL_BOOL allow_overlaps)
{
struct vmod_selector_set *set;
struct set_init_head *task_head;
struct set_init_task *task;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
CHECK_OBJ_NOTNULL(ctx->ws, WS_MAGIC);
AN(setp);
AZ(*setp);
AN(vcl_name);
AN(priv_vcl);
AN(priv_vcl->priv);
AN(priv_task);
ALLOC_OBJ(set, VMOD_SELECTOR_SET_MAGIC);
AN(set);
......@@ -186,6 +403,34 @@ vmod_set__init(VRT_CTX, struct vmod_selector_set **setp, const char *vcl_name,
AN(set->bitmaps->bitmaps[i]);
}
if (priv_task->priv == NULL) {
if ((task_head = WS_Alloc(ctx->ws, sizeof(*task_head)))
== NULL) {
VERRNOMEM(ctx, "insufficient workspace for task "
"head initializing %s", vcl_name);
return;
}
VSLIST_INIT(task_head);
priv_task->priv = task_head;
priv_task->len = sizeof(*task);
priv_task->methods = set_init;
}
else {
AN(priv_task->methods);
task_head = priv_task->priv;
}
if ((task = WS_Alloc(ctx->ws, sizeof(*task))) == NULL) {
VERRNOMEM(ctx, "insufficient workspace to initialize %s",
vcl_name);
return;
}
task->magic = SET_INIT_TASK_MAGIC;
task->set = set;
task->vsc_head = priv_vcl->priv;
task->create_stats = 0;
VSLIST_INSERT_HEAD(task_head, task, list);
AZ(set->table);
AZ(set->members);
AZ(set->origo);
......@@ -335,24 +580,9 @@ vmod_set_add(VRT_CTX, struct vmod_selector_set *set,
set->table[n - 1] = entry;
}
struct memberidx {
char *member;
unsigned n;
};
static int
cmp(const void *a, const void *b)
{
const struct memberidx *aa = a, *bb = b;
return( strcmp(aa->member, bb->member) );
}
VCL_VOID
vmod_set_compile(VRT_CTX, struct VPFX(selector_set) *set)
{
char **members;
struct memberidx *idx;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
CHECK_OBJ_NOTNULL(set, VMOD_SELECTOR_SET_MAGIC);
......@@ -366,60 +596,7 @@ vmod_set_compile(VRT_CTX, struct VPFX(selector_set) *set)
set->vcl_name);
return;
}
members = set->members;
if (!set->case_sensitive)
members = set->lomembers;
if (members == NULL || set->nmembers == 0) {
CHECK_OBJ_NOTNULL(ctx->msg, VSB_MAGIC);
VSL(SLT_VCL_Error, 0, "VCL %s vmod selector %s.compile(): "
"no entries were added, nothing to compile, "
"%s.match() will always fail\n", VCL_Name(ctx->vcl),
set->vcl_name, set->vcl_name);
return;
}
idx = malloc(set->nmembers * sizeof(*idx));
if (idx == NULL) {
VFAIL(ctx, "%s.compile(): out of memory", set->vcl_name);
return;
}
for (unsigned i = 0; i < set->nmembers; i++) {
idx[i].n = i;
idx[i].member = members[i];
}
qsort(idx, set->nmembers, sizeof(*idx), cmp);
for (unsigned i = 0; i < set->nmembers; i++) {
errno = 0;
if (QP_Insert(&set->origo, idx[i].n, members,
set->allow_overlaps) != 0) {
if (errno == EINVAL)
VFAIL(ctx, "%s.compile(): \"%s\" added more "
"than once", set->vcl_name, members[i]);
else if (errno == EPERM)
VFAIL(ctx, "%s.compile(): allow_overlaps is "
"false but strings with common prefixes "
"were added", set->vcl_name);
else
VFAIL(ctx, "%s.compile(\"%s\") failed: %s",
set->vcl_name, members[i],
strerror(errno));
free(idx);
return;
}
}
free(idx);
errno = 0;
if ((set->hash = PH_Generate(members, set->nmembers)) == NULL) {
if (errno == ERANGE)
VFAIL(ctx, "%s.compile(): too many strings in the set",
set->vcl_name);
else
VFAIL(ctx, "%s.compile() failed: %s", set->vcl_name,
strerror(errno));
}
return;
compile(ctx, set, ".compile()");
}
static struct match_data *
......@@ -883,102 +1060,31 @@ VCL_VOID
vmod_set_create_stats(VRT_CTX, struct vmod_selector_set *set,
struct vmod_priv *priv)
{
struct qp_stats qp_stats = { .magic = QP_STATS_MAGIC };
struct ph_stats ph_stats = { .magic = PH_STATS_MAGIC };
struct VSC_selector *vsc;
struct vsc_seg *vsc_seg;
struct vsc_head *vsc_head;
struct vsc_entry *vsc_entry;
struct set_init_task *task;
struct set_init_head *task_head;
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.create_stats() 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(&qp_stats, 0, sizeof(qp_stats));
memset(&ph_stats, 0, sizeof(ph_stats));
}
else if (set->origo == NULL) {
VFAIL(ctx, "%s.create_stats(): set was not compiled",
set->vcl_name);
return;
task_head = priv->priv;
AZ(VSLIST_EMPTY(task_head));
VSLIST_FOREACH(task, task_head, list) {
CHECK_OBJ_NOTNULL(task, SET_INIT_TASK_MAGIC);
CHECK_OBJ_NOTNULL(task->set, VMOD_SELECTOR_SET_MAGIC);
if (task->set == set)
break;
}
else {
char **members = set->members;
if (!set->case_sensitive)
members = set->lomembers;
AN(members);
QP_Stats(set->origo, members, &qp_stats);
assert(qp_stats.terms == set->nmembers);
assert(qp_stats.leaves <= qp_stats.terms);
assert(qp_stats.terms <= qp_stats.nodes);
assert(qp_stats.dmin <= qp_stats.dmax);
assert(qp_stats.dmin <= qp_stats.davg);
assert(qp_stats.davg <= qp_stats.dmax);
assert(qp_stats.fmin <= qp_stats.fmax);
assert(qp_stats.fmin <= qp_stats.favg);
assert(qp_stats.favg <= qp_stats.fmax);
assert(qp_stats.nodesz > 0);
PH_Stats(set->hash, members, &ph_stats);
assert(ph_stats.buckets >= set->nmembers);
assert(ph_stats.collisions <= ph_stats.buckets);
assert(ph_stats.minlen <= ph_stats.maxlen);
assert(ph_stats.klen == ((ph_stats.maxlen + 7) / 8) * 2);
assert(ph_stats.h2buckets_min <= ph_stats.h2buckets_max);
assert(ph_stats.h2buckets_min <= ph_stats.h2buckets_avg);
assert(ph_stats.h2buckets_avg <= ph_stats.h2buckets_max);
assert(ph_stats.h2strings_min <= ph_stats.h2strings_max);
assert(ph_stats.h2strings_min <= ph_stats.h2strings_avg);
assert(ph_stats.h2strings_avg <= ph_stats.h2strings_max);
assert(ph_stats.h2klen_min <= ph_stats.h2klen_max);
assert(ph_stats.h2klen_min <= ph_stats.h2klen_avg);
assert(ph_stats.h2klen_avg <= ph_stats.h2klen_max);
}
vsc = VSC_selector_New(NULL, &vsc_seg, "%s.%s", VCL_Name(ctx->vcl),
set->vcl_name);
vsc->elements = set->nmembers;
for (unsigned i = 0; i < set->nmembers; i++)
vsc->setsz += strlen(set->members[i]) + 1;
vsc->minlen = ph_stats.minlen;
vsc->maxlen = ph_stats.maxlen;
vsc->trie_nodes = qp_stats.nodes;
vsc->trie_nodesz = qp_stats.nodesz;
vsc->trie_leaves = qp_stats.leaves;
vsc->trie_depth_min = qp_stats.dmin;
vsc->trie_depth_max = qp_stats.dmax;
vsc->trie_depth_avg = (uint64_t)(qp_stats.davg + 0.5);
vsc->trie_fanout_min = qp_stats.fmin;
vsc->trie_fanout_max = qp_stats.fmax;
vsc->trie_fanout_avg = (uint64_t)(qp_stats.favg + 0.5);
vsc->hash_buckets = ph_stats.buckets;
vsc->hash_collisions = ph_stats.collisions;
vsc->hash_keylen = ph_stats.klen;
vsc->hash_h2_buckets_min = ph_stats.h2buckets_min;
vsc->hash_h2_buckets_max = ph_stats.h2buckets_max;
vsc->hash_h2_buckets_avg = (uint64_t)(ph_stats.h2buckets_avg + 0.5);
vsc->hash_h2_strings_min = ph_stats.h2strings_min;
vsc->hash_h2_strings_max = ph_stats.h2strings_max;
vsc->hash_h2_strings_avg = (uint64_t)(ph_stats.h2strings_avg + 0.5);
vsc->hash_h2_klen_min = ph_stats.h2klen_min;
vsc->hash_h2_klen_max = ph_stats.h2klen_max;
vsc->hash_h2_klen_avg = (uint64_t)(ph_stats.h2klen_avg + 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);
CHECK_OBJ_NOTNULL(task, SET_INIT_TASK_MAGIC);
assert(task->set == set);
task->create_stats = 1;
}
VCL_STRING
......
......@@ -371,7 +371,7 @@ To re-state the rules more informally:
prefixes). ``select`` is meant to pick an element when
``.hasprefix()`` finds more than one string.
$Object set(BOOL case_sensitive=1, BOOL allow_overlaps=1)
$Object set(PRIV_VCL, PRIV_TASK, BOOL case_sensitive=1, BOOL allow_overlaps=1)
Create a set object.
......@@ -471,7 +471,7 @@ fail. In that case, a warning is emitted to the log with the
transaction, the error message can only be seen when a tool like
``varnishlog(1)`` is used with raw grouping (``-g raw``).
$Method VOID .create_stats(PRIV_VCL)
$Method VOID .create_stats(PRIV_TASK)
Create statistics counters for this object that are displayed by tools
such as ``varnishstat(1)``. See `STATISTICS`_ for details. It must be
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment