summaryrefslogtreecommitdiffabout
authorSergey Poznyakoff <gray@nxc.no>2018-02-04 09:11:07 (GMT)
committer Sergey Poznyakoff <gray@nxc.no>2018-02-04 11:52:11 (GMT)
commit7651936f80b1bc6f5b01477ee9e648843097d7b8 (patch) (side-by-side diff)
treeec6232e179767283c557b6c1babf23bcb1bb455a
parent82822c0a336018e33658aebb166819c960e92140 (diff)
downloadvarnish-mib-7651936f80b1bc6f5b01477ee9e648843097d7b8.tar.gz
varnish-mib-7651936f80b1bc6f5b01477ee9e648843097d7b8.tar.bz2
Rewrite hash table support.
* .gitignore: Update. * Makefile.am (EXTRA_DIST): Add perl modules from lib/VarnishMib * lib/VarnishMib/HashTable.pm: New file. * lib/VarnishMib/MIBTable.pm: New file. * src/Makefile.am (varnish_mib_la_SOURCES): Remove statdict. (.mib2c.c): Set PERL5LIB * src/betab.c (backend_dfn.vpt): Remove const qualifier. (backend_register): Store in vpt cloned points. (backend_clear): Destroy points in vpt. * src/statdict.c: Remove. * src/varnish_mib.mib2c: Use VarnishMib::MIBTable. Set mib2c variable $varnish_hash_table to an instance of VarnishMib::MIBTable. Use it to generate lookup table code section. (varnish_var_lookup, varnish_get_oid) (dict_clear, dict_install, dict_load): New functions. (handle_$i): Use direct addressing to obtain a vpt. Fix handling of ASN_TIMETICKS.
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--.gitignore1
-rw-r--r--Makefile.am6
-rwxr-xr-xbootstrap40
-rw-r--r--configure.ac3
-rw-r--r--lib/VarnishMib/HashTable.pm242
-rw-r--r--lib/VarnishMib/MIBTable.pm70
-rw-r--r--lib/prereq.pl5
-rw-r--r--src/Makefile.am5
-rw-r--r--src/betab.c7
-rw-r--r--src/statdict.c168
-rw-r--r--src/varnish_mib.mib2c101
11 files changed, 465 insertions, 183 deletions
diff --git a/.gitignore b/.gitignore
index 506e185..24dd695 100644
--- a/.gitignore
+++ b/.gitignore
@@ -26,3 +26,4 @@ core
libtool
m4
stamp-h1
+_Inline
diff --git a/Makefile.am b/Makefile.am
index 0334f01..30060d5 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -15,7 +15,11 @@
# along with varnish-mib. If not, see <http://www.gnu.org/licenses/>.
ACLOCAL_AMFLAGS = -I m4
SUBDIRS = src
-EXTRA_DIST=git2chg.awk
+EXTRA_DIST=\
+ git2chg.awk\
+ lib/prereq.pl\
+ lib/VarnishMib/HashTable.pm\
+ lib/VarnishMib/MIBTable.pm
.PHONY: ChangeLog
ChangeLog:
diff --git a/bootstrap b/bootstrap
index a4a33d4..5717cbc 100755
--- a/bootstrap
+++ b/bootstrap
@@ -1,4 +1,8 @@
-#!/usr/bin/perl
+#!/bin/sh
+#! -*-perl-*-
+eval 'exec perl -x -wS $0 ${1+"$@"}'
+ if 0;
+
use strict;
use autodie;
@@ -7,6 +11,40 @@ my $mib2c_config = 'src/varnish_mib.mib2c';
die "This file must be run from the varnish-mib top level source directory"
unless -r $mib2c_config;
+sub vercmp {
+ my ($va, $vb) = @_;
+ my @a = split /\./, $va;
+ my @b = split /\./, $vb;
+ my $res;
+ while (defined(my $na = shift @a)) {
+ return 0 unless $na =~ /^\d+$/;
+ my $nb = shift @b;
+ return 1 unless defined($nb);
+ return 0 unless $nb =~ /^\d+$/;
+ $res = $na <=> $nb;
+ last if $res;
+ }
+ $res;
+}
+
+if (-f 'lib/prereq.pl') {
+ print "$0: checking prerequisites\n";
+ our @prereq;
+ do 'lib/prereq.pl';
+
+ while ((my $pkg = shift @prereq) && defined(my $req = shift @prereq)) {
+ my $v = eval "require $pkg; \$${pkg}::VERSION";
+ if ($@) {
+ warn "$pkg not installed";
+ next;
+ }
+ print "$0: $pkg version $v installed\n";
+ if ($v && vercmp($v, $req) < 0) {
+ warn "$pkg: version $v too old (at least $req is required)";
+ }
+ }
+}
+
print "$0: creating ancillary directories and files\n";
foreach my $dir ('m4', 'build-aux') {
mkdir($dir) unless -d $dir;
diff --git a/configure.ac b/configure.ac
index a800774..84544b2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -23,7 +23,8 @@ AC_CONFIG_MACRO_DIR([m4])
AC_CANONICAL_SYSTEM
AC_LANG(C)
-AM_INIT_AUTOMAKE([gnu tar-ustar])
+AM_INIT_AUTOMAKE([gnu tar-ustar silent-rules])
+AM_SILENT_RULES([yes])
AC_GNU_SOURCE
AC_PROG_CC
diff --git a/lib/VarnishMib/HashTable.pm b/lib/VarnishMib/HashTable.pm
new file mode 100644
index 0000000..0f3b47e
--- a/dev/null
+++ b/lib/VarnishMib/HashTable.pm
@@ -0,0 +1,242 @@
+package VarnishMib::HashTable;
+use strict;
+use warnings;
+use Carp;
+use Inline 'C';
+use Pod::Usage;
+use Pod::Man;
+
+=head1 NAME
+
+VarnishMib::HashTable - Create a hash table implementation in C
+
+=head1 DESCRIPTION
+
+Given a list of unique strings, creates a C code for fast look ups of
+data associated with them.
+
+=head1 CONSTRUCTOR
+
+ $ht = new VarnishMib::HashTable([KW => VAL,...]);
+
+Returns a new instance of the hash table generator. Allowed arguments are:
+
+=over 4
+
+=item B<max_collisions>
+
+Maximum number of collisions allowed for the resulting hash table. Default is
+unlimited.
+
+=item B<max_hash_size>
+
+Maximum size of the resulting hash table (in items).
+
+=item B<indent>
+
+Basic indent value for the generated C text. Default is 4.
+
+=item B<verbose>
+
+Produce verbose statistics about the created hash table.
+
+=item B<prefix>
+
+Prefix all C identifiers with this string. Default is C<ht_>.
+
+=back
+
+=cut
+
+sub new {
+ my $class = shift;
+ my $self = bless {}, $class;
+ my $v;
+ local %_ = @_;
+ $self->{max_collisions} = delete $_{max_collisions};
+ $self->{max_hash_size} = delete $_{max_hash_size};
+ $self->{indent} = ' ' x (delete $_{indent} || 4);
+ $self->{verbose} = delete $_{verbose};
+ $self->{prefix} = delete $_{prefix} || 'ht_';
+ croak "extra arguments" if keys %_;
+ return $self;
+}
+
+=head1 METHODS
+
+=head2 prefix
+
+ $s = $ht->prefix;
+
+Returns current prefix value.
+
+=cut
+
+sub prefix { shift->{prefix} }
+
+=head2 indent
+
+ $s = $ht->indent;
+
+Returns the indent prefix string. I<Note>, that it is not the same as the
+B<ident> parameter passed to the constructor. This method returs a string
+filled with appropriate number of whitespace characters, such that it can
+be used to produce the requested indentation.
+
+=cut
+
+sub indent { shift->{indent} }
+
+sub hash_string {
+ my ($self, $string, $hash_size) = @_;
+ string_hash($string, $hash_size);
+}
+
+sub _mktab {
+ my ($self, $hash_size) = @_;
+ my @ht = (-1) x $hash_size;
+ my $cmax = 0;
+ for (my $i = 0; $i < @{$self->{input}}; $i++) {
+ my $h = $self->hash_string($self->{input}[$i], $hash_size);
+ my $cn = 0;
+ while ($ht[$h] != -1) {
+ ++$cn;
+ return if (++$h >= $hash_size);
+ }
+ $ht[$h] = $i;
+# print STDERR $self->{input}[$i] . ' => ' . $h ." $i\n";
+ $cmax = $cn if $cn > $cmax;
+ }
+# print STDERR "$hash_size $cmax\n";
+ $self->{hash_table} = \@ht;
+ $self->{collisions} = $cmax;
+ return $self->{hash_table};
+}
+
+=head2 create
+
+ $success = $ht->create(LISTREF)
+
+B<LISTREF> must be a reference to a list of unique string values. This method
+creates a hash table. Returns true on success and undef on failure.
+
+=cut
+
+sub create {
+ my ($self, $names) = @_;
+ my $htab;
+ my $hsize;
+
+ $self->{input} = $names;
+ delete $self->{hash_table};
+
+ for ($hsize = (2 * @$names + 1);; $hsize++) {
+ last if $self->{max_hash_size} && $hsize < $self->{max_hash_size};
+ $self->_mktab($hsize) or next;
+ last unless (defined($self->{max_collisions})
+ && $self->{collisions} > $self->{max_collisions});
+ }
+ if ($self->{verbose}) {
+# print STDERR "Input: " . @$names . "\n";
+ if ($self->{hash_table}) {
+ print STDERR "Table size: " . @{$self->{hash_table}} . "\n";
+ print STDERR "Collisions: " . $self->{collisions} . "\n";
+ } else {
+ print STDERR "FAILED\n";
+ }
+ }
+ return $self->{hash_table};
+}
+
+sub format_input_table {
+ my ($self, $fh) = @_;
+ $fh ||= \*STDOUT;
+ croak "no input data to format" unless $self->{input};
+ print $fh 'char const *' . $self->{prefix} . "name_table[] = {\n";
+ foreach my $name (@{$self->{input}}) {
+ printf $fh $self->{indent} . '"' . $name . "\",\n";
+ }
+ print $fh "};\n";
+
+}
+
+sub format_data_table {
+ my ($self, $type, $fh) = @_;
+ $fh ||= \*STDOUT;
+ croak "no data to format" unless $self->{input};
+ my $n = @{$self->{input}};
+ print $fh $type . ' ' . $self->{prefix} . "data_table[$n];\n";
+}
+
+sub format_hash_table {
+ my ($self, $fh) = @_;
+ $fh ||= \*STDOUT;
+ croak "no hash table to format" unless $self->{hash_table};
+ print $fh "static int ".$self->{prefix}."hash_table[] = {\n";
+ my $col = 0;
+ print $fh $self->{indent};
+ foreach my $p (@{$self->{hash_table}}) {
+ printf $fh "%3d,", defined($p) ? $p : -1;
+ $col++;
+ print $fh ($col % 10 == 0) ? "\n".$self->{indent} : ' ';
+ }
+ print $fh "\n" if ($col % 10);
+ print $fh "};\n";
+ my $pfx = $self->{prefix} . 'hash_table';
+ print $fh "unsigned ${pfx}_size = sizeof($pfx) / sizeof(${pfx}[0]);\n";
+}
+
+sub format_code {
+ my ($self, $fh) = @_;
+ $fh ||= \*STDOUT;
+ seek DATA, 0, 0;
+ my $visible = 0;
+ while (<DATA>) {
+ if (/^__C__$/) {
+ $visible = 1;
+ } elsif ($visible) {
+ s{/\*\s*STATIC\s*\*/}{static};
+ print $fh "$_";
+ }
+ }
+}
+
+sub format_program {
+ my ($self, $type, $fh) = @_;
+ $fh ||= \*STDOUT;
+ $self->format_input_table($fh);
+ print $fh "\n";
+ $self->format_data_table($type, $fh);
+ print $fh "\n";
+ $self->format_hash_table($fh);
+ print $fh "\n";
+ $self->format_code($fh);
+}
+
+Inline->init();
+1;
+__DATA__
+__C__
+#ifndef CHAR_BIT
+# define CHAR_BIT 8
+#endif
+#ifndef UINT_MAX
+# define UINT_MAX ((unsigned)-1)
+#endif
+
+static inline unsigned
+rotl_sz(unsigned x, int n)
+{
+ return ((x << n) | (x >> ((CHAR_BIT * sizeof x) - n))) & UINT_MAX;
+}
+
+/*STATIC*/ unsigned
+string_hash(const char *str, unsigned size)
+{
+ unsigned value = 0;
+ unsigned char ch;
+
+ for (; (ch = *str); str++)
+ value = ch + rotl_sz(value, 7);
+ return value % size;
+}
diff --git a/lib/VarnishMib/MIBTable.pm b/lib/VarnishMib/MIBTable.pm
new file mode 100644
index 0000000..6aa959f
--- a/dev/null
+++ b/lib/VarnishMib/MIBTable.pm
@@ -0,0 +1,70 @@
+package VarnishMib::MIBTable;
+use strict;
+use warnings;
+use parent 'VarnishMib::HashTable';
+use Carp;
+
+sub new {
+ my ($class, $type, $table, %args) = @_;
+ my @oids =
+ sort { $table->{$a}[1] cmp $table->{$b}[1] }
+ grep { $table->{$_}[0] eq 'DICT' } keys %{$table};
+
+ my @equiv;
+ my @uniq_oids;
+ for (my $i = 0; $i <= $#oids; $i++) {
+ unless ($i > 0
+ && $table->{$uniq_oids[-1]}[1] eq $table->{$oids[$i]}[1]) {
+ push @uniq_oids, $oids[$i];
+ }
+ push @equiv, $#uniq_oids;
+ }
+ my $self = bless $class->SUPER::new(%args), $class;
+ $self->{oids_all} = \@oids;
+ $self->{oids_uniq} = \@uniq_oids;
+ $self->{equiv} = \@equiv;
+ $self->{type} = $type;
+
+ $self->create([map { $table->{$_}[1] } @{$self->{oids_uniq}}]);
+ return $self;
+}
+
+sub format_oids {
+ my ($self, $fh) = @_;
+ $fh ||= \*STDOUT;
+
+ print $fh "enum ".$self->prefix."oid {\n";
+ for (my $i = 0; $i <= $#{$self->{oids_all}}; $i++) {
+ print $fh $self->indent . $self->{oids_all}[$i];
+ if ($i > 0
+ && $self->{oids_all}[$i] ne $self->{oids_uniq}[$self->{equiv}[$i]]) {
+ print $fh ' = ' . $self->{oids_uniq}[$self->{equiv}[$i]];
+ }
+ print $fh ",\n";
+ }
+ print $fh $self->indent . 'MAX_' . uc($self->prefix) . "OID\n";
+ print $fh "};\n\n";
+}
+
+sub format_program {
+ my ($self, $fh) = @_;
+ $fh ||= \*STDOUT;
+ $self->format_oids($fh);
+ $self->SUPER::format_program($self->{type}, $fh);
+}
+
+sub str {
+ my $self = shift;
+ my $str;
+ open(my $fh, '>', \$str) or croak "can't write to string";
+ $self->format_program($fh);
+ close $fh;
+ return $str;
+};
+
+use overload '""' => \&str;
+
+1;
+
+
+
diff --git a/lib/prereq.pl b/lib/prereq.pl
new file mode 100644
index 0000000..a1e9e2d
--- a/dev/null
+++ b/lib/prereq.pl
@@ -0,0 +1,5 @@
+@prereq = (
+ 'Inline::C' => 0,
+ 'Pod::Usage' => 0,
+ 'Pod::Man' => 0
+);
diff --git a/src/Makefile.am b/src/Makefile.am
index 3ef9fa5..55cdb85 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -27,7 +27,6 @@ varnish_mib_la_SOURCES = \
modconf.c\
sha256.c\
sha256.h\
- statdict.c\
varnish_mib.c\
varnish_mib.h\
vcli.c\
@@ -40,7 +39,9 @@ BUILT_SOURCES = \
varnish_mib.c varnish_mib.h: varnish_mib.mib2c VARNISH-MIB.txt
.mib2c.c:
- MIBDIRS=${top_srcdir}/src:${NET_SNMP_MIBDIRS} MIBS="VARNISH-MIB:${NET_SNMP_MIBS}" \
+ MIBDIRS=${top_srcdir}/src:${NET_SNMP_MIBDIRS}\
+ MIBS="VARNISH-MIB:${NET_SNMP_MIBS}" \
+ PERL5LIB=${top_srcdir}/lib \
mib2c -c $< -f $@ varnish
#NET_SNMP_INCLUDES = `$(NET_SNMP_CONFIG) --cflags`
diff --git a/src/betab.c b/src/betab.c
index afec48a..2979f8b 100644
--- a/src/betab.c
+++ b/src/betab.c
@@ -79,7 +79,7 @@ struct backend_dfn {
size_t vbeIPv6_len;
u_long vbePort;
- const struct VSC_point *vpt[VBE_MAX];
+ struct VSC_point *vpt[VBE_MAX];
VTAILQ_ENTRY(backend_dfn) list;
};
@@ -92,6 +92,9 @@ backend_clear(void)
{
while (!VTAILQ_EMPTY(&backends)) {
struct backend_dfn *dfn = VTAILQ_FIRST(&backends);
+ int i;
+ for (i = 0; i < VBE_MAX; i++)
+ VSC_Destroy_Point(&dfn->vpt[i]);
VTAILQ_REMOVE(&backends, dfn, list);
free(dfn->vbeIdent);
SNMP_FREE(dfn);
@@ -124,7 +127,7 @@ backend_register(char const *name, size_t len, char const *param,
}
for (i = 0; betab_trans[i].param; i++) {
if (strcmp(betab_trans[i].param, param) == 0) {
- dfn->vpt[i] = vpt;
+ dfn->vpt[i] = VSC_Clone_Point(vpt);
break;
}
}
diff --git a/src/statdict.c b/src/statdict.c
deleted file mode 100644
index 69b442f..0000000
--- a/src/statdict.c
+++ b/dev/null
@@ -1,168 +0,0 @@
-/* This file is part of varnish-mib
- Copyright (C) 2018 Sergey Poznyakoff
-
- Varnish-mib is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3, or (at your option)
- any later version.
-
- Varnish-mib is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with varnish-mib. If not, see <http://www.gnu.org/licenses/>.
-*/
-#include <stdio.h>
-#include <stdlib.h>
-#include <limits.h>
-#include <inttypes.h>
-#include <string.h>
-#include <vapi/vsc.h>
-#include <vapi/vsm.h>
-#include <vas.h>
-#include <vcli.h>
-#include "backend.h"
-
-static size_t hash_size[] = {
- 7, 17, 37, 101, 229, 487, 1009, 2039, 4091, 8191, 16411
-};
-static size_t hash_num = 0;
-static struct VSC_point **dict;
-
-#define SIZE_T_MAX ((size_t)-1)
-
-static inline size_t
-rotl(size_t x, int n)
-{
- return ((x << n) | (x >> ((CHAR_BIT * sizeof x) - n))) & SIZE_T_MAX;
-}
-
-static size_t
-hash(const char *str)
-{
- size_t value = 0;
- unsigned char ch;
-
- while ((ch = *str++))
- value = ch + rotl(value, 7);
- return value % hash_size[hash_num];
-}
-
-struct VSC_point **lookup(const char *name, int install);
-
-static void
-rehash(void)
-{
- struct VSC_point **old_dict = dict;
- size_t old_size = hash_size[hash_num];
- size_t i;
-
- ++hash_num;
- AN(hash_num < sizeof(hash_size) / sizeof(hash_size[0]));
- dict = calloc(hash_size[hash_num], sizeof(dict[0]));
- AN(dict);
-
- for (i = 0; i < old_size; i++) {
- if (old_dict[i])
- *lookup(old_dict[i]->name, 1) = old_dict[i];
- }
- free(old_dict);
-}
-
-struct VSC_point **
-lookup(const char *name, int install)
-{
- size_t i, pos;
-
- if (!dict) {
- if (install) {
- dict = calloc(hash_size[hash_num], sizeof(dict[0]));
- AN(dict);
- } else
- return NULL;
- }
-
- pos = hash(name);
-
- for (i = pos; dict[i];) {
- if (strcmp(dict[i]->name, name) == 0) {
- return &dict[i];
- }
-
- if (++i >= hash_size[hash_num])
- i = 0;
- if (i == pos)
- break;
- }
-
- if (!install)
- return NULL;
-
- if (!dict[i])
- return &dict[i];
-
- rehash();
- return lookup(name, install);
-}
-
-int
-dict_lookup(char const *key, uint64_t *val)
-{
- struct VSC_point **ent;
-
- ent = lookup(key, 0);
- if (!ent)
- return -1;
- *val = *(uint64_t*)(*ent)->ptr;
- return 0;
-}
-
-void
-dict_clear(void)
-{
- if (dict) {
- size_t i;
- for (i = 0; i < hash_size[hash_num]; i++)
- if (dict[i])
- VSC_Destroy_Point(&dict[i]);
- }
-}
-
-struct VSC_point const *
-dict_install(struct VSC_point const *pt)
-{
- struct VSC_point **ent;
-
- ent = lookup(pt->name, 1);
- AN(ent);
- if (*ent)
- VSC_Destroy_Point(ent);
- *ent = VSC_Clone_Point(pt);
- return *ent;
-}
-
-static int
-load_cb(void *priv, const struct VSC_point *vpt)
-{
- AZ(strcmp(vpt->ctype, "uint64_t"));
- vpt = dict_install(vpt);
- if (strncmp(vpt->name, "VBE.", 4) == 0) {
- char const *name = vpt->name + 4;
- char *p = strrchr(name, '.');
- if (p) {
- backend_register(name, p - name, p + 1, vpt);
- }
- }
- return 0;
-}
-
-void
-dict_load(struct vsc *vsc)
-{
- struct vsm_fantom fantom = VSM_FANTOM_NULL;
- dict_clear();
- backend_clear();
- VSC_Iter(vsc, &fantom, load_cb, NULL);
-}
diff --git a/src/varnish_mib.mib2c b/src/varnish_mib.mib2c
index 7084476..2b12090 100644
--- a/src/varnish_mib.mib2c
+++ b/src/varnish_mib.mib2c
@@ -24,6 +24,8 @@
*/
@enddefine@
@startperl@
+use VarnishMib::MIBTable;
+
$vars{'varnish_translate_table'} = {
uptime => [ DICT => 'MAIN.uptime' ],
clientAcceptedConnections => [ DICT => 'MAIN.sess_conn' ],
@@ -96,7 +98,7 @@ $vars{'varnish_translate_table'} = {
bansLurkerObjKilled => [ DICT => 'MAIN.bans_lurker_obj_killed' ],
bansDups => [ DICT => 'MAIN.bans_dups' ],
bansLurkerContention => [ DICT => 'MAIN.bans_lurker_contention' ],
- bansPersistedBytes => [ DICT => 'MAIN.bans_persisted_bytes' ],
+ bansPersistedBytes => [ DICT => 'MAIN.bans_persisted_bytes' ],
bansPersistedFragmentation => [ DICT => 'MAIN.bans_persisted_fragmentation' ],
objectsCount => [ DICT => 'MAIN.n_object' ],
@@ -117,6 +119,12 @@ $vars{'varnish_translate_table'} = {
vclFail => [ DICT => 'MAIN.vcl_fail' ],
};
+$vars{'varnish_hash_table'} = new VarnishMib::MIBTable(
+ 'struct VSC_point *',
+ $vars{'varnish_translate_table'},
+ prefix => 'vmib_', max_collisions => 0
+ );
+
my @reset_names;
$vars{'varnish_translate'} = sub {
@@ -155,12 +163,11 @@ $vars{'set_field_dim'} = sub {
$vars{'modulename'} = $vars{'name'};
$vars{'modulename'} =~ s#.*/##;
$vars{'modulename'} =~ s/\.c$//;
-#print "$vars{'modulename'}\n";
-
0;
@endperl@
@open ${modulename}.h@
/* THIS FILE IS GENERATED AUTOMATICALLY. PLEASE DO NOT EDIT. */
+
#include <config.h>
#include <stddef.h>
#include <stdlib.h>
@@ -189,10 +196,6 @@ int varnish_ban(netsnmp_agent_request_info *reqinfo,
netsnmp_request_info *requests,
struct vsm *vsm);
-int dict_lookup(char const *key, uint64_t *val);
-void dict_install(struct VSC_point const *pt);
-void dict_load(struct vsc *vsc);
-
@open ${name}@
/* THIS FILE IS GENERATED AUTOMATICALLY. PLEASE DO NOT EDIT. */
@@ -202,6 +205,8 @@ void dict_load(struct vsc *vsc);
static struct vsm *vd;
static struct vsc *vsc;
+static void dict_load(struct vsc *vsc);
+
int
post_config(int majorID, int minorID, void *serverarg, void *clientarg)
{
@@ -253,6 +258,80 @@ varnish_get_vsm_data(void)
return vd;
}
+${varnish_hash_table}
+
+static struct VSC_point **
+varnish_var_lookup(char const *str)
+{
+ if (str) {
+ int i, h;
+
+ h = string_hash(str, vmib_hash_table_size);
+ i = h;
+ while (vmib_hash_table[i] != -1) {
+ if (strcmp(vmib_name_table[vmib_hash_table[i]], str) == 0)
+ return &vmib_data_table[vmib_hash_table[i]];
+ i = (i + 1) % vmib_hash_table_size;
+ if (i == h)
+ break;
+ }
+ }
+ return NULL;
+}
+
+static inline struct VSC_point *
+varnish_get_oid(int i)
+{
+ return vmib_data_table[i];
+}
+
+static void
+dict_clear(void)
+{
+ int i;
+ for (i = 0; i < MAX_VMIB_OID; i++)
+ if (vmib_data_table[i])
+ VSC_Destroy_Point(&vmib_data_table[i]);
+}
+
+static struct VSC_point const *
+dict_install(struct VSC_point const *pt)
+{
+ struct VSC_point **ent;
+
+ ent = varnish_var_lookup(pt->name);
+ if (!ent)
+ return NULL;
+ if (*ent)
+ VSC_Destroy_Point(ent);
+ *ent = VSC_Clone_Point(pt);
+ return *ent;
+}
+
+static int
+load_cb(void *priv, const struct VSC_point *vpt)
+{
+ AZ(strcmp(vpt->ctype, "uint64_t"));
+ if (strncmp(vpt->name, "VBE.", 4) == 0) {
+ char const *name = vpt->name + 4;
+ char *p = strrchr(name, '.');
+ if (p) {
+ backend_register(name, p - name, p + 1, vpt);
+ }
+ }
+ vpt = dict_install(vpt);
+ return 0;
+}
+
+static void
+dict_load(struct vsc *vsc)
+{
+ struct vsm_fantom fantom = VSM_FANTOM_NULL;
+ dict_clear();
+ backend_clear();
+ VSC_Iter(vsc, &fantom, load_cb, NULL);
+}
+
/* Variable handlers.
An instance handler only hands us one request at a time, unwrapping
@@ -282,9 +361,12 @@ handle_$i(netsnmp_mib_handler *handler,
case MODE_GET:
@if $varnish_type eq 'DICT'@
{
+ struct VSC_point *ent = varnish_get_oid($i);
uint64_t val;
- if (dict_lookup("$varnish_member", &val))
+
+ if (!ent)
return SNMP_ERR_NOSUCHNAME;
+ val = *(uint64_t*)ent->ptr;
@if $i.type eq 'ASN_COUNTER64'@
{
struct counter64 ctr;
@@ -295,6 +377,9 @@ handle_$i(netsnmp_mib_handler *handler,
sizeof(ctr));
}
@else@
+ @if $i.type eq 'ASN_TIMETICKS'@
+ val *= 100;
+ @end@
snmp_set_var_typed_value(requests->requestvb, $i.type,
&val,
sizeof(val));

Return to:

Send suggestions and report system problems to the System administrator.