From: Marek Vavrusa Date: Mon, 18 Apr 2016 00:32:17 +0000 (-0700) Subject: engine: clear bad scorers from RTT every 5 minutes X-Git-Tag: v1.0.0~29 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b64d6ce7a09bd19d56a41759eba9260d6f960908;p=thirdparty%2Fknot-resolver.git 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 --- diff --git a/daemon/engine.c b/daemon/engine.c index 1f3bbed25..4c0e0c50c 100644 --- a/daemon/engine.c +++ b/daemon/engine.c @@ -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()); } diff --git a/daemon/engine.h b/daemon/engine.h index 7c9379939..1eddda633 100644 --- a/daemon/engine.h +++ b/daemon/engine.h @@ -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; }; diff --git a/lib/generic/lru.h b/lib/generic/lru.h index 94eaa8a6d..93348326c 100644 --- a/lib/generic/lru.h +++ b/lib/generic/lru.h @@ -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)) + /** @} */