]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
gc: make state in kr_cache_gc() explicit
authorVladimír Čunát <vladimir.cunat@nic.cz>
Fri, 28 Feb 2020 14:02:27 +0000 (15:02 +0100)
committerVladimír Čunát <vladimir.cunat@nic.cz>
Fri, 28 Feb 2020 14:58:53 +0000 (15:58 +0100)
It really is nicer to work with.
Additionally re-open cache after any GC errors.

utils/cache_gc/db.c
utils/cache_gc/kr_cache_gc.c
utils/cache_gc/kr_cache_gc.h
utils/cache_gc/main.c

index 168c005ba75c6a00f8501978789a1196bc8f1b2f..7dbccd31d48586cf3b257a9fd255838bc05bf447 100644 (file)
@@ -10,6 +10,7 @@
 #include <time.h>
 #include <sys/stat.h>
 
+//TODO: we rely on mirrors of these two structs not changing layout in knot-dns and knot-resolver!
 struct libknot_lmdb_env {
        bool shared;
        unsigned dbi;
index 5913d29b0d6b2bcce82c3c69bc015c1e01fbd448..8b8ecf5b957341c3a69f24460d332dcc47b3968b 100644 (file)
@@ -142,27 +142,39 @@ int cb_delete_categories(const knot_db_val_t * key, gc_record_info_t * info,
        return KNOT_EOK;
 }
 
-int kr_cache_gc(kr_cache_gc_cfg_t * cfg)
+struct kr_cache_gc_state {
+       struct kr_cache kres_db;
+       knot_db_t *db;
+};
+
+void kr_cache_gc_free_state(kr_cache_gc_state_t **state)
 {
-       // statically open cache, its clean up and initialization
-       static bool is_open = false;
-       static struct kr_cache kres_db = { 0 };
-       static knot_db_t *db = NULL;
-       if (!cfg) {
-               if (is_open) {
-                       kr_gc_cache_close(&kres_db, db);
-                       is_open = false;
-               }
-               return 0;
+       assert(state);
+       if (!*state) { // not open
+               return;
        }
-       if (!is_open) {
-               int ret = kr_gc_cache_open(cfg->cache_path, &kres_db, &db);
+       kr_gc_cache_close(&(*state)->kres_db, (*state)->db);
+       free(*state);
+       *state = NULL;
+}
+
+int kr_cache_gc(kr_cache_gc_cfg_t *cfg, kr_cache_gc_state_t **state)
+{
+       assert(cfg && state);
+       if (!*state) { // Cache not open -> do that.
+               *state = calloc(1, sizeof(**state));
+               if (!*state) {
+                       return KNOT_ENOMEM;
+               }
+               int ret = kr_gc_cache_open(cfg->cache_path, &(*state)->kres_db,
+                                          &(*state)->db);
                if (ret) {
+                       free(*state);
+                       *state = NULL;
                        return ret;
-               } else {
-                       is_open = true;
                }
        }
+       knot_db_t *const db = (*state)->db; // frequently used shortcut
 
        const size_t db_size = knot_db_lmdb_get_mapsize(db);
        const size_t db_usage_abs = knot_db_lmdb_get_usage(db);
@@ -193,6 +205,7 @@ int kr_cache_gc(kr_cache_gc_cfg_t * cfg)
        };
        int ret = kr_gc_cache_iter(db, cb_compute_categories, &cats);
        if (ret != KNOT_EOK) {
+               kr_cache_gc_free_state(state);
                return ret;
        }
 
@@ -232,6 +245,7 @@ int kr_cache_gc(kr_cache_gc_cfg_t * cfg)
        ret = kr_gc_cache_iter(db, cb_delete_categories, &to_del);
        if (ret != KNOT_EOK) {
                entry_dynarray_deep_free(&to_del.to_delete);
+               kr_cache_gc_free_state(state);
                return ret;
        }
        printf
@@ -252,6 +266,7 @@ int kr_cache_gc(kr_cache_gc_cfg_t * cfg)
                printf("Error starting R/W DB transaction (%s).\n",
                       knot_strerror(ret));
                entry_dynarray_deep_free(&to_del.to_delete);
+               kr_cache_gc_free_state(state);
                return ret;
        }
 
@@ -311,8 +326,7 @@ finish:
        entry_dynarray_deep_free(&to_del.to_delete);
 
        // OK, let's close it in this case.
-       kr_gc_cache_close(&kres_db, db);
-       is_open = false;
+       kr_cache_gc_free_state(state);
 
        return ret;
 }
index 34b475e7e5ee335a09e1bf80c58386d9b93e6ad2..261115d00ea1ea3dcb20ff7273eebb5bd19f0728 100644 (file)
@@ -30,6 +30,12 @@ typedef struct {
        bool dry_run;
 } kr_cache_gc_cfg_t;
 
-int kr_cache_gc(kr_cache_gc_cfg_t * cfg);
+/** State persisting across kr_cache_gc() invocations (opaque).
+ * NULL pointer represents a clean state. */
+typedef struct kr_cache_gc_state kr_cache_gc_state_t;
+
+/** Do one iteration of cache-size check and (if necessary) GC pass. */
+int kr_cache_gc(kr_cache_gc_cfg_t *cfg, kr_cache_gc_state_t **state);
+void kr_cache_gc_free_state(kr_cache_gc_state_t **state);
 
 #define KR_CACHE_GC_VERSION "0.2"
index 5384562537136cef6a6a4c8feef1a9fd5b474aff..6738ba03d2b015b4bd32e61e1381eb7797acb929 100644 (file)
@@ -117,8 +117,9 @@ int main(int argc, char *argv[])
        }
 
        int exit_code = 0;
+       kr_cache_gc_state_t *gc_state = NULL;
        do {
-               int ret = kr_cache_gc(&cfg);
+               int ret = kr_cache_gc(&cfg, &gc_state);
                // ENOENT: kresd may not be started yet or cleared the cache now
                if (ret && ret != -ENOENT) {
                        printf("Error (%s)\n", knot_strerror(ret));
@@ -128,8 +129,8 @@ int main(int argc, char *argv[])
 
                usleep(cfg.gc_interval);
        } while (cfg.gc_interval > 0 && !killed);
-       // clean up any state
-       kr_cache_gc(NULL);
+
+       kr_cache_gc_free_state(&gc_state);
 
        return exit_code;
 }