]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
gc: delete inconsistent entries from cache instead of skipping them
authorPetr Špaček <petr.spacek@nic.cz>
Tue, 25 Jun 2019 11:00:22 +0000 (13:00 +0200)
committerPetr Špaček <petr.spacek@nic.cz>
Wed, 10 Jul 2019 13:59:23 +0000 (15:59 +0200)
utils/cache_gc/categories.c
utils/cache_gc/db.c
utils/cache_gc/kr_cache_gc.h

index b50cffc1b200e16b1e14326cdaa01aeff17c959b..c64f6d20af38a5dcd9b59e7386fe0fc0efa3b449 100644 (file)
@@ -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:
index 5054d3f2c08f8d1525f4a03832faeab6077c270f..e5ba3b89d5929e994416d4b2b0b041dbcc8a583e 100644 (file)
@@ -1,3 +1,5 @@
+// #define DEBUG 1
+
 #include "db.h"
 
 #include <lib/cache/impl.h>
@@ -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;
 }
index 5988ec762f84458182770bf7a8210404a821aa95..bebc2bcc6446c9a948bbc54ffa1c3549a9f3c65c 100644 (file)
@@ -5,11 +5,12 @@
 #include <stdint.h>
 
 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 {