+++ /dev/null
-/* Copyright (C) CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
- * SPDX-License-Identifier: GPL-3.0-or-later
- */
-
-/*!
- * \brief Simple write-once allocation-optimal dynamic array.
- *
- * Include it into your .c file
- *
- * prefix - identifier prefix, e.g. ptr -> struct ptr_dynarray, ptr_dynarray_add(), ...
- * ntype - data type to be stored. Let it be a number, pointer or small struct
- * initial_capacity - how many data items will be allocated on stack and copied with assignment
- *
- * prefix_dynarray_add() - add a data item
- * prefix_dynarray_fix() - call EVERYTIME the array is copied from some already invalid stack
- * prefix_dynarray_free() - call EVERYTIME you dismiss all copies of the array
- *
- */
-
-#include <stdlib.h>
-#include <assert.h>
-
-#pragma once
-
-#define DYNARRAY_VISIBILITY_STATIC static
-#define DYNARRAY_VISIBILITY_PUBLIC
-#define DYNARRAY_VISIBILITY_LIBRARY __public__
-
-#define dynarray_declare(prefix, ntype, visibility, initial_capacity) \
- typedef struct prefix ## _dynarray { \
- ssize_t capacity; \
- ssize_t size; \
- ntype *(*arr)(struct prefix ## _dynarray *dynarray); \
- ntype init[initial_capacity]; \
- ntype *_arr; \
- } prefix ## _dynarray_t; \
- \
- visibility ntype *prefix ## _dynarray_arr(prefix ## _dynarray_t *dynarray); \
- visibility void prefix ## _dynarray_add(prefix ## _dynarray_t *dynarray, \
- ntype const *to_add); \
- visibility void prefix ## _dynarray_free(prefix ## _dynarray_t *dynarray);
-
-#define dynarray_foreach(prefix, ntype, ptr, array) \
- for (ntype *ptr = prefix ## _dynarray_arr(&(array)); \
- ptr < prefix ## _dynarray_arr(&(array)) + (array).size; ptr++)
-
-#define dynarray_define(prefix, ntype, visibility) \
- \
- static void prefix ## _dynarray_free__(struct prefix ## _dynarray *dynarray) \
- { \
- if (dynarray->capacity > sizeof(dynarray->init) / sizeof(*dynarray->init)) { \
- free(dynarray->_arr); \
- } \
- } \
- \
- __attribute__((unused)) \
- visibility ntype *prefix ## _dynarray_arr(struct prefix ## _dynarray *dynarray) \
- { \
- assert(dynarray->size <= dynarray->capacity); \
- return (dynarray->capacity <= sizeof(dynarray->init) / sizeof(*dynarray->init) ? \
- dynarray->init : dynarray->_arr); \
- } \
- \
- static ntype *prefix ## _dynarray_arr_init__(struct prefix ## _dynarray *dynarray) \
- { \
- assert(dynarray->capacity == sizeof(dynarray->init) / sizeof(*dynarray->init)); \
- return dynarray->init; \
- } \
- \
- static ntype *prefix ## _dynarray_arr_arr__(struct prefix ## _dynarray *dynarray) \
- { \
- assert(dynarray->capacity > sizeof(dynarray->init) / sizeof(*dynarray->init)); \
- return dynarray->_arr; \
- } \
- \
- __attribute__((unused)) \
- visibility void prefix ## _dynarray_add(struct prefix ## _dynarray *dynarray, \
- ntype const *to_add) \
- { \
- if (dynarray->capacity < 0) { \
- return; \
- } \
- if (dynarray->capacity == 0) { \
- dynarray->capacity = sizeof(dynarray->init) / sizeof(*dynarray->init); \
- dynarray->arr = prefix ## _dynarray_arr_init__; \
- } \
- if (dynarray->size >= dynarray->capacity) { \
- ssize_t new_capacity = dynarray->capacity * 2 + 1; \
- ntype *new_arr = calloc(new_capacity, sizeof(ntype)); \
- if (new_arr == NULL) { \
- prefix ## _dynarray_free__(dynarray); \
- dynarray->capacity = dynarray->size = -1; \
- return; \
- } \
- if (dynarray->capacity > 0) { \
- memcpy(new_arr, prefix ## _dynarray_arr(dynarray), \
- dynarray->capacity * sizeof(ntype)); \
- } \
- prefix ## _dynarray_free__(dynarray); \
- dynarray->_arr = new_arr; \
- dynarray->capacity = new_capacity; \
- dynarray->arr = prefix ## _dynarray_arr_arr__; \
- } \
- prefix ## _dynarray_arr(dynarray)[dynarray->size++] = *to_add; \
- } \
- \
- __attribute__((unused)) \
- visibility void prefix ## _dynarray_free(struct prefix ## _dynarray *dynarray) \
- { \
- prefix ## _dynarray_free__(dynarray); \
- memset(dynarray, 0, sizeof(*dynarray)); \
- }
// libknot includes
#include <libknot/libknot.h>
-// dynarray is inside libknot since 3.1, but it's differently named
-#ifdef knot_dynarray_declare
- #define dynarray_declare knot_dynarray_declare
- #define dynarray_define knot_dynarray_define
- #define dynarray_foreach knot_dynarray_foreach
-#else
- #include <contrib/dynarray.h>
-#endif
-
// resolver includes
#include <lib/cache/api.h>
#include <lib/cache/impl.h>
#include <lib/defines.h>
#include "lib/cache/cdb_lmdb.h"
+#include "lib/generic/array.h"
#include "lib/utils.h"
#include "kr_cache_gc.h"
}
// section: rrtype list
+typedef array_t(uint16_t) rrtype_array_t;
-dynarray_declare(rrtype, uint16_t, DYNARRAY_VISIBILITY_STATIC, 64)
- dynarray_define(rrtype, uint16_t, DYNARRAY_VISIBILITY_STATIC)
-static void rrtypelist_add(rrtype_dynarray_t * arr, uint16_t add_type)
+static void rrtypelist_add(rrtype_array_t *arr, uint16_t add_type)
{
bool already_present = false;
- dynarray_foreach(rrtype, uint16_t, i, *arr) {
- if (*i == add_type) {
+ for (size_t i = 0; i < arr->len; i++) {
+ if (arr->at[i] == add_type) {
already_present = true;
break;
}
}
if (!already_present) {
- rrtype_dynarray_add(arr, &add_type);
+ kr_require(array_push(*arr, add_type) >= 0);
}
}
-static void rrtypelist_print(rrtype_dynarray_t * arr)
+static void rrtypelist_print(rrtype_array_t *arr)
{
char type_s[32] = { 0 };
- dynarray_foreach(rrtype, uint16_t, i, *arr) {
- knot_rrtype_to_string(*i, type_s, sizeof(type_s));
+ for (size_t i = 0; i < arr->len; i++) {
+ knot_rrtype_to_string(arr->at[i], type_s, sizeof(type_s));
printf(" %s", type_s);
}
printf("\n");
}
-dynarray_declare(entry, knot_db_val_t *, DYNARRAY_VISIBILITY_STATIC, 256)
- dynarray_define(entry, knot_db_val_t *, DYNARRAY_VISIBILITY_STATIC)
-static void entry_dynarray_deep_free(entry_dynarray_t * d)
+typedef array_t(knot_db_val_t *) entry_array_t;
+
+static void entry_array_deep_free(entry_array_t *d)
{
- dynarray_foreach(entry, knot_db_val_t *, i, *d) {
- free(*i);
+ for (size_t i = 0; i < d->len; i++) {
+ free(d->at[i]);
}
- entry_dynarray_free(d);
+ array_clear(*d);
}
typedef struct {
typedef struct {
category_t limit_category;
- entry_dynarray_t to_delete;
+ entry_array_t to_delete;
size_t cfg_temp_keys_space;
size_t used_space;
size_t oversize_records;
ctx->oversize_records++;
free(todelete);
} else {
- entry_dynarray_add(&ctx->to_delete, &todelete);
+ kr_require(array_push(ctx->to_delete, todelete) >= 0);
ctx->used_space = used;
}
}
to_del.limit_category = limit_category;
ret = kr_gc_cache_iter(db, cfg, cb_delete_categories, &to_del);
if (ret != KNOT_EOK) {
- entry_dynarray_deep_free(&to_del.to_delete);
+ entry_array_deep_free(&to_del.to_delete);
kr_cache_gc_free_state(state);
return ret;
}
printf
("%zu records to be deleted using %.2lf MBytes of temporary memory, %zu records skipped due to memory limit.\n",
- to_del.to_delete.size, ((double)to_del.used_space / 1048576.0),
+ to_del.to_delete.len, ((double)to_del.used_space / 1048576.0),
to_del.oversize_records);
//// 4. execute the planned deletions.
kr_timer_start(&timer_delete);
kr_timer_start(&timer_rw_txn);
- rrtype_dynarray_t deleted_rrtypes = { 0 };
+ rrtype_array_t deleted_rrtypes = { 0 };
ret = api->txn_begin(db, &txn, 0);
if (ret != KNOT_EOK) {
printf("Error starting R/W DB transaction (%s).\n",
knot_strerror(ret));
- entry_dynarray_deep_free(&to_del.to_delete);
+ entry_array_deep_free(&to_del.to_delete);
kr_cache_gc_free_state(state);
return ret;
}
- dynarray_foreach(entry, knot_db_val_t *, i, to_del.to_delete) {
- ret = api->del(&txn, *i);
+ for (size_t i = 0; i < to_del.to_delete.len; i++) {
+ knot_db_val_t *val = to_del.to_delete.at[i];
+ ret = api->del(&txn, val);
switch (ret) {
case KNOT_EOK:
deleted_records++;
- const int entry_type = kr_gc_key_consistent(**i);
+ const int entry_type = kr_gc_key_consistent(*val);
if (entry_type >= 0) // some "inconsistent" entries are OK
rrtypelist_add(&deleted_rrtypes, entry_type);
break;
if (VERBOSE_STATUS) {
// kresd normally only inserts (or overwrites),
// so it's generally suspicious when a key goes missing.
- printf("Record already gone (key len %zu): ", (*i)->len);
- debug_printbin((*i)->data, (*i)->len);
+ printf("Record already gone (key len %zu): ", val->len);
+ debug_printbin(val->data, val->len);
printf("\n");
}
break;
printf("It took %.0lf msecs, %zu transactions (%s)\n\n",
kr_timer_elapsed(&timer_delete) * 1000, rw_txn_count, knot_strerror(ret));
- rrtype_dynarray_free(&deleted_rrtypes);
- entry_dynarray_deep_free(&to_del.to_delete);
+ array_clear(deleted_rrtypes);
+ entry_array_deep_free(&to_del.to_delete);
// OK, let's close it in this case.
kr_cache_gc_free_state(state);