aboutsummaryrefslogtreecommitdiffstats
path: root/src/fuzzy_storage.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/fuzzy_storage.c')
-rw-r--r--src/fuzzy_storage.c222
1 files changed, 143 insertions, 79 deletions
diff --git a/src/fuzzy_storage.c b/src/fuzzy_storage.c
index 1e8243ec0..99f4449b4 100644
--- a/src/fuzzy_storage.c
+++ b/src/fuzzy_storage.c
@@ -101,6 +101,9 @@ struct rspamd_fuzzy_storage_ctx {
rspamd_mutex_t *update_mtx;
GCond *update_cond;
GThread *update_thread;
+
+ /* lmdb interface */
+ MDB_env *env;
};
struct rspamd_legacy_fuzzy_node {
@@ -122,6 +125,12 @@ struct fuzzy_session {
extern sig_atomic_t wanna_die;
+static GQuark
+rspamd_fuzzy_quark(void)
+{
+ return g_quark_from_static_string ("fuzzy-storage");
+}
+
static void
legacy_fuzzy_node_free (gpointer n)
{
@@ -156,7 +165,7 @@ legacy_expire_nodes (gpointer *to_expire, gint expired_num,
}
static gpointer
-legacy_sync_cache (gpointer ud)
+rspamd_fuzzy_storage_sync_cb (gpointer ud)
{
static const int max_expired = 8192;
struct rspamd_worker *wrk = ud;
@@ -170,7 +179,7 @@ legacy_sync_cache (gpointer ud)
ctx = wrk->ctx;
- for (;; ) {
+ for (;;) {
rspamd_mutex_lock (ctx->update_mtx);
@@ -180,79 +189,86 @@ legacy_sync_cache (gpointer ud)
}
msg_info ("syncing fuzzy hash storage");
- filename = ctx->hashfile;
- if (filename == NULL ) {
- rspamd_mutex_unlock (ctx->update_mtx);
- if (wanna_die) {
- return NULL;
+ if (ctx->legacy) {
+ filename = ctx->hashfile;
+ if (filename == NULL ) {
+ rspamd_mutex_unlock (ctx->update_mtx);
+ if (wanna_die) {
+ return NULL;
+ }
+ continue;
}
- continue;
- }
- expire = ctx->expire;
+ expire = ctx->expire;
- if ((fd = open (filename, O_WRONLY | O_TRUNC | O_CREAT,
- S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH)) == -1) {
- msg_err (
- "cannot create hash file %s: %s", filename, strerror (errno));
- rspamd_mutex_unlock (ctx->update_mtx);
- if (wanna_die) {
- return NULL;
+ if ((fd = open (filename, O_WRONLY | O_TRUNC | O_CREAT,
+ S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH)) == -1) {
+ msg_err (
+ "cannot create hash file %s: %s", filename,
+ strerror (errno));
+ rspamd_mutex_unlock (ctx->update_mtx);
+ if (wanna_die) {
+ return NULL;
+ }
+ continue;
}
- continue;
- }
- (void) rspamd_file_lock (fd, FALSE);
+ (void) rspamd_file_lock (fd, FALSE);
- now = (guint64) time (NULL );
+ now = (guint64) time (NULL );
- /* Fill header */
- memcpy (header, FUZZY_FILE_MAGIC, 3);
- header[3] = (gchar) CURRENT_FUZZY_VERSION;
- if (write (fd, header, sizeof(header)) == -1) {
- msg_err (
- "cannot write file %s while writing header: %s",
- filename,
- strerror (errno));
- goto end;
- }
-
- rspamd_rwlock_reader_lock (ctx->tree_lock);
- g_hash_table_iter_init (&iter, static_hash);
+ /* Fill header */
+ memcpy (header, FUZZY_FILE_MAGIC, 3);
+ header[3] = (gchar) CURRENT_FUZZY_VERSION;
+ if (write (fd, header, sizeof(header)) == -1) {
+ msg_err (
+ "cannot write file %s while writing header: %s",
+ filename,
+ strerror (errno));
+ goto end;
+ }
- while (g_hash_table_iter_next (&iter, NULL, (void **)&node)) {
- if (node->time == INVALID_NODE_TIME || now - node->time >
- expire) {
- if (nodes_expired == NULL) {
- nodes_expired = g_malloc (
- max_expired * sizeof (gpointer));
+ rspamd_rwlock_reader_lock (ctx->tree_lock);
+ g_hash_table_iter_init (&iter, static_hash);
+
+ while (g_hash_table_iter_next (&iter, NULL, (void **)&node)) {
+ if (node->time == INVALID_NODE_TIME ||
+ now - node->time > expire) {
+ if (nodes_expired == NULL) {
+ nodes_expired = g_malloc (
+ max_expired * sizeof (gpointer));
+ }
+
+ if (expired_num < max_expired) {
+ nodes_expired[expired_num++] = node;
+ }
+ continue;
}
-
- if (expired_num < max_expired) {
- nodes_expired[expired_num++] = node;
+ if (write (fd, node, sizeof (struct rspamd_legacy_fuzzy_node))
+ == -1) {
+ msg_err ("cannot write file %s: %s", filename,
+ strerror (errno));
+ goto end;
}
- continue;
}
- if (write (fd, node, sizeof (struct rspamd_legacy_fuzzy_node)) == -1) {
- msg_err ("cannot write file %s: %s", filename,
- strerror (errno));
- goto end;
- }
- }
- rspamd_rwlock_reader_unlock (ctx->tree_lock);
+ rspamd_rwlock_reader_unlock (ctx->tree_lock);
- /* Now try to expire some nodes */
- if (expired_num > 0) {
- rspamd_rwlock_writer_lock (ctx->tree_lock);
- legacy_expire_nodes (nodes_expired, expired_num, ctx);
- rspamd_rwlock_writer_unlock (ctx->tree_lock);
+ /* Now try to expire some nodes */
+ if (expired_num > 0) {
+ rspamd_rwlock_writer_lock (ctx->tree_lock);
+ legacy_expire_nodes (nodes_expired, expired_num, ctx);
+ rspamd_rwlock_writer_unlock (ctx->tree_lock);
+ }
+ mods = 0;
+ end:
+ if (nodes_expired != NULL) {
+ g_free (nodes_expired);
+ }
+ (void) rspamd_file_unlock (fd, FALSE);
+ close (fd);
}
- mods = 0;
-end:
- if (nodes_expired != NULL) {
- g_free (nodes_expired);
+ else {
+ mdb_env_sync (ctx->env, 0);
}
- (void) rspamd_file_unlock (fd, FALSE);
- close (fd);
rspamd_mutex_unlock (ctx->update_mtx);
if (wanna_die) {
@@ -651,6 +667,38 @@ legacy_fuzzy_cmd (struct fuzzy_session *session)
#undef LEGACY_CMD_PROCESS
+/*
+ * MDB Interface
+ */
+
+static gboolean
+rspamd_fuzzy_storage_open_db (struct rspamd_fuzzy_storage_ctx *ctx, GError **err)
+{
+ gchar *dir;
+ gint rc;
+
+ if (ctx->hashfile == NULL) {
+ g_set_error (err, rspamd_fuzzy_quark(), 500, "Cannot work without file");
+ return FALSE;
+ }
+
+ dir = g_path_get_dirname (ctx->hashfile);
+ if (dir == NULL || access (dir, W_OK) == -1) {
+ g_set_error (err, rspamd_fuzzy_quark(), errno, "Cannot access directory: %s",
+ strerror (errno));
+ return FALSE;
+ }
+
+ mdb_env_create (&ctx->env);
+
+ if ((rc = mdb_env_open (ctx->env, dir, MDB_NOSYNC, 0600)) != 0) {
+ g_set_error (err, rspamd_fuzzy_quark(), errno, "Cannot open mdb_env: %s",
+ mdb_strerror (rc));
+ return FALSE;
+ }
+
+ return TRUE;
+}
/*
* Accept new connection and construct task
@@ -744,16 +792,7 @@ init_fuzzy (struct rspamd_config *cfg)
ctx = g_malloc0 (sizeof (struct rspamd_fuzzy_storage_ctx));
ctx->max_mods = DEFAULT_MOD_LIMIT;
- ctx->frequent_score = DEFAULT_FREQUENT_SCORE;
ctx->expire = DEFAULT_EXPIRE;
- ctx->tree_lock = rspamd_rwlock_new ();
- ctx->update_mtx = rspamd_mutex_new ();
-#if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION > 30))
- ctx->update_cond = g_malloc0 (sizeof (GCond));
- g_cond_init (ctx->update_cond);
-#else
- ctx->update_cond = g_cond_new ();
-#endif
rspamd_rcl_register_worker_option (cfg, type, "hashfile",
rspamd_rcl_parse_struct_string, ctx,
@@ -771,6 +810,10 @@ init_fuzzy (struct rspamd_config *cfg)
rspamd_rcl_parse_struct_string, ctx,
G_STRUCT_OFFSET (struct rspamd_fuzzy_storage_ctx, hashfile), 0);
+ rspamd_rcl_register_worker_option (cfg, type, "legacy",
+ rspamd_rcl_parse_struct_boolean, ctx,
+ G_STRUCT_OFFSET (struct rspamd_fuzzy_storage_ctx, legacy), 0);
+
/* Legacy options */
rspamd_rcl_register_worker_option (cfg, type, "max_mods",
rspamd_rcl_parse_struct_integer, ctx,
@@ -827,15 +870,32 @@ start_fuzzy (struct rspamd_worker *worker)
sigh->post_handler = sigterm_handler;
sigh->handler_data = worker;
- static_hash = g_hash_table_new_full (rspamd_fuzzy_hash, rspamd_fuzzy_equal,
+ if (ctx->legacy) {
+ ctx->tree_lock = rspamd_rwlock_new ();
+ ctx->update_mtx = rspamd_mutex_new ();
+#if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION > 30))
+ ctx->update_cond = g_malloc0 (sizeof (GCond));
+ g_cond_init (ctx->update_cond);
+#else
+ ctx->update_cond = g_cond_new ();
+#endif
+ static_hash = g_hash_table_new_full (rspamd_fuzzy_hash, rspamd_fuzzy_equal,
NULL, legacy_fuzzy_node_free);
- /* Init bloom filter */
- bf = rspamd_bloom_create (2000000L, RSPAMD_DEFAULT_BLOOM_HASHES);
- /* Try to read hashes from file */
- if (!legacy_read_db (worker)) {
- msg_err (
- "cannot read hashes file, it can be created after save procedure");
+ /* Init bloom filter */
+ bf = rspamd_bloom_create (2000000L, RSPAMD_DEFAULT_BLOOM_HASHES);
+ /* Try to read hashes from file */
+ if (!legacy_read_db (worker)) {
+ msg_err (
+ "cannot read hashes file, it can be created after save procedure");
+ }
+ }
+ else {
+ if (!rspamd_fuzzy_storage_open_db (ctx, &err)) {
+ msg_err (err->message);
+ g_error_free (err);
+ exit (EXIT_FAILURE);
+ }
}
/* Timer event */
@@ -863,7 +923,7 @@ start_fuzzy (struct rspamd_worker *worker)
rspamd_map_watch (worker->srv->cfg, ctx->ev_base);
ctx->update_thread = rspamd_create_thread ("fuzzy update",
- legacy_sync_cache,
+ rspamd_fuzzy_storage_sync_cb,
worker,
&err);
if (ctx->update_thread == NULL) {
@@ -876,6 +936,10 @@ start_fuzzy (struct rspamd_worker *worker)
g_thread_join (ctx->update_thread);
}
+ if (!ctx->legacy) {
+ mdb_env_close (ctx->env);
+ }
+
rspamd_log_close (rspamd_main->logger);
exit (EXIT_SUCCESS);
}