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);
};
int ret = kr_gc_cache_iter(db, cb_compute_categories, &cats);
if (ret != KNOT_EOK) {
+ kr_cache_gc_free_state(state);
return ret;
}
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
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;
}
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;
}
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"
}
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));
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;
}