From: Petr Špaček Date: Tue, 25 Jun 2019 11:00:22 +0000 (+0200) Subject: gc: delete inconsistent entries from cache instead of skipping them X-Git-Tag: v4.1.0^2~15 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0b6748aa8bcdba5087e9903a200769a9ed010065;p=thirdparty%2Fknot-resolver.git gc: delete inconsistent entries from cache instead of skipping them --- diff --git a/utils/cache_gc/categories.c b/utils/cache_gc/categories.c index b50cffc1b..c64f6d20a 100644 --- a/utils/cache_gc/categories.c +++ b/utils/cache_gc/categories.c @@ -28,6 +28,8 @@ static int get_random(int to) category_t kr_gc_categorize(gc_record_info_t *info) { category_t res = 60; + if (!info->valid) + return CATEGORIES - 1; switch (info->no_labels) { case 0: diff --git a/utils/cache_gc/db.c b/utils/cache_gc/db.c index 5054d3f2c..e5ba3b89d 100644 --- a/utils/cache_gc/db.c +++ b/utils/cache_gc/db.c @@ -1,3 +1,5 @@ +// #define DEBUG 1 + #include "db.h" #include @@ -129,8 +131,28 @@ static uint8_t entry_labels(knot_db_val_t *key, uint16_t rrtype) return lab; } +#ifdef DEBUG +void debug_printbin(const char *str, unsigned int len) { + putchar('"'); + for (int idx = 0; idx < len; idx++) { + char c = str[idx]; + if (isprint(c)) + putchar(c); + else + printf("`%02x`", c); + } + putchar('"'); +} +#endif + int kr_gc_cache_iter(knot_db_t *knot_db, kr_gc_iter_callback callback, void *ctx) { +#ifdef DEBUG + unsigned int counter_iter = 0; + unsigned int counter_gc_consistent = 0; + unsigned int counter_kr_consistent = 0; +#endif + knot_db_txn_t txn = { 0 }; knot_db_iter_t *it = NULL; const knot_db_api_t *api = knot_db_lmdb_api(); @@ -160,20 +182,34 @@ int kr_gc_cache_iter(knot_db_t *knot_db, kr_gc_iter_callback callback, void *ctx if (ret == KNOT_EOK) { ret = api->iter_val(it, &val); } +#ifdef DEBUG + counter_iter++; +#endif + info.entry_size = key.len + val.len; + info.valid = false; const uint16_t *entry_type = ret == KNOT_EOK ? kr_gc_key_consistent(key) : NULL; + struct entry_h *entry = NULL; if (entry_type != NULL) { - struct entry_h *entry = entry_h_consistent(val, *entry_type); - +#ifdef DEBUG + counter_gc_consistent++; +#endif + entry = entry_h_consistent(val, *entry_type); if (entry != NULL) { + info.valid = true; info.rrtype = *entry_type; - info.entry_size = key.len + val.len; info.expires_in = entry->time + entry->ttl - now; info.no_labels = entry_labels(&key, *entry_type); - - ret = callback(&key, &info, ctx); } } +#ifdef DEBUG + counter_kr_consistent += info.valid; + printf("GC %sconsistent, KR %sconsistent, size %u, key len %u: ", + entry_type ? "" : "in", entry ? "" : "IN", (key.len + val.len), key.len); + debug_printbin(key.data, key.len); + printf("\n"); +#endif + ret = callback(&key, &info, ctx); if (ret != KNOT_EOK) { printf("Error iterating database (%s).\n", knot_strerror(ret)); @@ -187,5 +223,8 @@ skip: } 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); +#endif return KNOT_EOK; } diff --git a/utils/cache_gc/kr_cache_gc.h b/utils/cache_gc/kr_cache_gc.h index 5988ec762..bebc2bcc6 100644 --- a/utils/cache_gc/kr_cache_gc.h +++ b/utils/cache_gc/kr_cache_gc.h @@ -5,11 +5,12 @@ #include typedef struct { + size_t entry_size; // amount of bytes occupied in cache by this record + bool valid; // fields further down are valid (ignore them if false) int64_t expires_in; // < 0 => already expired uint16_t rrtype; uint8_t no_labels; // 0 == ., 1 == root zone member, 2 == TLD member ... uint8_t rank; - size_t entry_size; // amount of bytes occupied in cache by this record } gc_record_info_t; typedef struct {