summaryrefslogtreecommitdiffstats
path: root/src/fuzzy_storage.c
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2013-06-11 15:14:06 +0100
committerVsevolod Stakhov <vsevolod@highsecure.ru>2013-06-11 15:14:06 +0100
commitb7ac6e35ef69c635370f1b9316c0643ad82c81db (patch)
treec2c294c7e397ad129bcce5718aa32ac1ef84e0c9 /src/fuzzy_storage.c
parentdef7ea2c8ba62a067b63f3be65bfd44147da315f (diff)
downloadrspamd-b7ac6e35ef69c635370f1b9316c0643ad82c81db.tar.gz
rspamd-b7ac6e35ef69c635370f1b9316c0643ad82c81db.zip
Add expiration logic.
Diffstat (limited to 'src/fuzzy_storage.c')
-rw-r--r--src/fuzzy_storage.c110
1 files changed, 84 insertions, 26 deletions
diff --git a/src/fuzzy_storage.c b/src/fuzzy_storage.c
index 53bde37bf..919d9e4c8 100644
--- a/src/fuzzy_storage.c
+++ b/src/fuzzy_storage.c
@@ -154,19 +154,73 @@ compare_nodes (gconstpointer a, gconstpointer b, gpointer unused)
return n1->value - n2->value;
}
+/**
+ * Expire nodes from list (need to be called in tree write lock)
+ * @param to_expire nodes that should be removed (if judy it is an array of nodes,
+ * and it is array of GList * otherwise)
+ * @param expired_num number of elements to expire
+ * @param ctx context
+ */
+static void
+expire_nodes (gpointer *to_expire, gint expired_num,
+ struct rspamd_fuzzy_storage_ctx *ctx)
+{
+ gint i;
+ struct rspamd_fuzzy_node *node;
+ GList *cur;
+ GQueue *head;
+
+ for (i = 0; i < expired_num; i ++) {
+#ifdef WITH_JUDY
+ PPvoid_t pvalue;
+ gpointer data;
+
+ if (ctx->use_judy) {
+ node = (struct rspamd_fuzzy_node *)to_expire[i];
+ JudySLDel (&jtree, node->h.hash_pipe, PJE0);
+ bloom_del (bf, node->h.hash_pipe);
+ g_slice_free1 (sizeof (struct rspamd_fuzzy_node), node);
+
+ pvalue = JudySLGet (jtree, node->h.hash_pipe, PJE0);
+ if (pvalue) {
+ data = *pvalue;
+ JudySLDel (&jtree, node->h.hash_pipe, PJE0);
+ g_slice_free1 (sizeof (struct rspamd_fuzzy_node), data);
+ server_stat->fuzzy_hashes_expired ++;
+ server_stat->fuzzy_hashes --;
+ }
+ }
+ else {
+#endif
+ cur = (GList *)to_expire[i];
+ node = (struct rspamd_fuzzy_node *)cur->data;
+ head = hashes[node->h.block_size % BUCKETS];
+ g_queue_delete_link (head, cur);
+ bloom_del (bf, node->h.hash_pipe);
+ server_stat->fuzzy_hashes_expired++;
+ server_stat->fuzzy_hashes--;
+ g_slice_free1 (sizeof(struct rspamd_fuzzy_node), node);
+#ifdef WITH_JUDY
+ }
+#endif
+ }
+}
+
static gpointer
sync_cache (gpointer ud)
{
- struct rspamd_worker *wrk = ud;
- gint fd, i;
- gchar *filename, header[4];
- GList *cur, *tmp;
- struct rspamd_fuzzy_node *node;
+ static const int max_expired = 8192;
+ struct rspamd_worker *wrk = ud;
+ gint fd, i, expired_num = 0;
+ gchar *filename, header[4];
+ GList *cur;
+ struct rspamd_fuzzy_node *node;
+ gpointer *nodes_expired = NULL;
guint64 expire, now;
struct rspamd_fuzzy_storage_ctx *ctx;
#ifdef WITH_JUDY
PPvoid_t pvalue;
- gchar indexbuf[1024], tmpindex[1024];
+ gchar indexbuf[1024];
#endif
ctx = wrk->ctx;
@@ -217,17 +271,14 @@ sync_cache (gpointer ud)
while (pvalue) {
node = *((struct rspamd_fuzzy_node **)pvalue);
if (now - node->time > expire) {
-#if 0
- /* Remove expired item */
- rspamd_strlcpy (tmpindex, indexbuf, sizeof (tmpindex));
- pvalue = JudySLNext (jtree, tmpindex, PJE0);
- JudySLDel (&jtree, indexbuf, PJE0);
- rspamd_strlcpy (indexbuf, tmpindex, sizeof (indexbuf));
- bloom_del (bf, node->h.hash_pipe);
- server_stat->fuzzy_hashes_expired ++;
- server_stat->fuzzy_hashes --;
- g_slice_free1 (sizeof (struct rspamd_fuzzy_node), node);
-#endif
+ if (nodes_expired == NULL) {
+ nodes_expired = g_malloc (max_expired * sizeof (gpointer));
+ }
+
+ if (expired_num < max_expired) {
+ nodes_expired[expired_num ++] = node;
+ }
+ pvalue = JudySLNext (jtree, indexbuf, PJE0);
continue;
}
if (write (fd, node, sizeof (struct rspamd_fuzzy_node)) == -1) {
@@ -254,16 +305,14 @@ sync_cache (gpointer ud)
while (cur) {
node = cur->data;
if (now - node->time > expire) {
-#if 0
- /* Remove expired item */
- tmp = cur;
+ if (nodes_expired == NULL) {
+ nodes_expired = g_malloc (max_expired * sizeof (gpointer));
+ }
+
+ if (expired_num < max_expired) {
+ nodes_expired[expired_num ++] = cur;
+ }
cur = g_list_next (cur);
- g_queue_delete_link (hashes[i], tmp);
- bloom_del (bf, node->h.hash_pipe);
- server_stat->fuzzy_hashes_expired++;
- server_stat->fuzzy_hashes--;
- g_slice_free1 (sizeof(struct rspamd_fuzzy_node), node);
-#endif
continue;
}
if (write (fd, node, sizeof(struct rspamd_fuzzy_node)) == -1) {
@@ -279,7 +328,16 @@ sync_cache (gpointer ud)
}
#endif
+ /* Now try to expire some nodes */
+ if (expired_num > 0) {
+ rspamd_rwlock_writer_lock (ctx->tree_lock);
+ expire_nodes (nodes_expired, expired_num, ctx);
+ rspamd_rwlock_writer_unlock (ctx->tree_lock);
+ }
end:
+ if (nodes_expired != NULL) {
+ g_free (nodes_expired);
+ }
(void) unlock_file (fd, FALSE);
close (fd);