From: Vladimír Čunát Date: Fri, 28 Feb 2020 14:02:27 +0000 (+0100) Subject: gc: make state in kr_cache_gc() explicit X-Git-Tag: v5.1.0~40^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f991063a50dfd95386edf934190d1ec0166dd450;p=thirdparty%2Fknot-resolver.git gc: make state in kr_cache_gc() explicit It really is nicer to work with. Additionally re-open cache after any GC errors. --- diff --git a/utils/cache_gc/db.c b/utils/cache_gc/db.c index 168c005ba..7dbccd31d 100644 --- a/utils/cache_gc/db.c +++ b/utils/cache_gc/db.c @@ -10,6 +10,7 @@ #include #include +//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; diff --git a/utils/cache_gc/kr_cache_gc.c b/utils/cache_gc/kr_cache_gc.c index 5913d29b0..8b8ecf5b9 100644 --- a/utils/cache_gc/kr_cache_gc.c +++ b/utils/cache_gc/kr_cache_gc.c @@ -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; } diff --git a/utils/cache_gc/kr_cache_gc.h b/utils/cache_gc/kr_cache_gc.h index 34b475e7e..261115d00 100644 --- a/utils/cache_gc/kr_cache_gc.h +++ b/utils/cache_gc/kr_cache_gc.h @@ -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" diff --git a/utils/cache_gc/main.c b/utils/cache_gc/main.c index 538456253..6738ba03d 100644 --- a/utils/cache_gc/main.c +++ b/utils/cache_gc/main.c @@ -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; }