elt->flags = flags;
elt->size = len;
elt->expire = expire;
+ if (expire == 0) {
+ elt->flags |= KV_ELT_PERSISTENT;
+ }
/* Place to the backend */
if (storage->backend) {
for (i = 0; i < expire->queues; i ++) {
elt = expire->heads[i].tqh_first;
- if (elt && (elt->flags & KV_ELT_PERSISTENT) == 0) {
+ if (elt && (elt->flags & (KV_ELT_PERSISTENT|KV_ELT_DIRTY)) == 0) {
diff = elt->expire - (now - elt->age);
if (diff > 0) {
/* This element is not expired */
}
else {
/* This element is already expired */
- rspamd_kv_storage_delete (storage, ELT_KEY (elt));
+ storage->cache->steal_func (storage->cache, elt);
+ /* Free memory */
+ g_slice_free1 (ELT_SIZE (elt), elt);
res = TRUE;
/* Check other elements in this queue */
TAILQ_FOREACH_SAFE (elt, &expire->heads[i], entry, temp) {
- if ((elt->flags & KV_ELT_PERSISTENT) != 0 || elt->expire < (now - elt->age)) {
+ if ((elt->flags & (KV_ELT_PERSISTENT|KV_ELT_DIRTY)) != 0 || elt->expire < (now - elt->age)) {
break;
}
- rspamd_kv_storage_delete (storage, ELT_KEY (elt));
+ storage->cache->steal_func (storage->cache, elt);
+ /* Free memory */
+ g_slice_free1 (ELT_SIZE (elt), elt);
}
break;
}
}
if (!res) {
- /* Oust the oldest element from cache */
- storage->cache->delete_func (storage->cache, ELT_KEY (oldest_elt));
- oldest_elt->flags |= KV_ELT_OUSTED;
- storage->memory -= oldest_elt->size + sizeof (*elt);
+ storage->memory -= ELT_SIZE (oldest_elt);
storage->elts --;
- rspamd_lru_delete (e, oldest_elt);
+ storage->cache->steal_func (storage->cache, oldest_elt);
+ /* Free memory */
+ if ((oldest_elt->flags & KV_ELT_DIRTY) != 0) {
+ oldest_elt->flags |= KV_ELT_NEED_FREE;
+ }
+ else {
+ g_slice_free1 (ELT_SIZE (oldest_elt), oldest_elt);
+ }
}
return TRUE;
memcpy (ELT_DATA (elt), value, len);
g_hash_table_insert (cache->hash, ELT_KEY (elt), elt);
}
+ else {
+ g_hash_table_steal (cache->hash, ELT_KEY (elt));
+ if ((elt->flags & KV_ELT_DIRTY) != 0) {
+ elt->flags |= KV_ELT_NEED_FREE;
+ }
+ else {
+ /* Free it by self */
+ g_slice_free1 (ELT_SIZE (elt), elt);
+ }
+ keylen = strlen (key);
+ elt = g_slice_alloc0 (sizeof (struct rspamd_kv_element) + len + keylen + 1);
+ elt->age = time (NULL);
+ elt->keylen = keylen;
+ elt->size = len;
+ elt->hash = rspamd_strcase_hash (key);
+ memcpy (elt->data, key, keylen + 1);
+ memcpy (ELT_DATA (elt), value, len);
+ g_hash_table_insert (cache->hash, ELT_KEY (elt), elt);
+ }
return elt;
}
rspamd_kv_hash_replace (struct rspamd_kv_cache *c, gpointer key, struct rspamd_kv_element *elt)
{
struct rspamd_kv_hash_cache *cache = (struct rspamd_kv_hash_cache *)c;
+ struct rspamd_kv_element *oldelt;
+
+ if ((oldelt = g_hash_table_lookup (cache->hash, key)) != NULL) {
+ g_hash_table_steal (cache->hash, key);
- g_hash_table_replace (cache->hash, key, elt);
+ if ((oldelt->flags & KV_ELT_DIRTY) != 0) {
+ oldelt->flags |= KV_ELT_NEED_FREE;
+ }
+ else {
+ /* Free it by self */
+ g_slice_free1 (ELT_SIZE (oldelt), oldelt);
+ }
+ g_hash_table_insert (cache->hash, ELT_KEY (elt), elt);
+ return TRUE;
+ }
- return TRUE;
+ return FALSE;
}
/**