summaryrefslogtreecommitdiffabout
path: root/src/statdict.c
Side-by-side diff
Diffstat (limited to 'src/statdict.c') (more/less context) (ignore whitespace changes)
-rw-r--r--src/statdict.c172
1 files changed, 172 insertions, 0 deletions
diff --git a/src/statdict.c b/src/statdict.c
new file mode 100644
index 0000000..e87123b
--- a/dev/null
+++ b/src/statdict.c
@@ -0,0 +1,172 @@
+/* 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) {
+ fprintf(stderr, "%s NOT FOUND\n", key);
+ }
+ 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);
+ backend_collect_addr();
+}

Return to:

Send suggestions and report system problems to the System administrator.