commit f312ec8: [Fix] Core: treat nodes with ttl properly in lru cache

Vsevolod Stakhov vsevolod at highsecure.ru
Thu Dec 27 18:28:05 UTC 2018


Author: Vsevolod Stakhov
Date: 2018-12-10 09:40:12 +0000
URL: https://github.com/rspamd/rspamd/commit/f312ec82940ce2d7356f00bb59d568b5ff7bc3cf

[Fix] Core: treat nodes with ttl properly in lru cache
Issue: #2675

---
 src/libutil/hash.c | 76 +++++++++++++++++++++++++++++++++++-------------------
 1 file changed, 49 insertions(+), 27 deletions(-)

diff --git a/src/libutil/hash.c b/src/libutil/hash.c
index 18b01f2ec..bc438830f 100644
--- a/src/libutil/hash.c
+++ b/src/libutil/hash.c
@@ -35,16 +35,28 @@ struct rspamd_lru_hash_s {
 	GHashTable *tbl;
 };
 
+enum rspamd_lru_element_flags {
+	RSPAMD_LRU_ELEMENT_NORMAL = 0,
+	RSPAMD_LRU_ELEMENT_VOLATILE = (1 << 0),
+};
+
 struct rspamd_lru_element_s {
-	guint16 ttl;
 	guint16 last;
 	guint8 lg_usages;
-	guint eviction_pos;
+	guint8 eviction_pos;
+	guint8 flags;
 	gpointer data;
 	gpointer key;
 	rspamd_lru_hash_t *hash;
 };
 
+struct rspamd_lru_volatile_element_s {
+	struct rspamd_lru_element_s e;
+	time_t creation_time;
+	time_t ttl;
+};
+typedef struct rspamd_lru_volatile_element_s rspamd_lru_vol_element_t;
+
 #define TIME_TO_TS(t) ((guint16)(((t) / 60) & 0xFFFFU))
 
 static void
@@ -141,7 +153,7 @@ rspamd_lru_hash_maybe_evict (rspamd_lru_hash_t *hash,
 	guint i;
 	rspamd_lru_element_t *cur;
 
-	if (elt->eviction_pos == -1) {
+	if (elt->eviction_pos == (guint8)-1) {
 		if (hash->eviction_used < eviction_candidates) {
 			/* There are free places in eviction pool */
 			hash->eviction_pool[hash->eviction_used] = elt;
@@ -183,24 +195,30 @@ rspamd_lru_hash_maybe_evict (rspamd_lru_hash_t *hash,
 
 static rspamd_lru_element_t *
 rspamd_lru_create_node (rspamd_lru_hash_t *hash,
-	gpointer key,
-	gpointer value,
-	time_t now,
-	guint ttl)
+						gpointer key,
+						gpointer value,
+						time_t now,
+						guint ttl)
 {
 	rspamd_lru_element_t *node;
+	rspamd_lru_vol_element_t *vnode;
 
-	node = g_malloc (sizeof (rspamd_lru_element_t));
-	node->data = value;
-	node->key = key;
-	node->ttl = TIME_TO_TS (ttl);
-
-	if (node->ttl == 0) {
-		node->ttl = 1;
+	if (ttl == 0) {
+		node = g_malloc (sizeof (rspamd_lru_element_t));
+		node->flags = RSPAMD_LRU_ELEMENT_NORMAL;
+	}
+	else {
+		vnode = g_malloc (sizeof (rspamd_lru_vol_element_t));
+		vnode->creation_time = now;
+		vnode->ttl = ttl;
+		node = &vnode->e;
+		node->flags = RSPAMD_LRU_ELEMENT_VOLATILE;
 	}
 
+	node->data = value;
+	node->key = key;
 	node->hash = hash;
-	node->lg_usages = lfu_base_value;
+	node->lg_usages = (guint8)lfu_base_value;
 	node->last = TIME_TO_TS (now);
 	node->eviction_pos = -1;
 
@@ -210,7 +228,7 @@ rspamd_lru_create_node (rspamd_lru_hash_t *hash,
 static void
 rspamd_lru_hash_remove_node (rspamd_lru_hash_t *hash, rspamd_lru_element_t *elt)
 {
-	if (elt->eviction_pos != -1) {
+	if (elt->eviction_pos != (guint8)-1) {
 		rspamd_lru_hash_remove_evicted (hash, elt);
 	}
 
@@ -280,11 +298,11 @@ rspamd_lru_hash_evict (rspamd_lru_hash_t *hash, time_t now)
 
 rspamd_lru_hash_t *
 rspamd_lru_hash_new_full (
-	gint maxsize,
-	GDestroyNotify key_destroy,
-	GDestroyNotify value_destroy,
-	GHashFunc hf,
-	GEqualFunc cmpf)
+		gint maxsize,
+		GDestroyNotify key_destroy,
+		GDestroyNotify value_destroy,
+		GHashFunc hf,
+		GEqualFunc cmpf)
 {
 	rspamd_lru_hash_t *new;
 
@@ -306,9 +324,9 @@ rspamd_lru_hash_new_full (
 
 rspamd_lru_hash_t *
 rspamd_lru_hash_new (
-	gint maxsize,
-	GDestroyNotify key_destroy,
-	GDestroyNotify value_destroy)
+		gint maxsize,
+		GDestroyNotify key_destroy,
+		GDestroyNotify value_destroy)
 {
 	return rspamd_lru_hash_new_full (maxsize,
 			key_destroy, value_destroy,
@@ -319,19 +337,23 @@ gpointer
 rspamd_lru_hash_lookup (rspamd_lru_hash_t *hash, gconstpointer key, time_t now)
 {
 	rspamd_lru_element_t *res;
+	rspamd_lru_vol_element_t *vnode;
 
 	res = g_hash_table_lookup (hash->tbl, key);
 	if (res != NULL) {
-		now = TIME_TO_TS(now);
 
-		if (res->ttl != 0) {
-			if (now - res->last > res->ttl) {
+		if (res->flags & RSPAMD_LRU_ELEMENT_VOLATILE) {
+			/* Check ttl */
+			vnode = (rspamd_lru_vol_element_t *)res;
+
+			if (now - vnode->creation_time > vnode->ttl) {
 				rspamd_lru_hash_remove_node (hash, res);
 
 				return NULL;
 			}
 		}
 
+		now = TIME_TO_TS(now);
 		res->last = MAX (res->last, now);
 		rspamd_lru_hash_update_counter (res);
 		rspamd_lru_hash_maybe_evict (hash, res);


More information about the Commits mailing list