/** @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.
*/
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) {
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());
}
/** 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));
}
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)
{
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);
(__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))
+
/** @} */