aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2015-03-05 09:50:25 +0000
committerVsevolod Stakhov <vsevolod@highsecure.ru>2015-03-05 09:50:25 +0000
commit6aeab25b1d1e1d49b94ee152ded2c011c6f7d5e1 (patch)
tree71c36fdb81260537aeb493e364374b691110a035
parent58ff3a43b71928263415a8a874943de9de158018 (diff)
downloadrspamd-6aeab25b1d1e1d49b94ee152ded2c011c6f7d5e1.tar.gz
rspamd-6aeab25b1d1e1d49b94ee152ded2c011c6f7d5e1.zip
Implement cache functions.
-rw-r--r--src/libutil/regexp.c98
-rw-r--r--src/libutil/regexp.h10
2 files changed, 103 insertions, 5 deletions
diff --git a/src/libutil/regexp.c b/src/libutil/regexp.c
index e4fbdef12..2dfe3e918 100644
--- a/src/libutil/regexp.c
+++ b/src/libutil/regexp.c
@@ -29,13 +29,15 @@
#include "ref.h"
#include <pcre.h>
+typedef guchar regexp_id_t[BLAKE2B_OUTBYTES];
+
struct rspamd_regexp_s {
- gdouble exec_time; /**< average execution time */
+ gdouble exec_time;
pcre *re;
pcre_extra *extra;
pcre *raw_re;
pcre_extra *raw_extra;
- guchar id[BLAKE2B_OUTBYTES / 2];
+ regexp_id_t id;
ref_entry_t ref;
};
@@ -45,6 +47,18 @@ struct rspamd_regexp_cache {
static struct rspamd_regexp_cache *global_re_cache = NULL;
+static void
+rspamd_regexp_generate_id (const gchar *pattern, const gchar *flags,
+ regexp_id_t out)
+{
+ blake2b_state st;
+
+ blake2b_init (&st, sizeof (regexp_id_t));
+ blake2b_update (&st, flags, strlen (flags));
+ blake2b_update (&st, pattern, strlen (pattern));
+ blake2b_final (&st, out, sizeof (regexp_id_t));
+}
+
rspamd_regexp_t*
rspamd_regexp_new (const gchar *pattern, const gchar *flags,
GError **err)
@@ -70,10 +84,35 @@ rspamd_regexp_unref (rspamd_regexp_t *re)
REF_RELEASE (re);
}
+static gboolean
+rspamd_regexp_equal (gconstpointer a, gconstpointer b)
+{
+ const guchar *ia = a, *ib = b;
+
+ return (memcmp (ia, ib, sizeof (regexp_id_t)) == 0);
+}
+
+static guint32
+rspamd_regexp_hash (gconstpointer a)
+{
+ const guchar *ia = a;
+ guint32 res;
+
+ memcpy (&res, ia, sizeof (res));
+
+ return res;
+}
+
struct rspamd_regexp_cache*
rspamd_regexp_cache_new (void)
{
- return NULL;
+ struct rspamd_regexp_cache *ncache;
+
+ ncache = g_slice_alloc (sizeof (*ncache));
+ ncache->tbl = g_hash_table_new_full (rspamd_regexp_hash, rspamd_regexp_equal,
+ NULL, (GDestroyNotify)rspamd_regexp_unref);
+
+ return ncache;
}
@@ -82,7 +121,19 @@ rspamd_regexp_cache_query (struct rspamd_regexp_cache* cache,
const gchar *pattern,
const gchar *flags)
{
- return NULL;
+ rspamd_regexp_t *res = NULL;
+ regexp_id_t id;
+
+ if (cache == NULL) {
+ cache = global_re_cache;
+ }
+
+ g_assert (cache != NULL);
+ rspamd_regexp_generate_id (pattern, flags, id);
+
+ res = g_hash_table_lookup (cache->tbl, id);
+
+ return res;
}
@@ -91,11 +142,48 @@ rspamd_regexp_cache_create (struct rspamd_regexp_cache *cache,
const gchar *pattern,
const gchar *flags, GError **err)
{
- return NULL;
+ rspamd_regexp_t *res;
+
+ if (cache == NULL) {
+ cache = global_re_cache;
+ }
+
+ g_assert (cache != NULL);
+ res = rspamd_regexp_cache_query (cache, pattern, flags);
+
+ if (res != NULL) {
+ return res;
+ }
+
+ res = rspamd_regexp_new (pattern, flags, err);
+
+ if (res) {
+ g_hash_table_insert (cache->tbl, res->id, res);
+ }
+
+ return res;
}
void
rspamd_regexp_cache_destroy (struct rspamd_regexp_cache *cache)
{
+ if (cache != NULL) {
+ g_hash_table_destroy (cache->tbl);
+ }
+}
+void
+rspamd_regexp_library_init (void)
+{
+ if (global_re_cache == NULL) {
+ global_re_cache = rspamd_regexp_cache_new ();
+ }
+}
+
+void
+rspamd_regexp_library_finalize (void)
+{
+ if (global_re_cache != NULL) {
+ rspamd_regexp_cache_destroy (global_re_cache);
+ }
}
diff --git a/src/libutil/regexp.h b/src/libutil/regexp.h
index 4ca4196a0..e44fbee01 100644
--- a/src/libutil/regexp.h
+++ b/src/libutil/regexp.h
@@ -105,4 +105,14 @@ rspamd_regexp_t* rspamd_regexp_cache_create (struct rspamd_regexp_cache *cache,
*/
void rspamd_regexp_cache_destroy (struct rspamd_regexp_cache *cache);
+/**
+ * Initialize superglobal regexp cache and library
+ */
+void rspamd_regexp_library_init (void);
+
+/**
+ * Cleanup internal library structures
+ */
+void rspamd_regexp_library_finalize (void);
+
#endif /* REGEXP_H_ */