]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
lib/cache check_health(): also detect size changes
authorVladimír Čunát <vladimir.cunat@nic.cz>
Wed, 19 Aug 2020 08:23:04 +0000 (10:23 +0200)
committerPetr Špaček <petr.spacek@nic.cz>
Mon, 7 Sep 2020 15:47:11 +0000 (17:47 +0200)
This is important for GC - otherwise the usage computation would be
wrong after another process changed size (without replacing the file).

lib/cache/cdb_lmdb.c
utils/cache_gc/db.h
utils/cache_gc/main.c

index 81708ee5c73ccf6a7766e6144b79f7968e67432c..c955b3bfb0d0c39491f4edf4f106ee3ee057c55f 100644 (file)
@@ -48,6 +48,7 @@ struct lmdb_env
        /* Cached part of struct stat for data.mdb. */
        dev_t st_dev;
        ino_t st_ino;
+       off_t st_size;
        const char *mdb_data_path; /**< path to data.mdb, for convenience */
 };
 
@@ -309,6 +310,10 @@ static int cdb_open_env(struct lmdb_env *env, const char *path, size_t mapsize,
        }
        env->st_dev = st.st_dev;
        env->st_ino = st.st_ino;
+       env->st_size = st.st_size;
+       if (env->st_size != env->mapsize)
+               kr_log_verbose("[cache] suspicious size of cache file: %zu != %zu\n",
+                               (size_t)env->st_size, env->mapsize);
 
        /* Open the database. */
        MDB_txn *txn = NULL;
@@ -436,7 +441,15 @@ static int cdb_check_health(knot_db_t *db, struct kr_cdb_stats *stats)
                // FIXME: if the file doesn't exist?
        }
        if (st.st_dev == env->st_dev && st.st_ino == env->st_ino) {
-               return kr_ok();
+               if (st.st_size == env->st_size)
+                       return kr_ok();
+               kr_log_info("[cache] detected size change by another process: %zu -> %zu\n",
+                               (size_t)env->st_size, (size_t)st.st_size);
+               int ret = cdb_commit(db, stats);
+               if (!ret) ret = lmdb_error(mdb_env_set_mapsize(env->env, st.st_size));
+               if (!ret) env->mapsize = st.st_size;
+               env->st_size = st.st_size; // avoid retrying in cycle even if it failed
+               return kr_error(ret);
        }
        kr_log_verbose("[cache] cache file has been replaced, reopening\n");
        int ret = reopen_env(env, stats);
index 74d876359c1603237f836a8adfb0ecbfc122b318..44cfbec2955c3658caf9594b685934e1127bc257 100644 (file)
@@ -9,6 +9,8 @@
 int kr_gc_cache_open(const char *cache_path, struct kr_cache *kres_db,
                     knot_db_t ** libknot_db);
 
+/** A wrapper around kr_cdb_api::check_health that keeps libknot_db up to date.
+ * \return zero or negative error code. */
 int kr_gc_cache_check_health(struct kr_cache *kres_db, knot_db_t ** libknot_db);
 
 void kr_gc_cache_close(struct kr_cache *kres_db, knot_db_t * knot_db);
index a2c05489f9b0c3e35be751c089b2a1489d6580b4..736ade3219e813f7180e21cb8fccc4e9463c8fcb 100644 (file)
@@ -8,6 +8,7 @@
 #include "lib/defines.h"
 #include "lib/utils.h"
 #include <libknot/libknot.h>
+#include <lmdb.h>
 
 #include "kresconfig.h"
 #include "kr_cache_gc.h"
@@ -148,7 +149,8 @@ int main(int argc, char *argv[])
                }
 
                // ENOENT: kresd may not be started yet or cleared the cache now
-               if (ret && ret != KNOT_ENOENT) {
+               // MDB_MAP_RESIZED: GC bailed out but on next iteration it should be OK
+               if (ret && ret != KNOT_ENOENT && ret != kr_error(MDB_MAP_RESIZED)) {
                        printf("Error (%s)\n", knot_strerror(ret));
                        exit_code = 10;
                        break;