belt = storage->backend->lookup_func (storage->backend, key);
if (belt) {
/* Put this element into cache */
- rspamd_kv_storage_insert_internal (storage, belt->key, belt->data, belt->size, belt->flags,
+ rspamd_kv_storage_insert_internal (storage, ELT_KEY (belt), ELT_DATA (belt),
+ belt->size, belt->flags,
belt->expire, &elt);
if ((belt->flags & KV_ELT_DIRTY) == 0) {
g_free (belt);
}
else {
/* This element is already expired */
- rspamd_kv_storage_delete (storage, elt->key);
+ rspamd_kv_storage_delete (storage, ELT_KEY (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)) {
break;
}
- rspamd_kv_storage_delete (storage, elt->key);
+ rspamd_kv_storage_delete (storage, ELT_KEY (elt));
}
break;
}
if (!res) {
/* Oust the oldest element from cache */
- storage->cache->delete_func (storage->cache, oldest_elt->key);
+ storage->cache->delete_func (storage->cache, ELT_KEY (oldest_elt));
oldest_elt->flags |= KV_ELT_OUSTED;
storage->memory -= oldest_elt->size + sizeof (*elt);
storage->elts --;
{
struct rspamd_kv_element *elt;
struct rspamd_kv_hash_cache *cache = (struct rspamd_kv_hash_cache *)c;
+ guint keylen;
if ((elt = g_hash_table_lookup (cache->hash, key)) == NULL) {
- elt = g_slice_alloc0 (sizeof (struct rspamd_kv_element) + len);
+ keylen = strlen (key);
+ elt = g_slice_alloc0 (sizeof (struct rspamd_kv_element) + len + keylen + 1);
elt->age = time (NULL);
- elt->key = key;
+ elt->keylen = keylen;
elt->size = len;
elt->hash = rspamd_strcase_hash (key);
- memcpy (elt->data, value, len);
- g_hash_table_insert (cache->hash, key, elt);
+ memcpy (elt->data, key, keylen + 1);
+ memcpy (ELT_DATA (elt), value, len);
+ g_hash_table_insert (cache->hash, ELT_KEY (elt), elt);
}
return elt;
struct rspamd_kv_hash_cache *new;
new = g_slice_alloc (sizeof (struct rspamd_kv_hash_cache));
- new->hash = g_hash_table_new_full (rspamd_strcase_hash, rspamd_strcase_equal, NULL, kv_elt_destroy_func);
+ new->hash = g_hash_table_new_full (rspamd_strcase_hash, rspamd_strcase_equal, NULL, NULL);
new->init_func = NULL;
new->insert_func = rspamd_kv_hash_insert;
new->lookup_func = rspamd_kv_hash_lookup;
struct rspamd_kv_element *elt;
struct rspamd_kv_radix_cache *cache = (struct rspamd_kv_radix_cache *)c;
guint32 rkey = rspamd_kv_radix_validate (key);
+ guint keylen;
if (rkey == 0) {
return NULL;
}
elt = (struct rspamd_kv_element *)radix32tree_find (cache->tree, rkey);
if ((uintptr_t)elt == RADIX_NO_VALUE) {
- elt = g_slice_alloc0 (sizeof (struct rspamd_kv_element) + len);
+ keylen = strlen (key);
+ elt = g_slice_alloc0 (sizeof (struct rspamd_kv_element) + len + keylen + 1);
elt->age = time (NULL);
- elt->key = key;
elt->size = len;
elt->hash = rkey;
- memcpy (elt->data, value, len);
+ memcpy (elt->data, key, keylen + 1);
+ memcpy (ELT_DATA (elt), value, len);
radix32tree_insert (cache->tree, rkey, 0xffffffff, (uintptr_t)elt);
}
KV_ELT_OUSTED = 1 << 3
};
+#define ELT_DATA(elt) (gchar *)(elt)->data + (elt)->keylen + 1
+#define ELT_KEY(elt) (gchar *)(elt)->data
+#define ELT_SIZE(elt) elt->size + sizeof(struct rspamd_kv_element) + elt->keylen + 1
+
/* Common structures description */
struct rspamd_kv_element {
gsize size; /*< size of element */
TAILQ_ENTRY (rspamd_kv_element) entry; /*< list entry */
guint32 hash; /*< numeric hash */
- gpointer key; /*< pointer to key */
+ guint keylen; /*< length of key */
gchar data[1]; /*< expandable data */
};
memset (&db_key, 0, sizeof(DBT));
memset (&db_data, 0, sizeof(DBT));
- db_key.size = strlen (op->elt->key);
- db_key.data = op->elt->key;
- db_data.size = op->elt->size + sizeof (struct rspamd_kv_element);
+
+ db_key.size = op->elt->keylen;
+ db_key.data = ELT_KEY (op->elt);
+ db_data.size = op->elt->size + sizeof (struct rspamd_kv_element) + op->elt->keylen + 1;
db_data.data = op->elt;
switch (op->op) {
struct bdb_op *op;
DBC *cursorp;
DB_TXN *txn = NULL;
- GList *cur, *tmp;
+ GList *cur;
/* Start transaction */
if (db->envp->txn_begin (db->envp, NULL, &txn, 0) != 0) {
cur = db->ops_queue->head;
while (cur) {
op = cur->data;
- tmp = cur;
- g_hash_table_remove (db->ops_hash, op->elt->key);
if (op->op == BDB_OP_DELETE) {
/* Also clean memory */
- g_slice_free1 (sizeof (struct rspamd_kv_element) + op->elt->size, op->elt);
+ g_slice_free1 (ELT_SIZE (op->elt), op->elt);
}
- cur = g_list_next (cur);
- g_queue_delete_link (db->ops_queue, tmp);
g_slice_free1 (sizeof (struct bdb_op), op);
+ cur = g_list_next (cur);
}
+ g_hash_table_remove_all (db->ops_hash);
+ g_queue_clear (db->ops_queue);
+
return TRUE;
}
elt->flags |= KV_ELT_DIRTY;
g_queue_push_head (db->ops_queue, op);
- g_hash_table_insert (db->ops_hash, key, op);
+ g_hash_table_insert (db->ops_hash, ELT_KEY (elt), op);
if (g_queue_get_length (db->ops_queue) >= db->sync_ops) {
return bdb_process_queue (db);
elt->flags |= KV_ELT_DIRTY;
g_queue_push_head (db->ops_queue, op);
- g_hash_table_insert (db->ops_hash, key, op);
+ g_hash_table_insert (db->ops_hash, ELT_KEY (elt), op);
if (g_queue_get_length (db->ops_queue) >= db->sync_ops) {
return bdb_process_queue (db);
if (cursorp->get (cursorp, &db_key, &db_data, DB_SET) == 0) {
elt = db_data.data;
- elt->key = key;
elt->flags &= ~KV_ELT_DIRTY;
}
op->elt = elt;
elt->flags |= KV_ELT_DIRTY;
- g_queue_push_head (db->ops_queue, elt);
- g_hash_table_insert (db->ops_hash, key, elt);
+ g_queue_push_head (db->ops_queue, op);
+ g_hash_table_insert (db->ops_hash, ELT_KEY(elt), op);
if (g_queue_get_length (db->ops_queue) >= db->sync_ops) {
bdb_process_queue (db);
}
else {
r = rspamd_snprintf (outbuf, sizeof (outbuf), "VALUE %s %ud %ud" CRLF,
- elt->key, elt->flags, elt->size);
+ ELT_KEY (elt), elt->flags, elt->size);
if (!rspamd_dispatcher_write (session->dispather, outbuf,
r, TRUE, FALSE)) {
return FALSE;
}
- if (!rspamd_dispatcher_write (session->dispather, elt->data, elt->size, TRUE, TRUE)) {
+ if (!rspamd_dispatcher_write (session->dispather, ELT_DATA(elt), elt->size, TRUE, TRUE)) {
return FALSE;
}
return rspamd_dispatcher_write (session->dispather, CRLF "END" CRLF,
if (elt != NULL) {
if ((elt->flags & KV_ELT_DIRTY) == 0) {
/* Free memory if backend has deleted this element */
- g_slice_free1 (elt->size + sizeof (struct rspamd_kv_element), elt);
+ g_slice_free1 (ELT_SIZE (elt), elt);
}
g_static_rw_lock_writer_unlock (&session->cf->storage->rwlock);
return rspamd_dispatcher_write (session->dispather, "DELETED" CRLF,