diff options
author | Vsevolod Stakhov <vsevolod@rambler-co.ru> | 2011-10-10 16:42:07 +0400 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@rambler-co.ru> | 2011-10-10 16:42:07 +0400 |
commit | 25769904acc693327d9ae40e329fc8bd93ae43bc (patch) | |
tree | b7e4715715a3430b136d4c6c3ed92853dd24a46a | |
parent | 2c7e49f97e737af5ac40bef8bf2b33fa9331736f (diff) | |
download | rspamd-25769904acc693327d9ae40e329fc8bd93ae43bc.tar.gz rspamd-25769904acc693327d9ae40e329fc8bd93ae43bc.zip |
* LRU cache now is capable to get custom insert and delete functions that would allow to use custom storage engines for it0.4.4
-rw-r--r-- | src/hash.c | 87 | ||||
-rw-r--r-- | src/hash.h | 25 |
2 files changed, 90 insertions, 22 deletions
diff --git a/src/hash.c b/src/hash.c index f5444ba5b..fae3d3f66 100644 --- a/src/hash.c +++ b/src/hash.c @@ -332,7 +332,7 @@ rspamd_lru_create_node (rspamd_lru_hash_t *hash, gpointer key, gpointer value, t } /** - * Create new lru hash + * Create new lru hash with GHashTable as storage * @param maxsize maximum elements in a hash * @param maxage maximum age of elemnt * @param hash_func pointer to hash function @@ -350,11 +350,47 @@ rspamd_lru_hash_new (GHashFunc hash_func, GEqualFunc key_equal_func, gint maxsiz new->maxage = maxage; new->maxsize = maxsize; new->value_destroy = value_destroy; + new->key_destroy = NULL; new->q = g_queue_new (); + new->insert_func = (lru_cache_insert_func)g_hash_table_replace; + new->lookup_func = (lru_cache_lookup_func)g_hash_table_lookup; + new->delete_func = (lru_cache_delete_func)g_hash_table_remove; + new->destroy_func = (lru_cache_destroy_func)g_hash_table_destroy; return new; } /** + * Create new lru hash with custom storage + * @param maxsize maximum elements in a hash + * @param maxage maximum age of elemnt + * @param hash_func pointer to hash function + * @param key_equal_func pointer to function for comparing keys + * @return new rspamd_hash object + */ +rspamd_lru_hash_t* +rspamd_lru_hash_new_full (GHashFunc hash_func, GEqualFunc key_equal_func, + gint maxsize, gint maxage, GDestroyNotify key_destroy, GDestroyNotify value_destroy, + gpointer storage, lru_cache_insert_func insert_func, lru_cache_lookup_func lookup_func, + lru_cache_delete_func delete_func) +{ + rspamd_lru_hash_t *new; + + new = g_malloc (sizeof (rspamd_lru_hash_t)); + new->storage = storage; + new->maxage = maxage; + new->maxsize = maxsize; + new->value_destroy = value_destroy; + new->key_destroy = key_destroy; + new->q = g_queue_new (); + new->insert_func = insert_func; + new->lookup_func = lookup_func; + new->delete_func = delete_func; + new->destroy_func = NULL; + + return new; +} + +/** * Lookup item from hash * @param hash hash object * @param key key to find @@ -365,21 +401,23 @@ rspamd_lru_hash_lookup (rspamd_lru_hash_t *hash, gpointer key, time_t now) { rspamd_lru_element_t *res; - if ((res = g_hash_table_lookup (hash->storage, key)) != NULL) { - if (now - res->store_time > hash->maxage) { - /* Expire elements from queue tail */ - res = g_queue_pop_tail (hash->q); - - while (res != NULL && now - res->store_time > hash->maxage) { - g_hash_table_remove (hash->storage, res->key); + if ((res = hash->lookup_func (hash->storage, key)) != NULL) { + if (hash->maxage > 0) { + if (now - res->store_time > hash->maxage) { + /* Expire elements from queue tail */ res = g_queue_pop_tail (hash->q); - } - /* Restore last element */ - if (res != NULL) { - g_queue_push_tail (hash->q, res); - } - return NULL; + while (res != NULL && now - res->store_time > hash->maxage) { + hash->delete_func (hash->storage, res->key); + res = g_queue_pop_tail (hash->q); + } + /* Restore last element */ + if (res != NULL) { + g_queue_push_tail (hash->q, res); + } + + return NULL; + } } } @@ -401,28 +439,35 @@ rspamd_lru_hash_insert (rspamd_lru_hash_t *hash, gpointer key, gpointer value, t rspamd_lru_element_t *res; gint removed = 0; - if ((gint)g_hash_table_size (hash->storage) >= hash->maxsize) { + if ((gint)g_queue_get_length (hash->q) >= hash->maxsize) { /* Expire some elements */ res = g_queue_pop_tail (hash->q); - while (res != NULL && now - res->store_time > hash->maxage) { - g_hash_table_remove (hash->storage, res->key); - res = g_queue_pop_tail (hash->q); - removed ++; + if (hash->maxage > 0) { + while (res != NULL && now - res->store_time > hash->maxage) { + if (res->key != NULL) { + hash->delete_func (hash->storage, res->key); + } + res = g_queue_pop_tail (hash->q); + removed ++; + } } + /* If elements are already removed do not expire extra elements */ if (removed != 0 && res != NULL) { g_queue_push_tail (hash->q, res); } } res = rspamd_lru_create_node (hash, key, value, now); - g_hash_table_insert (hash->storage, key, res); + hash->insert_func (hash->storage, key, res); g_queue_push_head (hash->q, res); } void rspamd_lru_hash_destroy (rspamd_lru_hash_t *hash) { - g_hash_table_destroy (hash->storage); + if (hash->destroy_func) { + hash->destroy_func (hash->storage); + } g_queue_free (hash->q); g_free (hash); } diff --git a/src/hash.h b/src/hash.h index 1625aaba1..fc336b6bb 100644 --- a/src/hash.h +++ b/src/hash.h @@ -28,12 +28,22 @@ typedef struct rspamd_hash_s { memory_pool_t *pool; } rspamd_hash_t; +typedef void (*lru_cache_insert_func)(gpointer storage, gpointer key, gpointer value); +typedef gpointer (*lru_cache_lookup_func)(gpointer storage, gpointer key); +typedef gboolean (*lru_cache_delete_func)(gpointer storage, gpointer key); +typedef void (*lru_cache_destroy_func)(gpointer storage); + typedef struct rspamd_lru_hash_s { gint maxsize; gint maxage; - GHashTable *storage; GDestroyNotify value_destroy; + GDestroyNotify key_destroy; GQueue *q; + gpointer storage; + lru_cache_insert_func insert_func; + lru_cache_lookup_func lookup_func; + lru_cache_delete_func delete_func; + lru_cache_destroy_func destroy_func; } rspamd_lru_hash_t; typedef struct rspamd_lru_element_s { @@ -105,6 +115,19 @@ void rspamd_hash_foreach (rspamd_hash_t *hash, GHFunc func, gpointer user_data); */ rspamd_lru_hash_t* rspamd_lru_hash_new (GHashFunc hash_func, GEqualFunc key_equal_func, gint maxsize, gint maxage, GDestroyNotify key_destroy, GDestroyNotify value_destroy); + +/** + * Create new lru hash with custom storage + * @param maxsize maximum elements in a hash + * @param maxage maximum age of elemnt + * @param hash_func pointer to hash function + * @param key_equal_func pointer to function for comparing keys + * @return new rspamd_hash object + */ +rspamd_lru_hash_t* rspamd_lru_hash_new_full (GHashFunc hash_func, GEqualFunc key_equal_func, + gint maxsize, gint maxage, GDestroyNotify key_destroy, GDestroyNotify value_destroy, + gpointer storage, lru_cache_insert_func insert_func, lru_cache_lookup_func lookup_func, + lru_cache_delete_func delete_func); /** * Lookup item from hash * @param hash hash object |