]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
cache: add percentage usage to cache stats
authorLukáš Ježek <lukas.jezek@nic.cz>
Fri, 10 Jul 2020 13:08:13 +0000 (15:08 +0200)
committerPetr Špaček <petr.spacek@nic.cz>
Thu, 16 Jul 2020 06:49:34 +0000 (08:49 +0200)
NEWS
daemon/bindings/cache.c
daemon/cache.test/clear.test.lua
daemon/lua/kres-gen.lua
lib/cache/cdb_api.h
lib/cache/cdb_lmdb.c
lib/cache/cdb_lmdb.h
utils/cache_gc/db.c
utils/cache_gc/kr_cache_gc.c

diff --git a/NEWS b/NEWS
index 91464668a182a8103ab8be57fd72716fff0deb36..a3dfd3b11a55665a46bf36cd3fe64fdcb969f609 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -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
 --------
index 170282e5fe0da0928588e5d55da0c247cf4c27de..bf944b90fc443fd94cf5946e6135c6f52bb972b5 100644 (file)
@@ -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;
index 37bd8ab27ab59a1f4ac644203a1c7cf13651c4cc..8185ae524ed7902c562e85446f32ed908c5443bd 100644 (file)
@@ -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),
 }
index 4977ef1b1bbd93ac5fcfd87af4e50bd606f3c44a..c77ffc0ebde872d8e1c519ae02fb972ada6bc0ac 100644 (file)
@@ -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;
index 23d9a7c59a8a8c4781ed2aac1d14b917306dd182..c04cce533bac3ee3bbb25854b9b1d7c5ec3a0644 100644 (file)
@@ -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);
 };
index d009f1d1bc15ccf46f5c9f6f52d52818f680e7bf..9e970d5d84f18a3998abeb90a5ae37598c554097 100644 (file)
@@ -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 @@ success:
        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;
index 114adca44128d8bc406f67fbaeb85ce9b0e58c49..020e056901c026d252cae42f65ecc2ed3cc5e4d3 100644 (file)
@@ -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);
index 7dbccd31d48586cf3b257a9fd255838bc05bf447..2fd0ed172ff25a4274db628c13e7c1e61294e7f9 100644 (file)
@@ -3,6 +3,7 @@
 
 #include "db.h"
 
+#include "lib/cache/cdb_lmdb.h"
 #include <lib/cache/impl.h>
 //#include <lib/defines.h>
 
 #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)
 {
index 38bf21ed67c875250b7343dfeabe5fb12ca43278..ca76eb1e9ff0e24058246238f3542c4799679384 100644 (file)
@@ -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;