]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
lib/cache/top: remove temp logging, add comments, polish docs-cache-kru-8qejro/deployments/7253 cache-kru 1726/head
authorLukáš Ondráček <lukas.ondracek@nic.cz>
Fri, 18 Jul 2025 21:17:32 +0000 (23:17 +0200)
committerLukáš Ondráček <lukas.ondracek@nic.cz>
Sat, 19 Jul 2025 00:47:49 +0000 (02:47 +0200)
daemon/lua/kres-gen-33.lua
daemon/lua/kres-gen.sh
lib/cache/api.c
lib/cache/cdb_lmdb.c
lib/cache/top.c
lib/cache/top.h
lib/kru.h
lib/kru.inc.c
lib/mmapped.h
utils/cache_gc/categories.c

index a56f09c232bd4ef46dcfef0268acfd5c7d4196e6..d035b8289ccacc714952e1ff37b997db8315a5e6 100644 (file)
@@ -235,7 +235,6 @@ struct kr_extended_error {
 };
 struct kr_cache_top_context {
        uint32_t bloom[32];
-       uint32_t cnt;
 };
 struct kr_request {
        struct kr_context *ctx;
@@ -310,12 +309,25 @@ struct kr_cdb_stats {
        double usage_percent;
 };
 typedef struct uv_timer_s uv_timer_t;
+struct mmapped {
+       void *mem;
+       size_t size;
+       int fd;
+       _Bool write_lock;
+       _Bool persistent;
+};
+struct kr_cache_top {
+       struct mmapped mmapped;
+       struct top_data *data;
+       struct kr_cache_top_context *ctx;
+};
 struct kr_cache {
        kr_cdb_pt db;
        const struct kr_cdb_api *api;
        struct kr_cdb_stats stats;
        uint32_t ttl_min;
        uint32_t ttl_max;
+       struct kr_cache_top top;
        struct timeval checkpoint_walltime;
        uint64_t checkpoint_monotime;
        uv_timer_t *health_timer;
index 4647b0d4d80d431863a130100d3bb636b0e90190..129b80857de17205ab6951f98e5663daa2d5a1f0 100755 (executable)
@@ -149,6 +149,8 @@ ${CDEFS} ${LIBKRES} types <<-EOF
        typedef kr_cdb_pt
        struct kr_cdb_stats
        typedef uv_timer_t
+       struct mmapped
+       struct kr_cache_top
        struct kr_cache
        # lib/layer.h
        kr_layer_t
index 1677240bef5e529113670d126764de855e37b62c..5b0465081b9057d9d552615aed220999996cb449 100644 (file)
@@ -154,7 +154,7 @@ int kr_cache_open(struct kr_cache *cache, const struct kr_cdb_api *api, struct k
                if (opts->maxsize && (maxsize > opts->maxsize)) {
                        kr_log_warning(CACHE,
                                "Warning: real cache size is %zu instead of the requested %zu bytes, removing all data.",
-                               maxsize, opts->maxsize, fpath);
+                               maxsize, opts->maxsize);
                        cache_op(cache, clear, opts->maxsize);
                        maxsize = cache->api->get_maxsize(cache->db);
                }
index 56746c09fbed7b8bdf7aba7be85e59374ae7d547..e13f437e02dbc66f98a2645f98a847cd115c582c 100644 (file)
 #include "contrib/ucw/lib.h"
 #include "lib/cache/cdb_lmdb.h"
 #include "lib/cache/cdb_api.h"
-#include "lib/cache/top.h"
 #include "lib/utils.h"
 
-#define kr_cache_top_access_cdb(...) { if (env->is_cache) kr_cache_top_access_cdb(__VA_ARGS__); } // TODO remove
-
 /// A hacky way allowing usual usage of kr_log_error(MDB, ...)
 /// while differentiating between cache and rules in the produced logs.
 #define LOG_GRP_MDB     (env->is_cache ? LOG_GRP_CACHE     : LOG_GRP_RULES)
@@ -50,7 +47,6 @@ struct lmdb_env
        } txn;
 
        bool is_cache; /**< cache vs. rules; from struct kr_cdb_opts::is_cache */
-       struct kr_cache_top *top; // TODO remove
 
        /* Cached part of struct stat for data.mdb. */
        dev_t st_dev;
@@ -658,7 +654,6 @@ static int cdb_readv(kr_cdb_pt db, struct kr_cdb_stats *stats,
                MDB_val _key = val_knot2mdb(key[i]);
                MDB_val _val = val_knot2mdb(val[i]);
                stats->read++;
-               kr_cache_top_access_cdb(env->top, _key.mv_data, _key.mv_size, "readv");
                ret = mdb_get(txn, env->dbi, &_key, &_val);
                if (ret != MDB_SUCCESS) {
                        if (ret == MDB_NOTFOUND) {
@@ -686,7 +681,6 @@ static int cdb_write(struct lmdb_env *env, MDB_txn **txn, const knot_db_val_t *k
        MDB_val _key = val_knot2mdb(*key);
        MDB_val _val = val_knot2mdb(*val);
        stats->write++;
-       kr_cache_top_access_cdb(env->top, _key.mv_data, _key.mv_size, "write");
 
        /* This is LMDB specific optimisation,
         * if caller specifies value with NULL data and non-zero length,
@@ -779,7 +773,6 @@ static int cdb_match(kr_cdb_pt db, struct kr_cdb_stats *stats,
        MDB_val cur_key = val_knot2mdb(*key);
        MDB_val cur_val = { 0, NULL };
        stats->match++;
-       kr_cache_top_access_cdb(env->top, cur_key.mv_data, cur_key.mv_size, "match-prefix");
        ret = mdb_cursor_get(cur, &cur_key, &cur_val, MDB_SET_RANGE);
        if (ret != MDB_SUCCESS) {
                mdb_cursor_close(cur);
@@ -797,7 +790,6 @@ static int cdb_match(kr_cdb_pt db, struct kr_cdb_stats *stats,
                }
                /* Add to result set */
                if (results < maxcount) {
-                       kr_cache_top_access_cdb(env->top, cur_key.mv_data, cur_key.mv_size, "matched");
                        keyval[results][0] = val_mdb2knot(cur_key);
                        keyval[results][1] = val_mdb2knot(cur_val);
                        ++results;
@@ -832,7 +824,6 @@ static int cdb_read_leq(kr_cdb_pt db, struct kr_cdb_stats *stats,
        MDB_val key2_m = val_knot2mdb(*key);
        MDB_val val2_m = { 0, NULL };
        stats->read_leq++;
-       kr_cache_top_access_cdb(env->top, key2_m.mv_data, key2_m.mv_size, "leq-query");
        ret = mdb_cursor_get(curs, &key2_m, &val2_m, MDB_SET_RANGE);
        if (ret) goto failure;
        /* test for equality //:unlikely */
@@ -850,7 +841,6 @@ static int cdb_read_leq(kr_cdb_pt db, struct kr_cdb_stats *stats,
        ret = 1;
 success:
        /* finalize the output */
-       kr_cache_top_access_cdb(env->top, key2_m.mv_data, key2_m.mv_size, "leq");
        *key = val_mdb2knot(key2_m);
        *val = val_mdb2knot(val2_m);
        return ret;
@@ -876,12 +866,10 @@ static int cdb_read_less(kr_cdb_pt db, struct kr_cdb_stats *stats,
        MDB_val key2_m = val_knot2mdb(*key);
        MDB_val val2_m = { 0, NULL };
        stats->read_less++;
-       kr_cache_top_access_cdb(env->top, key2_m.mv_data, key2_m.mv_size, "less-query");
        // It could keep on the same `key` when MDB_PREV was used.
        ret = mdb_cursor_get(curs, &key2_m, &val2_m, MDB_PREV_NODUP);
        if (!ret) {
                /* finalize the output */
-               kr_cache_top_access_cdb(env->top, key2_m.mv_data, key2_m.mv_size, "less");
                *key = val_mdb2knot(key2_m);
                *val = val_mdb2knot(val2_m);
                return 1;
index a26e5d5b108aba8e39f12565bd3a5b4cc32a8588..372104ff4732c4f718f7e378fe69b0e4d0e0301f 100644 (file)
 #include "lib/mmapped.h"
 #include "lib/kru.h"
 
-// #ifdef LOG_GRP_MDB
-#define VERBOSE_LOG(...) printf("GC KRU " __VA_ARGS__)
-
 #define FILE_FORMAT_VERSION 1  // fail if different
 
-
 #define KRU_CAPACITY(cache_size) (cache_size / 128)   // KRU size is approx. (8 * capacity) B
        // average entry size seems to be 100-200 B,
        // make KRU capacity between cache_size/128 and cache_size/64 (power of two)
-       // -> KRU size: between cache_size/16 and cache_size/8 (cache data size is the rest)
+       // -> KRU size: between cache_size/16 and cache_size/8 (LMDB size is the rest)
 #define TICK_SEC        1
 #define NORMAL_SIZE  (150 + KR_CACHE_SIZE_OVERHEAD)  // B; normal size of cache entry
        // used as baseline for the following
@@ -32,7 +28,6 @@
        // -> rate limit: 1/2 per sec  (more frequent accesses are incomparable)
        // -> half-life:  ~5h 3min
 
-
 static inline uint32_t ticks_now(void)
 {
        struct timespec now_ts = {0};
@@ -40,8 +35,9 @@ static inline uint32_t ticks_now(void)
        return now_ts.tv_sec / TICK_SEC;
 }
 
-static inline bool first_access_ro(struct kr_cache_top_context *ctx, kru_hash_t hash) {
-       // struct kr_cache_top_context { uint64_t bloom[4]; }
+static inline bool first_access_ro(struct kr_cache_top_context *ctx, kru_hash_t hash)
+{
+       // struct kr_cache_top_context { uint32_t bloom[32]; }
        static_assert(sizeof(((struct kr_cache_top_context *)0)->bloom[0]) * 8 == 32);
        static_assert(sizeof(((struct kr_cache_top_context *)0)->bloom)    * 8 == 32 * 32);
                // expected around 40 unique cache accesses per request context, possibly up to ~200;
@@ -61,28 +57,13 @@ static inline bool first_access_ro(struct kr_cache_top_context *ctx, kru_hash_t
        return !accessed;
 }
 
-static inline bool first_access(struct kr_cache_top_context *ctx, kru_hash_t hash, bool *overfull) {
+static inline bool first_access(struct kr_cache_top_context *ctx, kru_hash_t hash)
+{
        if (!first_access_ro(ctx, hash)) return false;
 
        uint8_t *h = (uint8_t *)&hash;
        static_assert(sizeof(kru_hash_t) >= 8);
 
-       { // temporal statistics, TODO remove
-               int ones = 0;
-               for (int i = 0; i < 32; i++) {
-                       ones += __builtin_popcount(ctx->bloom[i]);
-               }
-               double collision_prob = ones / 1024.0; // 1-bit collision
-               collision_prob *= collision_prob;      // 2-bit collision
-               collision_prob *= collision_prob;      // 4-bit collision
-
-               if (collision_prob > 0.1) {
-                       VERBOSE_LOG("BLOOM %d unique accesses, collision prob. %5.3f %% (%d/1024 ones)\n", ctx->cnt, 100.0 * collision_prob, ones);
-                       *overfull = true;
-               }
-               ctx->cnt++;
-       }
-
        ctx->bloom[h[0] % 32] |= 1u << (h[1] % 32);
        ctx->bloom[h[2] % 32] |= 1u << (h[3] % 32);
        ctx->bloom[h[4] % 32] |= 1u << (h[5] % 32);
@@ -93,7 +74,6 @@ static inline bool first_access(struct kr_cache_top_context *ctx, kru_hash_t has
        return true;
 }
 
-
 static inline void get_size_capacity(size_t cache_size, size_t *top_size, size_t *capacity_log)
 {
        *top_size = 0;
@@ -105,7 +85,7 @@ static inline void get_size_capacity(size_t cache_size, size_t *top_size, size_t
        *top_size = offsetof(struct top_data, kru) + KRU.get_size(*capacity_log);
 }
 
-int kr_cache_top_get_size(size_t cache_size)
+size_t kr_cache_top_get_size(size_t cache_size)
 {
        size_t top_size, capacity_log;
        get_size_capacity(cache_size, &top_size, &capacity_log);
@@ -119,9 +99,6 @@ int kr_cache_top_init(struct kr_cache_top *top, char *mmap_file, size_t cache_si
                get_size_capacity(cache_size, &size, &capacity_log);
        } // else use existing file settings
 
-       VERBOSE_LOG("INIT, cache size %d, KRU capacity_log %d\n", cache_size, capacity_log);
-
-
        struct top_data header = {
                .version          = (FILE_FORMAT_VERSION << 1) | kru_using_avx2(),
                .base_price_norm  = BASE_PRICE * NORMAL_SIZE,
@@ -139,20 +116,17 @@ int kr_cache_top_init(struct kr_cache_top *top, char *mmap_file, size_t cache_si
                header_size = offsetof(struct top_data, base_price_norm);
        }
 
-       VERBOSE_LOG("INIT mmapped_init\n");
        int state = mmapped_init(&top->mmapped, mmap_file, size, &header, header_size, true);
        top->data = top->mmapped.mem;
        bool using_existing = false;
 
        // try using existing data
        if ((state >= 0) && (state & MMAPPED_EXISTING)) {
-               if (!KRU.check_size((struct kru *)top->data->kru, top->mmapped.size - offsetof(struct top_data, kru))) {
-                       VERBOSE_LOG("INIT reset, wrong size\n");
+               if (!KRU.check_size((struct kru *)top->data->kru, (ptrdiff_t)top->mmapped.size - offsetof(struct top_data, kru))) {
                        state = mmapped_init_reset(&top->mmapped, mmap_file, size, &header, header_size);
                        top->data = top->mmapped.mem;
                } else {
                        using_existing = true;
-                       VERBOSE_LOG("INIT finish existing\n");
                        state = mmapped_init_finish(&top->mmapped);
                }
        }
@@ -164,9 +138,8 @@ int kr_cache_top_init(struct kr_cache_top *top, char *mmap_file, size_t cache_si
                        state = kr_error(EINVAL);
                        goto fail;
                }
-               kr_assert(KRU.check_size((struct kru *)top->data->kru, top->mmapped.size - offsetof(struct top_data, kru)));
+               kr_assert(KRU.check_size((struct kru *)top->data->kru, (ptrdiff_t)top->mmapped.size - offsetof(struct top_data, kru)));
 
-               VERBOSE_LOG("INIT finish new\n");
                state = mmapped_init_finish(&top->mmapped);
        }
 
@@ -180,13 +153,13 @@ int kr_cache_top_init(struct kr_cache_top *top, char *mmap_file, size_t cache_si
        return 0;
 
 fail:
-       VERBOSE_LOG("INIT error, deinit\n");
        kr_cache_top_deinit(top);
        kr_log_crit(SYSTEM, "Initialization of cache top failed.\n");
        return state;
 }
 
-void kr_cache_top_deinit(struct kr_cache_top *top) {
+void kr_cache_top_deinit(struct kr_cache_top *top)
+{
        top->data = NULL;
        mmapped_deinit(&top->mmapped);
 }
@@ -194,8 +167,10 @@ void kr_cache_top_deinit(struct kr_cache_top *top) {
 /* text mode: '\0' -> '|'
  * hex bytes: <x00010203x>
  * decimal bytes: <0.1.2.3>
+ * CACHE_KEY_DEF
  */
-char *kr_cache_top_strkey(void *key, size_t len) {
+char *kr_cache_top_strkey(void *key, size_t len)
+{
        static char str[4 * KR_CACHE_KEY_MAXLEN + 1];
        if (4 * len + 1 > sizeof(str)) len = (sizeof(str) - 1) / 4;
        unsigned char *k = key;
@@ -263,26 +238,13 @@ char *kr_cache_top_strkey(void *key, size_t len) {
 
 void kr_cache_top_access(struct kr_cache_top *top, void *key, size_t key_len, size_t data_size, char *debug_label)
 {
-       bool bloom_overfull = false; // XXX tmp
        kru_hash_t hash = KRU.hash_bytes((struct kru *)&top->data->kru, (uint8_t *)key, key_len);
-       const bool unique = top->ctx ? first_access(top->ctx, hash, &bloom_overfull) : true;
-       const size_t size = kr_cache_top_entry_size(key_len, data_size);
-       if (unique) {
-               const kru_price_t price = kr_cache_top_entry_price(top, size);
-               KRU.load_hash((struct kru *)&top->data->kru, ticks_now(), hash, price);
-       }
-       if (bloom_overfull) {
-               VERBOSE_LOG("ACCESS %-19s%4d B %-5s  %s\n", debug_label, size,
-                               !top->ctx ? "NO_CTX" : unique ? "" : "SKIP",
-                               kr_cache_top_strkey(key, key_len));
-       }
-}
-
-// temporal logging one level under _access
-void kr_cache_top_access_cdb(struct kr_cache_top *top, void *key, size_t len, char *debug_label)
-{
+       const bool unique = top->ctx ? first_access(top->ctx, hash) : true;
+       if (!unique) return;
 
-       // VERBOSE_LOG("ACCESS   %-17s %s\n", debug_label, kr_cache_top_strkey(key, len));
+       const size_t size = kr_cache_top_entry_size(key_len, data_size);
+       const kru_price_t price = kr_cache_top_entry_price(top, size);
+       KRU.load_hash((struct kru *)&top->data->kru, ticks_now(), hash, price);
 }
 
 struct kr_cache_top_context *kr_cache_top_context_switch(struct kr_cache_top *top,
@@ -293,10 +255,8 @@ struct kr_cache_top_context *kr_cache_top_context_switch(struct kr_cache_top *to
        return old_ctx;
 }
 
-uint16_t kr_cache_top_load(struct kr_cache_top *top, void *key, size_t len) {
+uint16_t kr_cache_top_load(struct kr_cache_top *top, void *key, size_t len)
+{
        kru_hash_t hash = KRU.hash_bytes((struct kru *)&top->data->kru, (uint8_t *)key, len);
-       uint16_t load = KRU.load_hash((struct kru *)&top->data->kru, ticks_now(), hash, 0);
-
-       // VERBOSE_LOG("LOAD %s -> %d\n", kr_cache_top_strkey(key, len), load);
-       return load;
+       return KRU.load_hash((struct kru *)&top->data->kru, ticks_now(), hash, 0);
 }
index c6eb920cbefe54c0d77b419dd8f08a79740fd0cc..9917d9fc5b3feedf761f8206202ef9c22ac95418 100644 (file)
@@ -2,21 +2,33 @@
  *  SPDX-License-Identifier: GPL-3.0-or-later
  */
 
+/// Top uses KRU to maintain statistics about recently used cache entries
+/// for deciding what to evict during garbage collection.
+///
+/// The statistics are stored persistently beside LMDB data file
+/// and their half-life is currently 5 hours, taking ~3-day traffic into account.
+/// Each accessed cache entry is counted only once within a single request context
+/// and the price of the access is inversely proportional to the size of the cache entry;
+/// thus accesses per byte are the measure.
+///
+/// The keys currently stored in KRU and in cache need not necessarily correspond.
+/// It is possible that a key is reinserted into cache after it was previously evicted
+/// likely due to the expired TTL, but still has high load assinged in KRU.
+/// Or that the KRU load of a key decreased to zero after hours or days of inactivity,
+/// but there was no need to remove the (possibly expired) entry from the cache.
+
 #pragma once
 #include "lib/mmapped.h"
 #include "lib/kru.h"
 
+/// Data related to open cache.
 struct kr_cache_top {
        struct mmapped mmapped;
        struct top_data *data;
        struct kr_cache_top_context *ctx;
 };
 
-struct kr_cache_top_context {
-       uint32_t bloom[32]; // size of just one cache-line, but probably not aligned (neither kr_request is)
-       uint32_t cnt;  // TODO remove this (and propagate to kres-gen)
-};
-
+/// Part of the previous, shared between all processes.
 struct top_data {
        uint32_t version;
        uint32_t base_price_norm;
@@ -24,36 +36,63 @@ struct top_data {
        _Alignas(64) uint8_t kru[];
 };
 
+/// Part of kr_request to avoid counting repeated cache accesses multiple times during single request.
+struct kr_cache_top_context {
+       uint32_t bloom[32];
+};
+
 #define KR_CACHE_SIZE_OVERHEAD  16 // B, just guess, probably more; size = key + data + DB overhead
 
+/// Approximate size of a cache entry.
 static inline size_t kr_cache_top_entry_size(size_t key_len, size_t data_size) {
        return key_len + data_size + KR_CACHE_SIZE_OVERHEAD;
 }
+
+/// Price of a cache entry access in KRU based on the entry size.
 static inline kru_price_t kr_cache_top_entry_price(struct kr_cache_top *top, size_t size) {
        return top->data->base_price_norm / size;
 }
 
+/// Size of the top data as part of the cache size, LMDB should occupy the rest;
+/// currently between 6 and 13 %.
 KR_EXPORT
-int kr_cache_top_get_size(size_t cache_size);
+size_t kr_cache_top_get_size(size_t cache_size);
 
+/// Initialize memory shared between processes, possibly using existing data in mmap_file.
+/// If cache_size differs from the previously used value, the data are cleared,
+/// otherwise they are persistent across restarts.
 KR_EXPORT
 int kr_cache_top_init(struct kr_cache_top *top, char *mmap_file, size_t cache_size);
 
+/// Deinitialize shared memory, keeping the data stored in file.
 KR_EXPORT
 void kr_cache_top_deinit(struct kr_cache_top *top);
 
-KR_EXPORT
-void kr_cache_top_access_cdb(struct kr_cache_top *top, void *key, size_t len, char *debug_label); // temporal, TODO remove
-
+/// Charge cache access to the accessed key
+/// unless it was already accessed in the current request context.
 KR_EXPORT
 void kr_cache_top_access(struct kr_cache_top *top, void *key, size_t key_len, size_t data_size, char *debug_label);
+       // debug_label is currently not used, TODO remove?
 
+/// Get current KRU load value assigned to the given cache entry key.
 KR_EXPORT
 uint16_t kr_cache_top_load(struct kr_cache_top *top, void *key, size_t len);
 
-// ctx has to be kept valid until next call
+/// Switch request context; the ctx has to be kept valid until next call.
+/// The context of a new kr_request has to be initialized with zeroes.
+/// Use NULL as ctx to stop using current context;
+/// all cache accesses in such a state are considered unique,
+/// but no such access is expected to happen.
+/// Returns the previous context.
 KR_EXPORT
 struct kr_cache_top_context *kr_cache_top_context_switch(struct kr_cache_top *top, struct kr_cache_top_context *ctx, char *debug_label);
+       // debug_label is currently not used, TODO remove?
 
+/// Return readable string representation of a cache key in a statically allocated memory.
+/// By default printable characters are kept unchanged and NULL-bytes are printed as '|'.
+/// Where numeric values are expected (CACHE_KEY_DEF) or non-printable characters occur,
+/// either decimal bytes in form <0.1.2> or hexadecimal in form <x000102x> are printed.
+/// Decimal form is used for RRTYPEs and IPv4; hexadecimal for NSEC3 hashes, IPv6
+/// and unexpected unprintable characters or '|', '<', '>' for unambiguity.
 KR_EXPORT
 char *kr_cache_top_strkey(void *key, size_t len);
index bad258695a6df598f9b459fbac16095405689db6..31149d51ab6ea8b1a554f8140bf74963fd8a6d12 100644 (file)
--- a/lib/kru.h
+++ b/lib/kru.h
@@ -67,7 +67,7 @@ struct kru_api {
        /// Verify that given KRU structure expects just memory of the given size;
        /// it accesses just the first size bytes of kru.
        /// If false is returned, the memory is corrupted and calling other methods may cause SIGSEGV.
-       bool (*check_size)(struct kru *kru, size_t size);
+       bool (*check_size)(struct kru *kru, ptrdiff_t size);
 
        /// Determine if a key should get limited (and update the KRU).
        /// key needs to be aligned to a multiple of 16 bytes.
@@ -107,10 +107,13 @@ struct kru_api {
        void (*load_multi_prefix)(struct kru *kru, uint32_t time_now,
                        uint8_t namespace, uint8_t key[static 16], uint8_t *prefixes, kru_price_t *prices, size_t queries_cnt, uint16_t *loads_out);
 
-       // TODO
-       /// Compute 64-bit hash to be used in load_hash.
+       /// Compute 64-bit hash of an arbitrary-size byte array to be used in load_hash function.
        /// The key need not to be aligned as we use always unoptimized variant here.
        kru_hash_t (*hash_bytes)(struct kru *kru, uint8_t *key, size_t key_size);
+
+       /// Single query based on the hash computed by the previous function.
+       /// Returns the final value of the counter normalized to the limit 2^16.
+       /// Set price to zero to skip updating; otherwise, KRU is always updated, using maximal allowed value on overflow.
        uint16_t (*load_hash)(struct kru *kru, uint32_t time_now, kru_hash_t hash, kru_price_t price);
 };
 
index 1e3c77c0b13c1d49a06433e3f2aff44015653ec0..cc972f1e54f8570cd8b8d275b22039cd989ab0b7 100644 (file)
@@ -203,7 +203,8 @@ static size_t kru_get_size(int capacity_log)
                    + sizeof(struct load_cl) * TABLE_COUNT * (1 << loads_bits);
 }
 
-static bool kru_check_size(struct kru *kru, size_t size) {
+static bool kru_check_size(struct kru *kru, ptrdiff_t size)
+{
        if (size < sizeof(struct kru)) return false;
        return size == kru_get_size(kru->loads_bits + LOADS_CAPACITY_SHIFT);
 }
@@ -355,7 +356,8 @@ static inline void kru_limited_prefetch_prefix(struct kru *kru, uint32_t time_no
        ctx->id = hash;
 }
 
-static kru_hash_t kru_hash_bytes(struct kru *kru, uint8_t *key, size_t key_size) {
+static kru_hash_t kru_hash_bytes(struct kru *kru, uint8_t *key, size_t key_size)
+{
        // Obtain hash of *buf.
        kru_hash_t hash;
        static_assert(sizeof(kru_hash_t) * 8 <= 64);
index 39f40f63bc6a90f0f1c0c1b7b99443553de9d1fd..c39bc60bad3d5c467e24018310df60155b3d2693 100644 (file)
@@ -106,7 +106,7 @@ void mmapped_deinit(struct mmapped *mmapped);
                        mmapped_init_finish
                }
                if (<0) fail + return
-               assert(==0) // if both _finish above were used
+               assertion (==0) // if both _finish above were used
                // done
 
        non-persistent case:
@@ -119,7 +119,7 @@ void mmapped_deinit(struct mmapped *mmapped);
                        mmapped_init_finish
                }
                if (<0) fail + return
-               assert(==0) // no other outcome if both _finish above were used
+               assertion (==0) // no other outcome if both _finish above were used
                // done
 */
 
index ec1aa773178dbaa0958c1877008b24ea5981c4e4..f8946df5d5c00a1ae89c260ba88b1a824d6bacf5 100644 (file)
@@ -6,28 +6,8 @@
 #include "lib/cache/top.h"
 #include "utils/cache_gc/db.h"
 
-static bool rrtype_is_infrastructure(uint16_t r)  // currently unused
+static inline int load2cat(uint16_t load)  // -> 0..64, reversed
 {
-       switch (r) {
-       case KNOT_RRTYPE_NS:
-       case KNOT_RRTYPE_DS:
-       case KNOT_RRTYPE_DNSKEY:
-       case KNOT_RRTYPE_A:
-       case KNOT_RRTYPE_AAAA:
-               return true;
-       default:
-               return false;
-       }
-}
-
-static unsigned int get_random(int to)  // currently unused
-{
-       // We don't need these to be really unpredictable,
-       // but this should be cheap enough not to be noticeable.
-       return kr_rand_bytes(1) % to;
-}
-
-static inline int load2cat(uint16_t load) { // 0..64, reversed
        const uint32_t load32 = ((uint32_t)load << 16) | 0xFFFF;
        const int leading_zeroes = __builtin_clz(load32);  // 0..16
        const int logss2 =  //  0, 4, 6, 8..64; approx of log with base 2^{1/4}
@@ -41,21 +21,19 @@ category_t kr_gc_categorize(struct kr_cache_top *top, gc_record_info_t * info, v
 {
        category_t res; // 0..(CATEGORIES - 1), highest will be dropped first
 
-       if (!info->valid)
+       if (!info->valid) {
+               // invalid entries will be evicted first
                return CATEGORIES - 1;
+       }
 
        uint16_t load = kr_cache_top_load(top, key, key_len);
        res = load2cat(load);  // 0..64
 
-       if (info->rrtype == KNOT_CACHE_RTT) {
-               // TODO some correction here?
-       } else {
-               if (info->expires_in <= 0) {
-                       // evict all expired before any non-expired
-                       res = res / 2 + 65;  // 65..94
-               }
+       if ((info->rrtype != KNOT_CACHE_RTT) && (info->expires_in <= 0)) {
+               // evict all expired before any non-expired (incl. RTT)
+               res = res / 2 + 65;  // 65..97
        }
-       static_assert(CATEGORIES - 1 > 94);
+       static_assert(CATEGORIES - 1 > 97);
 
        const kru_price_t price = kr_cache_top_entry_price(top, info->entry_size);
        const double accesses = (double)((kru_price_t)load << (KRU_PRICE_BITS - 16)) / price;