]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
engine: clear bad scorers from RTT every 5 minutes
authorMarek Vavrusa <marek@vavrusa.com>
Mon, 18 Apr 2016 00:32:17 +0000 (17:32 -0700)
committerMarek Vavrusa <marek@vavrusa.com>
Mon, 18 Apr 2016 00:32:17 +0000 (17:32 -0700)
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

daemon/engine.c
daemon/engine.h
lib/generic/lru.h

index 1f3bbed25c111ef27481ecfe3a500061cc7dc144..4c0e0c50cd8e4884606d225f47cb0172e0ac79fb 100644 (file)
@@ -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());
 }
 
index 7c9379939ae562d49985b20ef3894198783c0411..1eddda6330c7e124ff625da03a982b45c7d463c6 100644 (file)
@@ -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;
 };
 
index 94eaa8a6d1047c32cdbbe09142494bc8e780fcf2..93348326c135134fbfd2d5954439b5162674bb6f 100644 (file)
@@ -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))
+
 /** @} */