#include <lib/cache/impl.h>
//#include <lib/defines.h>
-#include <ctype.h> //DEBUG
+#include <ctype.h> //DEBUG
#include <time.h>
#include <sys/stat.h>
-struct libknot_lmdb_env
-{
+struct libknot_lmdb_env {
bool shared;
unsigned dbi;
void *env;
knot_mm_t *pool;
};
-struct kres_lmdb_env
-{
+struct kres_lmdb_env {
size_t mapsize;
unsigned dbi;
void *env;
// sub-struct txn ommited
};
-static knot_db_t *knot_db_t_kres2libknot(const knot_db_t *db)
+static knot_db_t *knot_db_t_kres2libknot(const knot_db_t * db)
{
- const struct kres_lmdb_env *kres_db = db; // this is struct lmdb_env as in resolver/cdb_lmdb.c
+ const struct kres_lmdb_env *kres_db = db; // this is struct lmdb_env as in resolver/cdb_lmdb.c
struct libknot_lmdb_env *libknot_db = malloc(sizeof(*libknot_db));
if (libknot_db != NULL) {
libknot_db->shared = false;
return libknot_db;
}
-int kr_gc_cache_open(const char *cache_path, struct kr_cache *kres_db, knot_db_t **libknot_db)
+int kr_gc_cache_open(const char *cache_path, struct kr_cache *kres_db,
+ knot_db_t ** libknot_db)
{
char cache_data[strlen(cache_path) + 10];
snprintf(cache_data, sizeof(cache_data), "%s/data.mdb", cache_path);
struct stat st = { 0 };
- if (stat(cache_path, &st) || !(st.st_mode & S_IFDIR) || stat(cache_data, &st)) {
+ if (stat(cache_path, &st) || !(st.st_mode & S_IFDIR)
+ || stat(cache_data, &st)) {
printf("Error: %s does not exist or is not a LMDB.\n", cache_path);
return -ENOENT;
}
return 0;
}
-void kr_gc_cache_close(struct kr_cache *kres_db, knot_db_t *knot_db)
+void kr_gc_cache_close(struct kr_cache *kres_db, knot_db_t * knot_db)
{
free(knot_db);
kr_cache_close(kres_db);
ssize_t i;
/* CACHE_KEY_DEF */
if (key.len >= 2 && kd[0] == '\0') {
- /* Beware: root zone is special and starts with
+ /* Beware: root zone is special and starts with
* a single \0 followed by type sign */
- i = 1;
+ i = 1;
} else {
/* find the first double zero in the key */
- for (i = 2; kd[i - 1] || kd[i - 2]; ++i) {
- if (i >= key.len)
- return NULL;
- }
+ for (i = 2; kd[i - 1] || kd[i - 2]; ++i) {
+ if (i >= key.len)
+ return NULL;
+ }
}
// the next character can be used for classification
switch (kd[i]) {
assert(!EINVAL);
return NULL;
}
- return (uint16_t *)&kd[i + 1];
+ return (uint16_t *) & kd[i + 1];
case '1':
return &NSEC1;
case '3':
}
/// expects that key is consistent! CACHE_KEY_DEF
-static uint8_t entry_labels(knot_db_val_t *key, uint16_t rrtype)
+static uint8_t entry_labels(knot_db_val_t * key, uint16_t rrtype)
{
uint8_t lab = 0, *p = key->data;
while (*p != 0) {
while (*p++ != 0) {
- if (p - (uint8_t *)key->data >= key->len) {
+ if (p - (uint8_t *) key->data >= key->len) {
return 0;
}
}
}
#ifdef DEBUG
-void debug_printbin(const char *str, unsigned int len) {
+void debug_printbin(const char *str, unsigned int len)
+{
putchar('"');
for (int idx = 0; idx < len; idx++) {
char c = str[idx];
#endif
/** Return one entry_h reference from a cache DB value. NULL if not consistent/suitable. */
-static const struct entry_h * val2entry(const knot_db_val_t val, uint16_t ktype)
+static const struct entry_h *val2entry(const knot_db_val_t val, uint16_t ktype)
{
if (ktype != KNOT_RRTYPE_NS)
return entry_h_consistent(val, ktype);
return NULL;
}
-int kr_gc_cache_iter(knot_db_t *knot_db, kr_gc_iter_callback callback, void *ctx)
+int kr_gc_cache_iter(knot_db_t * knot_db, kr_gc_iter_callback callback, void *ctx)
{
#ifdef DEBUG
unsigned int counter_iter = 0;
info.entry_size = key.len + val.len;
info.valid = false;
- const uint16_t *entry_type = ret == KNOT_EOK ? kr_gc_key_consistent(key) : NULL;
+ const uint16_t *entry_type =
+ ret == KNOT_EOK ? kr_gc_key_consistent(key) : NULL;
const struct entry_h *entry = NULL;
if (entry_type != NULL) {
#ifdef DEBUG
}
#ifdef DEBUG
counter_kr_consistent += info.valid;
- if (!entry_type || !entry) { // don't log fully consistent entries
- printf("GC %sconsistent, KR %sconsistent, size %zu, key len %zu: ",
- entry_type ? "" : "in", entry ? "" : "IN",
- (key.len + val.len), key.len);
+ if (!entry_type || !entry) { // don't log fully consistent entries
+ printf
+ ("GC %sconsistent, KR %sconsistent, size %zu, key len %zu: ",
+ entry_type ? "" : "in", entry ? "" : "IN",
+ (key.len + val.len), key.len);
debug_printbin(key.data, key.len);
printf("\n");
}
ret = callback(&key, &info, ctx);
if (ret != KNOT_EOK) {
- printf("Error iterating database (%s).\n", knot_strerror(ret));
+ printf("Error iterating database (%s).\n",
+ knot_strerror(ret));
api->iter_finish(it);
api->txn_abort(&txn);
return ret;
api->txn_abort(&txn);
#ifdef DEBUG
- printf("DEBUG: iterated %u items, gc consistent %u, kr consistent %u\n", counter_iter, counter_gc_consistent, counter_kr_consistent);
+ printf("DEBUG: iterated %u items, gc consistent %u, kr consistent %u\n",
+ counter_iter, counter_gc_consistent, counter_kr_consistent);
#endif
return KNOT_EOK;
}
typedef struct timespec gc_timer_t;
static gc_timer_t gc_timer_internal = { 0 };
-static void gc_timer_start(gc_timer_t *t)
+static void gc_timer_start(gc_timer_t * t)
{
(void)clock_gettime(CLOCK_MONOTONIC, t == NULL ? &gc_timer_internal : t);
}
-static double gc_timer_end(gc_timer_t *t)
+static double gc_timer_end(gc_timer_t * t)
{
gc_timer_t *start = t == NULL ? &gc_timer_internal : t;
gc_timer_t end = { 0 };
(void)clock_gettime(CLOCK_MONOTONIC, &end);
- return (((double)end.tv_sec - (double)start->tv_sec) + ((double)end.tv_nsec - (double)start->tv_nsec) / 1e9);
+ return (((double)end.tv_sec - (double)start->tv_sec) +
+ ((double)end.tv_nsec - (double)start->tv_nsec) / 1e9);
}
-static unsigned long gc_timer_usecs(gc_timer_t *t)
+static unsigned long gc_timer_usecs(gc_timer_t * t)
{
gc_timer_t *start = t == NULL ? &gc_timer_internal : t;
gc_timer_t end = { 0 };
(void)clock_gettime(CLOCK_MONOTONIC, &end);
- return ((end.tv_sec - start->tv_sec) * 1000000UL + (end.tv_nsec - start->tv_nsec) / 1000UL);
+ return ((end.tv_sec - start->tv_sec) * 1000000UL +
+ (end.tv_nsec - start->tv_nsec) / 1000UL);
}
// section: dbval_copy
-static knot_db_val_t *dbval_copy(const knot_db_val_t *from)
+static knot_db_val_t *dbval_copy(const knot_db_val_t * from)
{
knot_db_val_t *to = malloc(sizeof(knot_db_val_t) + from->len);
if (to != NULL) {
memcpy(to, from, sizeof(knot_db_val_t));
- to->data = to + 1; // == ((uit8_t *)to) + sizeof(knot_db_val_t)
+ to->data = to + 1; // == ((uit8_t *)to) + sizeof(knot_db_val_t)
memcpy(to->data, from->data, from->len);
}
return to;
// section: rrtype list
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)
+ dynarray_define(rrtype, uint16_t, DYNARRAY_VISIBILITY_STATIC)
+static void rrtypelist_add(rrtype_dynarray_t * arr, uint16_t add_type)
{
bool already_present = false;
dynarray_foreach(rrtype, uint16_t, i, *arr) {
}
}
-static void rrtypelist_print(rrtype_dynarray_t *arr)
+static void rrtypelist_print(rrtype_dynarray_t * arr)
{
char type_s[32] = { 0 };
dynarray_foreach(rrtype, uint16_t, i, *arr) {
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)
+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)
{
- dynarray_foreach(entry, knot_db_val_t*, i, *d) {
+ dynarray_foreach(entry, knot_db_val_t *, i, *d) {
free(*i);
}
entry_dynarray_free(d);
size_t records;
} ctx_compute_categories_t;
-int cb_compute_categories(const knot_db_val_t *key, gc_record_info_t *info, void *vctx)
+int cb_compute_categories(const knot_db_val_t * key, gc_record_info_t * info,
+ void *vctx)
{
ctx_compute_categories_t *ctx = vctx;
category_t cat = kr_gc_categorize(info);
size_t oversize_records;
} ctx_delete_categories_t;
-int cb_delete_categories(const knot_db_val_t *key, gc_record_info_t *info, void *vctx)
+int cb_delete_categories(const knot_db_val_t * key, gc_record_info_t * info,
+ void *vctx)
{
ctx_delete_categories_t *ctx = vctx;
category_t cat = kr_gc_categorize(info);
knot_db_val_t *todelete = dbval_copy(key);
size_t used = ctx->used_space + key->len + sizeof(*key);
if ((ctx->cfg_temp_keys_space > 0 &&
- used > ctx->cfg_temp_keys_space) ||
- todelete == NULL) {
+ used > ctx->cfg_temp_keys_space) || todelete == NULL) {
ctx->oversize_records++;
} else {
entry_dynarray_add(&ctx->to_delete, &todelete);
return KNOT_EOK;
}
-int kr_cache_gc(kr_cache_gc_cfg_t *cfg)
+int kr_cache_gc(kr_cache_gc_cfg_t * cfg)
{
struct kr_cache kres_db = { 0 };
knot_db_t *db = NULL;
const size_t db_size = knot_db_lmdb_get_mapsize(db);
const size_t db_usage_abs = knot_db_lmdb_get_usage(db);
const double db_usage = (double)db_usage_abs / db_size * 100.0;
-#if 0 // Probably not worth it, better reduce the risk by checking more often.
+#if 0 // Probably not worth it, better reduce the risk by checking more often.
if (db_usage > 90.0) {
free(*libknot_db);
kr_cache_close(kres_db);
opts.maxsize = cache_size;
goto open_kr_cache;
}
-# endif
+#endif
const bool large_usage = db_usage >= cfg->cache_max_usage;
- if (cfg->dry_run || large_usage) { // don't print this on every size check
- printf("Usage: %.2lf%% (%zu / %zu)\n", db_usage, db_usage_abs, db_size);
+ if (cfg->dry_run || large_usage) { // don't print this on every size check
+ printf("Usage: %.2lf%% (%zu / %zu)\n", db_usage, db_usage_abs,
+ db_size);
}
if (cfg->dry_run || !large_usage) {
kr_gc_cache_close(&kres_db, db);
return KNOT_EOK;
}
- gc_timer_t timer_analyze = { 0 }, timer_choose = { 0 }, timer_delete = { 0 }, timer_rw_txn = { 0 };
+ gc_timer_t timer_analyze = { 0 }, timer_choose = { 0 }, timer_delete =
+ { 0 }, timer_rw_txn = { 0 };
gc_timer_start(&timer_analyze);
- ctx_compute_categories_t cats = {{ 0 }};
+ ctx_compute_categories_t cats = { { 0 }
+ };
ret = kr_gc_cache_iter(db, cb_compute_categories, &cats);
if (ret != KNOT_EOK) {
kr_gc_cache_close(&kres_db, db);
cats_sumsize += cats.categories_sizes[i];
}
ssize_t amount_tofree = knot_db_lmdb_get_mapsize(db) * cfg->cache_to_be_freed
- * cats_sumsize / (100 * knot_db_lmdb_get_usage(db));
+ * cats_sumsize / (100 * knot_db_lmdb_get_usage(db));
#ifdef DEBUG
printf("tofree: %zd\n", amount_tofree);
for (int i = 0; i < CATEGORIES; i++) {
if (cats.categories_sizes[i] > 0) {
- printf("category %d size %zu\n", i, cats.categories_sizes[i]);
+ printf("category %d size %zu\n", i,
+ cats.categories_sizes[i]);
}
}
#endif
amount_tofree -= cats.categories_sizes[--limit_category];
}
- printf("Cache analyzed in %.2lf secs, %zu records, limit category is %d.\n", gc_timer_end(&timer_analyze), cats.records, limit_category);
+ printf("Cache analyzed in %.2lf secs, %zu records, limit category is %d.\n",
+ gc_timer_end(&timer_analyze), cats.records, limit_category);
gc_timer_start(&timer_choose);
ctx_delete_categories_t to_del = { 0 };
kr_gc_cache_close(&kres_db, db);
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.oversize_records);
+ 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.oversize_records);
const knot_db_api_t *api = knot_db_lmdb_api();
knot_db_txn_t txn = { 0 };
ret = api->txn_begin(db, &txn, 0);
if (ret != KNOT_EOK) {
- printf("Error starting R/W DB transaction (%s).\n", knot_strerror(ret));
+ printf("Error starting R/W DB transaction (%s).\n",
+ knot_strerror(ret));
entry_dynarray_deep_free(&to_del.to_delete);
kr_gc_cache_close(&kres_db, db);
return ret;
}
- dynarray_foreach(entry, knot_db_val_t*, i, to_del.to_delete) {
+ dynarray_foreach(entry, knot_db_val_t *, i, to_del.to_delete) {
ret = api->del(&txn, *i);
switch (ret) {
case KNOT_EOK:
already_gone++;
break;
default:
- printf("Warning: skipping deletion because of error (%s)\n", knot_strerror(ret));
+ printf("Warning: skipping deletion because of error (%s)\n",
+ knot_strerror(ret));
api->txn_abort(&txn);
ret = api->txn_begin(db, &txn, 0);
if (ret != KNOT_EOK) {
- printf("Error: can't begin txn because of error (%s)\n", knot_strerror(ret));
+ printf
+ ("Error: can't begin txn because of error (%s)\n",
+ knot_strerror(ret));
goto finish;
}
continue;
ret = api->txn_begin(db, &txn, 0);
}
if (ret != KNOT_EOK) {
- printf("Error: transaction failed (%s)\n", knot_strerror(ret));
+ printf("Error: transaction failed (%s)\n",
+ knot_strerror(ret));
goto finish;
}
}
ret = api->txn_commit(&txn);
finish:
- printf("Deleted %zu records (%zu already gone) types", deleted_records, already_gone);
+ printf("Deleted %zu records (%zu already gone) types", deleted_records,
+ already_gone);
rrtypelist_print(&deleted_rrtypes);
- printf("It took %.2lf secs, %zu transactions (%s)\n", gc_timer_end(&timer_delete), rw_txn_count, knot_strerror(ret));
+ printf("It took %.2lf secs, %zu transactions (%s)\n",
+ gc_timer_end(&timer_delete), rw_txn_count, knot_strerror(ret));
rrtype_dynarray_free(&deleted_rrtypes);
entry_dynarray_deep_free(&to_del.to_delete);