Kaynağa Gözat

* LRU cache now is capable to get custom insert and delete functions that would allow to use custom storage engines for it

tags/0.4.4
Vsevolod Stakhov 12 yıl önce
ebeveyn
işleme
25769904ac
2 değiştirilmiş dosya ile 90 ekleme ve 22 silme
  1. 66
    21
      src/hash.c
  2. 24
    1
      src/hash.h

+ 66
- 21
src/hash.c Dosyayı Görüntüle

@@ -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,10 +350,46 @@ 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
@@ -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);
}

+ 24
- 1
src/hash.h Dosyayı Görüntüle

@@ -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

Loading…
İptal
Kaydet