summaryrefslogtreecommitdiffstats
path: root/src/utils/knotc/estimator.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/utils/knotc/estimator.c')
-rw-r--r--src/utils/knotc/estimator.c147
1 files changed, 147 insertions, 0 deletions
diff --git a/src/utils/knotc/estimator.c b/src/utils/knotc/estimator.c
new file mode 100644
index 0000000..f1fa1a7
--- /dev/null
+++ b/src/utils/knotc/estimator.c
@@ -0,0 +1,147 @@
+/* Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program 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 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <assert.h>
+
+#include "utils/knotc/estimator.h"
+#include "knot/zone/node.h"
+#include "libknot/libknot.h"
+#include "contrib/macros.h"
+#include "contrib/string.h"
+#include "contrib/ucw/lists.h"
+
+// Addition constants used for tweaking, mostly malloc overhead
+enum estim_consts {
+ MALLOC_OVERHEAD = sizeof(size_t), // set according to malloc.c
+ MALLOC_MIN = MALLOC_OVERHEAD * 3 // minimum size of malloc'd chunk
+};
+
+typedef struct {
+ node_t n;
+ uint16_t type;
+} type_list_item_t;
+
+static size_t add_overhead(size_t size)
+{
+ return MALLOC_OVERHEAD + size + size % MALLOC_MIN;
+}
+
+// return: 0 not present, 1 - present
+static int find_in_list(list_t *node_list, uint16_t type)
+{
+ node_t *n = NULL;
+ WALK_LIST(n, *node_list) {
+ type_list_item_t *l_entr = (type_list_item_t *)n;
+ assert(l_entr);
+ if (l_entr->type == type) {
+ return 1;
+ }
+ }
+
+ type_list_item_t *new_entry = malloc(sizeof(type_list_item_t));
+ assert(new_entry != NULL);
+ new_entry->type = type;
+
+ add_head(node_list, (node_t *)new_entry);
+ return 0;
+}
+
+// return: 0 not present (added), 1 - present
+static int dummy_node_add_type(list_t *l, uint16_t t)
+{
+ return find_in_list(l, t);
+}
+
+// return: 0 - unique, 1 - duplicate
+static int insert_dname_into_table(trie_t *table, const knot_dname_t *d,
+ list_t **dummy_node)
+{
+ size_t d_size = knot_dname_size(d);
+
+ trie_val_t *val = trie_get_try(table, (char *)d, d_size);
+ if (val == NULL) {
+ // Create new dummy node to use for this dname
+ *dummy_node = malloc(sizeof(list_t));
+ assert(dummy_node != NULL);
+ init_list(*dummy_node);
+ *trie_get_ins(table, (char *)d, d_size) = *dummy_node;
+ return 0;
+ } else {
+ // Return previously found dummy node
+ *dummy_node = (list_t *)(*val);
+ return 1;
+ }
+}
+
+static void rrset_memsize(zone_estim_t *est, const zs_scanner_t *scanner)
+{
+ // Handle RRSet's owner
+ list_t *dummy_node = NULL;
+ if (insert_dname_into_table(est->node_table, scanner->r_owner, &dummy_node) == 0) {
+ // First time we see this name == new node
+ est->node_size += add_overhead(sizeof(zone_node_t));
+ // Also, node has an owner.
+ est->dname_size += add_overhead(knot_dname_size(scanner->r_owner));
+ // Trie's nodes handled at the end of computation
+ }
+ assert(dummy_node);
+
+ // Add RDATA + size
+ size_t rdlen = knot_rdata_size(scanner->r_data_length);
+ est->rdata_size += add_overhead(rdlen);
+ est->record_count++;
+
+ /*
+ * RDATA size done, now add static part of RRSet to size.
+ * Do not add for RRs that would be merged.
+ * All possible duplicates will be added to total size.
+ */
+ if (dummy_node_add_type(dummy_node, scanner->r_type) == 0) {
+ /*
+ * New RR type, add actual rr_data struct's size. No way to
+ * guess the actual overhead taken up by the array, so we add
+ * it each time.
+ */
+ est->node_size += add_overhead(sizeof(struct rr_data));
+ }
+}
+
+void *estimator_malloc(void *ctx, size_t len)
+{
+ size_t *count = (size_t *)ctx;
+ *count += add_overhead(len);
+ return malloc(len);
+}
+
+void estimator_free(void *p)
+{
+ free(p);
+}
+
+void estimator_rrset_memsize_wrap(zs_scanner_t *scanner)
+{
+ rrset_memsize(scanner->process.data, scanner);
+}
+
+int estimator_free_trie_node(trie_val_t *val, void *data)
+{
+ UNUSED(data);
+ list_t *trie_n = (list_t *)(*val);
+ WALK_LIST_FREE(*trie_n);
+ free(trie_n);
+
+ return KNOT_EOK;
+}