Commit b64d6ce7 authored by Marek Vavrusa's avatar Marek Vavrusa

engine: clear bad scorers from RTT every 5 minutes

an internal timer walks RTT timer periodically and
clears entries with bad results every 5 minutes.
this means that a timeouted entry penalty is 
capped to that interval, making sure that the
bad reputation doesn't last forever
parent 0b02bf5f
......@@ -41,6 +41,9 @@
/** @internal Annotate for static checkers. */
KR_NORETURN int lua_error (lua_State *L);
/* Cleanup engine state every 5 minutes */
const size_t CLEANUP_TIMER = 5*60*1000;
/*
* Global bindings.
*/
......@@ -455,6 +458,22 @@ static int init_state(struct engine *engine)
return kr_ok();
}
static void update_state(uv_timer_t *handle)
{
struct engine *engine = handle->data;
/* Walk RTT table, clearing all entries with bad score
* to compensate for intermittent network issues or temporary bad behaviour. */
kr_nsrep_lru_t *table = engine->resolver.cache_rtt;
for (size_t i = 0; i < table->size; ++i) {
if (!table->slots[i].key)
continue;
if (table->slots[i].data > KR_NS_LONG) {
lru_evict(table, i);
}
}
}
int engine_init(struct engine *engine, knot_mm_t *pool)
{
if (engine == NULL) {
......@@ -607,11 +626,23 @@ int engine_start(struct engine *engine, const char *config_path)
lua_gc(engine->L, LUA_GCSETSTEPMUL, 50);
lua_gc(engine->L, LUA_GCSETPAUSE, 400);
lua_gc(engine->L, LUA_GCRESTART, 0);
/* Set up periodic update function */
uv_timer_t *timer = malloc(sizeof(*timer));
if (timer) {
uv_timer_init(uv_default_loop(), timer);
timer->data = engine;
engine->updater = timer;
uv_timer_start(timer, update_state, CLEANUP_TIMER, CLEANUP_TIMER);
}
return kr_ok();
}
void engine_stop(struct engine *engine)
{
uv_timer_stop(engine->updater);
uv_close((uv_handle_t *)engine->updater, (uv_close_cb) free);
uv_stop(uv_default_loop());
}
......
......@@ -59,6 +59,7 @@ struct engine {
module_array_t modules;
storage_registry_t storage_registry;
knot_mm_t *pool;
uv_timer_t *updater;
struct lua_State *L;
};
......
......@@ -116,6 +116,9 @@ struct { \
/** Get slot at given index. */
static inline void *lru_slot_at(struct lru_hash_base *lru, uint32_t id)
{
if (id >= lru->size) {
return NULL;
}
return (struct lru_slot *)(lru->slots + (id * lru->stride));
}
......@@ -139,6 +142,21 @@ static inline void *lru_slot_get(struct lru_hash_base *lru, const char *key, uin
return NULL;
}
static inline int lru_slot_evict(struct lru_hash_base *lru, uint32_t id, size_t offset)
{
struct lru_slot *slot = lru_slot_at(lru, id);
if (!slot || !slot->key) {
return -1;
}
lru->evictions += 1;
free(slot->key);
if (lru->evict) {
lru->evict(lru->baton, lru_slot_val(slot, offset));
}
memset(slot, 0, lru->stride);
return 0;
}
/** @internal Slot data setter */
static inline void *lru_slot_set(struct lru_hash_base *lru, const char *key, uint16_t len, size_t offset)
{
......@@ -155,10 +173,8 @@ static inline void *lru_slot_set(struct lru_hash_base *lru, const char *key, uin
if (slot->refs > 0) {
return NULL; /* Couldn't joust former key. */
}
lru->evictions += 1;
free(slot->key);
if (lru->evict) {
lru->evict(lru->baton, lru_slot_val(slot, offset));
if (lru_slot_evict(lru, id, offset) < 0) {
return NULL;
}
}
memset(slot, 0, lru->stride);
......@@ -227,4 +243,13 @@ static inline void *lru_slot_set(struct lru_hash_base *lru, const char *key, uin
(__typeof__(&(table)->slots[0].data)) \
lru_slot_set((struct lru_hash_base *)(table), (key_), (len_), lru_slot_offset(table))
/**
* @brief Evict element at index.
* @param table hash table
* @param pos_ element position
* @return 0 if successful, negative integer if failed
*/
#define lru_evict(table, pos_) \
lru_slot_evict((struct lru_hash_base *)(table), (pos_), lru_slot_offset(table))
/** @} */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment