Check differences between real and monotonic time.
It clears cache when this diffrence changes since
last cache clear.
return 0;
}
+/** Return time of last cache clear */
+static int cache_last_clear(lua_State *L)
+{
+ struct engine *engine = engine_luaget(L);
+ struct kr_cache *cache = &engine->resolver.cache;
+ lua_newtable(L);
+ lua_pushnumber(L, cache->last_clear_monotime);
+ lua_setfield(L, -2, "monotime");
+ lua_newtable(L);
+ lua_pushnumber(L, cache->last_clear_walltime.tv_sec);
+ lua_setfield(L, -2, "sec");
+ lua_pushnumber(L, cache->last_clear_walltime.tv_usec);
+ lua_setfield(L, -2, "usec");
+ lua_setfield(L, -2, "walltime");
+ return 1;
+}
+
/** Return cache statistics. */
static int cache_stats(lua_State *L)
{
{ "backends", cache_backends },
{ "count", cache_count },
{ "stats", cache_stats },
+ { "last_clear", cache_last_clear },
{ "open", cache_open },
{ "close", cache_close },
{ "prune", cache_prune },
void kr_qflags_clear(struct kr_qflags *, struct kr_qflags);
int kr_zonecut_add(struct kr_zonecut *, const knot_dname_t *, const knot_rdata_t *);
void kr_zonecut_set(struct kr_zonecut *, const knot_dname_t *);
+uint64_t kr_now();
knot_rrset_t *kr_ta_get(map_t *, const knot_dname_t *);
int kr_ta_add(map_t *, const knot_dname_t *, uint16_t, uint32_t, const uint8_t *, uint16_t);
int kr_ta_del(map_t *, const knot_dname_t *);
kr_qflags_clear
kr_zonecut_add
kr_zonecut_set
+ kr_now
# Trust anchors
kr_ta_get
kr_ta_add
modules.load('ta_signal_query')
modules.load('priming')
modules.load('detect_time_skew')
+modules.load('detect_time_jump')
-- Interactive command evaluation
function eval_cmd(line, raw)
.. include:: ../modules/ta_signal_query/README.rst
.. include:: ../modules/priming/README.rst
.. include:: ../modules/detect_time_skew/README.rst
+.. include:: ../modules/detect_time_jump/README.rst
#include <assert.h>
#include <time.h>
#include <sys/stat.h>
+#include <sys/time.h>
#include <unistd.h>
#include <errno.h>
#include <limits.h>
}
/** @internal Set time when clearing cache. */
-static void reset_time(struct kr_cache *cache)
+static void reset_timestamps(struct kr_cache *cache)
{
cache->last_clear_monotime = kr_now();
- gettimeofday(&cache->last_clear_timestamp, NULL);
+ gettimeofday(&cache->last_clear_walltime, NULL);
}
/** @internal Open cache db transaction and check internal data version. */
cache->ttl_min = 0;
cache->ttl_max = KR_CACHE_DEFAULT_MAXTTL;
/* Check cache ABI version */
+ reset_timestamps(cache);
(void) assert_right_version(cache);
return 0;
}
}
int ret = cache_purge(cache);
if (ret == 0) {
+ reset_timestamps(cache);
ret = assert_right_version(cache);
}
return ret;
} stats;
uint32_t ttl_min, ttl_max; /**< Maximum TTL of inserted entries */
+ struct timeval last_clear_walltime; /**< Time of last cache clear */
+ uint64_t last_clear_monotime; /**< Last cache clear in monotonic time */
};
/**
--- /dev/null
+.. _mod-detect_time_jump:
+
+Detect discontinuous jumps in the system time
+---------------------------------------------
+
+This module detect discontinuous jumps in the system time when resolver
+is running. It clears cache when some time jumps occurs.
+
+Time jumps is ussualy created by NTP time change or by admin intervention.
+These change can affect cache records as they store timestamp and TTL in real
+time.
+
+If you want to preserve cache during time travel you should disable
+this module by modules.unload('detect_time_jump').
--- /dev/null
+-- Module interface
+local ffi = require('ffi')
+
+local mod = {}
+mod.threshold = 10 * min
+local event_id = nil
+
+-- Get time of last cache clear. Compute difference between realtime
+-- adn monotonic time. Compute difference of actual realtime and monotonic
+-- time. In ideal case these differences should be almost same.
+-- If they differ more than mod.threshold value then clear cache.
+local function check_time()
+ local clear_time = cache.last_clear()
+ local cache_timeshift = clear_time.walltime.sec * 1000 - clear_time.monotime
+ local actual_timeshift = os.time() * 1000 - tonumber(ffi.C.kr_now())
+ local time_diff = math.abs(cache_timeshift - actual_timeshift)
+ log("check_time, %d", time_diff)
+ if time_diff > mod.threshold then
+ log("Detected time change, clearing cache\n" ..
+ "But what does that mean? It means your future hasn't been written yet."
+ )
+ cache.clear()
+ end
+end
+
+function mod.init()
+ if event_id then
+ error("Module is already loaded.")
+ else
+ event_id = event.recurrent(1 * min , check_time)
+ end
+end
+
+function mod.deinit()
+ if event_id then
+ event.cancel(event_id)
+ event_id = nil
+ end
+end
+
+return mod
--- /dev/null
+detect_time_jump_SOURCES := detect_time_jump.lua
+$(call make_lua_module,detect_time_jump)
version \
ta_signal_query \
priming \
- detect_time_skew
+ detect_time_skew \
+ detect_time_jump
endif
# Make C module