Skip to content
Snippets Groups Projects
Commit 6a9c3697 authored by Petr Špaček's avatar Petr Špaček
Browse files

Merge branch '580-add-cache-usage-to-cache-stats' into 'master'

cache: add percentage usage to cache stats

Closes #580

See merge request !1025
parents 3614b74b 510f61ea
No related branches found
No related tags found
1 merge request!1025cache: add percentage usage to cache stats
Pipeline #66267 failed
......@@ -4,6 +4,7 @@ Knot Resolver 5.2.0 (2020-0m-dd)
Improvements
------------
- capabilities are no longer constrained when running as root (!1012)
- cache: add percentage usage to cache.stats() (!1025)
Bugfixes
--------
......
......@@ -3,6 +3,7 @@
*/
#include "daemon/bindings/impl.h"
#include "lib/cache/cdb_lmdb.h"
#include "daemon/worker.h"
#include "daemon/zimport.h"
......@@ -93,6 +94,12 @@ static int cache_stats(lua_State *L)
add_stat(match_miss);
add_stat(read_leq);
add_stat(read_leq_miss);
/* usage_percent statistics special case - double */
struct libknot_lmdb_env *libknot_db = knot_db_t_kres2libknot(cache->db);
cache->stats.usage_percent = cache->api->usage_percent(libknot_db);
lua_pushnumber(L, cache->stats.usage_percent);
lua_setfield(L, -2, "usage_percent");
free(libknot_db);
#undef add_stat
return 1;
......
......@@ -186,17 +186,29 @@ local function test_complete_flush()
is(cache.count(), 0, 'cache is empty after full clear')
end
local function test_cache_used(lower, upper)
return function()
local usage = cache.stats().usage_percent
ok(usage >= lower and usage <= upper, string.format('cache percentage usage is between <%d, %d>', lower, upper))
end
end
return {
test_cache_used(0, 1),
import_zone,
test_cache_used(11, 12),
test_exact_match_qtype,
test_exact_match_qname,
test_callback,
import_zone,
test_subtree,
test_cache_used(10, 11),
test_subtree_limit,
test_cache_used(5, 6),
test_apex,
import_zone,
test_root,
import_zone,
test_complete_flush,
test_cache_used(0, 1),
}
......@@ -210,6 +210,7 @@ struct kr_cdb_stats {
uint64_t match_miss;
uint64_t read_leq;
uint64_t read_leq_miss;
double usage_percent;
};
struct kr_cache {
knot_db_t *db;
......
......@@ -29,6 +29,7 @@ struct kr_cdb_stats {
uint64_t match_miss;
uint64_t read_leq;
uint64_t read_leq_miss;
double usage_percent;
};
......@@ -74,4 +75,6 @@ struct kr_cdb_api {
* return: 0 for equality, > 0 for less, < 0 kr_error */
int (*read_leq)(knot_db_t *db, struct kr_cdb_stats *stat,
knot_db_val_t *key, knot_db_val_t *val);
double (*usage_percent)(knot_db_t *db);
};
......@@ -17,6 +17,7 @@
#include "lib/cache/cdb_lmdb.h"
#include "lib/cache/cdb_api.h"
#include "lib/cache/api.h"
#include <lib/cache/impl.h>
#include "lib/utils.h"
......@@ -24,6 +25,8 @@
#define LMDB_DIR_MODE 0770
#define LMDB_FILE_MODE 0660
/* TODO: we rely on mirrors of these two structs not changing layout
* in libknot and knot resolver! */
struct lmdb_env
{
size_t mapsize;
......@@ -43,6 +46,14 @@ struct lmdb_env
} txn;
};
struct libknot_lmdb_env {
bool shared;
unsigned dbi;
void *env;
knot_mm_t *pool;
};
/** @brief Convert LMDB error code. */
static int lmdb_error(int error)
{
......@@ -77,7 +88,6 @@ static inline MDB_val val_knot2mdb(knot_db_val_t v)
return (MDB_val){ .mv_size = v.len, .mv_data = v.data };
}
/*! \brief Set the environment map size.
* \note This also sets the maximum database size, see \fn mdb_env_set_mapsize
*/
......@@ -704,6 +714,30 @@ static int cdb_read_leq(knot_db_t *env, struct kr_cdb_stats *stats,
return ret;
}
static double cdb_usage(knot_db_t *db)
{
const size_t db_size = knot_db_lmdb_get_mapsize(db);
const size_t db_usage_abs = knot_db_lmdb_get_usage(db);
const double db_usage = (double)db_usage_abs / db_size * 100.0;
return db_usage;
}
/** Conversion between knot and lmdb structs. */
knot_db_t *knot_db_t_kres2libknot(const knot_db_t * db)
{
/* this is struct lmdb_env as in resolver/cdb_lmdb.c */
const struct lmdb_env *kres_db = db;
struct libknot_lmdb_env *libknot_db = malloc(sizeof(*libknot_db));
if (libknot_db != NULL) {
libknot_db->shared = false;
libknot_db->pool = NULL;
libknot_db->env = kres_db->env;
libknot_db->dbi = kres_db->dbi;
}
return libknot_db;
}
const struct kr_cdb_api *kr_cdb_lmdb(void)
{
......@@ -712,7 +746,8 @@ const struct kr_cdb_api *kr_cdb_lmdb(void)
cdb_init, cdb_deinit, cdb_count, cdb_clear, cdb_commit,
cdb_readv, cdb_writev, cdb_remove,
cdb_match,
cdb_read_leq
cdb_read_leq,
cdb_usage,
};
return &api;
......
......@@ -9,3 +9,6 @@
KR_EXPORT KR_CONST
const struct kr_cdb_api *kr_cdb_lmdb(void);
KR_EXPORT
knot_db_t *knot_db_t_kres2libknot(const knot_db_t * db);
......@@ -3,6 +3,7 @@
#include "db.h"
#include "lib/cache/cdb_lmdb.h"
#include <lib/cache/impl.h>
//#include <lib/defines.h>
......@@ -10,34 +11,6 @@
#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;
void *env;
knot_mm_t *pool;
};
struct kres_lmdb_env {
size_t mapsize;
unsigned dbi;
void *env;
// sub-struct txn ommited
};
static knot_db_t *knot_db_t_kres2libknot(const knot_db_t * db)
{
const struct kres_lmdb_env *kres_db = db; // this is struct lmdb_env as in resolver/cdb_lmdb.c
struct libknot_lmdb_env *libknot_db = malloc(sizeof(*libknot_db));
if (libknot_db != NULL) {
libknot_db->shared = false;
libknot_db->pool = NULL;
libknot_db->env = kres_db->env;
libknot_db->dbi = kres_db->dbi;
}
return libknot_db;
}
int kr_gc_cache_open(const char *cache_path, struct kr_cache *kres_db,
knot_db_t ** libknot_db)
{
......
......@@ -13,6 +13,7 @@
#include <lib/cache/api.h>
#include <lib/cache/impl.h>
#include <lib/defines.h>
#include "lib/cache/cdb_lmdb.h"
#include "kr_cache_gc.h"
......@@ -176,9 +177,8 @@ int kr_cache_gc(kr_cache_gc_cfg_t *cfg, kr_cache_gc_state_t **state)
}
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);
const double db_usage = (double)db_usage_abs / db_size * 100.0;
const struct kr_cdb_api *cache_api = kr_cdb_lmdb();
const double db_usage = cache_api->usage_percent(db);
#if 0 // Probably not worth it, better reduce the risk by checking more often.
if (db_usage > 90.0) {
free(*libknot_db);
......@@ -190,11 +190,7 @@ int kr_cache_gc(kr_cache_gc_cfg_t *cfg, kr_cache_gc_state_t **state)
#endif
const bool large_usage = db_usage >= cfg->cache_max_usage;
if (cfg->dry_run || large_usage) { // don't print this on every size check
const size_t MiB = 1024 * 1024;
#define MiB_round(n) (((n) + MiB/2) / MiB)
printf("Usage: %.2lf%% (%zu / %zu MiB)\n",
db_usage, MiB_round(db_usage_abs), MiB_round(db_size));
#undef MiB_round
printf("Usage: %.2lf%%\n", db_usage);
}
if (cfg->dry_run || !large_usage) {
return KNOT_EOK;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment