diff options
author | Vasek Sraier <git@vakabus.cz> | 2022-08-02 12:48:48 +0200 |
---|---|---|
committer | Vasek Sraier <git@vakabus.cz> | 2022-08-02 12:48:48 +0200 |
commit | 794acf074bae8004b9bc5a519d173882632ae2cd (patch) | |
tree | 366cbcf2298e2e4302ec0d2bb770b1a5f541a9ba /modules/stats/stats.c | |
parent | Merge branch 'manager-integration-without-submodule' into 'manager' (diff) | |
parent | Merge !1325: ci/pkgtest: remove Ubuntu 21.10 (diff) | |
download | knot-resolver-794acf074bae8004b9bc5a519d173882632ae2cd.tar.xz knot-resolver-794acf074bae8004b9bc5a519d173882632ae2cd.zip |
Merge branch 'master' into manager
Diffstat (limited to 'modules/stats/stats.c')
-rw-r--r-- | modules/stats/stats.c | 52 |
1 files changed, 39 insertions, 13 deletions
diff --git a/modules/stats/stats.c b/modules/stats/stats.c index e0196d2e..67b73df8 100644 --- a/modules/stats/stats.c +++ b/modules/stats/stats.c @@ -18,6 +18,7 @@ #include <arpa/inet.h> #include <lua.h> +#include "lib/generic/trie.h" #include "lib/layer/iterate.h" #include "lib/rplan.h" #include "lib/module.h" @@ -71,7 +72,7 @@ typedef array_t(struct sockaddr_in6) addrlist_t; /** @internal Stats data structure. */ struct stat_data { - map_t map; + trie_t *trie; struct { namehash_t *frequent; } queries; @@ -293,7 +294,8 @@ static char* stats_set(void *env, struct kr_module *module, const char *args) return NULL; } } - map_set(&data->map, pair, (void *)number); + trie_val_t *trie_val = trie_get_ins(data->trie, pair, strlen(pair)); + *trie_val = (void *)number; } return NULL; @@ -326,20 +328,39 @@ static char* stats_get(void *env, struct kr_module *module, const char *args) } } /* Check in variable map */ - if (!map_contains(&data->map, args)) { + trie_val_t *val = trie_get_try(data->trie, args, strlen(args)); + if (!val) { free(ret); return NULL; } - void *val = map_get(&data->map, args); - sprintf(ret, "%zu", (size_t) val); + sprintf(ret, "%zu", (size_t) *val); return ret; } -static int list_entry(const char *key, void *val, void *baton) +/** Checks whether: + * - `key` starts with `prefix`; OR + * - The prefix is a wildcard, which is indicated by `prefix_len` being zero. */ +static inline bool key_matches_prefix(const char *key, size_t key_len, + const char *prefix, size_t prefix_len) { - JsonNode *root = baton; - size_t number = (size_t) val; - json_append_member(root, key, json_mknumber(number)); + return prefix_len == 0 || (prefix_len <= key_len && memcmp(key, prefix, prefix_len) == 0); +} + +struct list_entry_context { + JsonNode *root; /**< JSON object into which matching entries will be inserted. */ + const char *key_prefix; /**< The prefix against which entries will be matched. */ + size_t key_prefix_len; /**< Prefix length. Prefix is a wildcard if zero. */ +}; + +/** Inserts the entry with a matching key into the JSON object. */ +static int list_entry(const char *key, uint32_t key_len, trie_val_t *val, void *baton) +{ + struct list_entry_context *ctx = baton; + if (!key_matches_prefix(key, key_len, ctx->key_prefix, ctx->key_prefix_len)) + return 0; + size_t number = (size_t) *val; + auto_free char *key_nt = strndup(key, key_len); + json_append_member(ctx->root, key_nt, json_mknumber(number)); return 0; } @@ -350,7 +371,6 @@ static int list_entry(const char *key, void *val, void *baton) */ static char* stats_list(void *env, struct kr_module *module, const char *args) { - struct stat_data *data = module->data; JsonNode *root = json_mkobject(); /* Walk const metrics map */ size_t args_len = args ? strlen(args) : 0; @@ -360,7 +380,13 @@ static char* stats_list(void *env, struct kr_module *module, const char *args) json_append_member(root, elm->key, json_mknumber(elm->val)); } } - map_walk_prefixed(&data->map, (args_len > 0) ? args : "", list_entry, root); + struct list_entry_context ctx = { + .root = root, + .key_prefix = args, + .key_prefix_len = args_len + }; + struct stat_data *data = module->data; + trie_apply_with_key(data->trie, list_entry, &ctx); char *ret = json_encode(root); json_delete(root); return ret; @@ -477,7 +503,7 @@ int stats_init(struct kr_module *module) if (!data) { return kr_error(ENOMEM); } - data->map = map_make(NULL); + data->trie = trie_create(NULL); module->data = data; lru_create(&data->queries.frequent, FREQUENT_COUNT, NULL, NULL); /* Initialize ring buffer of recently visited upstreams */ @@ -497,7 +523,7 @@ int stats_deinit(struct kr_module *module) { struct stat_data *data = module->data; if (data) { - map_clear(&data->map); + trie_free(data->trie); lru_free(data->queries.frequent); array_clear(data->upstreams.q); free(data); |