enum rspamd_re_type type;
gpointer type_data;
gsize type_len;
- GHashTable *re_ids;
- GPtrArray *all_re;
+ GHashTable *re;
gchar hash[rspamd_cryptobox_HASHBYTES * 2 + 1];
};
GHashTableIter it;
gpointer k, v;
struct rspamd_re_class *re_class;
- rspamd_regexp_t *re;
guint i;
g_assert (cache != NULL);
while (g_hash_table_iter_next (&it, &k, &v)) {
re_class = v;
g_hash_table_iter_steal (&it);
-
- for (i = 0; i < re_class->all_re->len; i++) {
- re = g_ptr_array_index (re_class->all_re, i);
-
- rspamd_regexp_set_cache_id (re, RSPAMD_INVALID_ID);
- rspamd_regexp_unref (re);
- }
-
+ g_hash_table_unref (re_class->re);
g_slice_free1 (sizeof (*re_class), re_class);
}
{
guint64 class_id;
struct rspamd_re_class *re_class;
+ rspamd_regexp_t *nre;
g_assert (cache != NULL);
g_assert (re != NULL);
re_class->id = class_id;
re_class->type_len = datalen;
re_class->type = type;
- re_class->re_ids = g_hash_table_new (rspamd_regexp_hash,
- rspamd_regexp_equal);
+ re_class->re = g_hash_table_new_full (rspamd_regexp_hash,
+ rspamd_regexp_equal, NULL, (GDestroyNotify)rspamd_regexp_unref);
if (datalen > 0) {
re_class->type_data = g_slice_alloc (datalen);
memcpy (re_class->type_data, type_data, datalen);
}
- re_class->all_re = g_ptr_array_new ();
g_hash_table_insert (cache->re_classes, &re_class->id, re_class);
}
- g_ptr_array_add (re_class->all_re, rspamd_regexp_ref (re));
/*
* We set re id based on the global position in the cache
*/
rspamd_regexp_set_cache_id (re, cache->nre ++);
+ nre = rspamd_regexp_ref (re);
+ g_hash_table_insert (re_class->re, re, re);
+}
+
+void
+rspamd_re_cache_replace (struct rspamd_re_cache *cache,
+ rspamd_regexp_t *what,
+ enum rspamd_re_type type,
+ gpointer type_data,
+ gsize datalen,
+ rspamd_regexp_t *with)
+{
+ guint64 class_id, re_id;
+ struct rspamd_re_class *re_class;
+ rspamd_regexp_t *src;
+
+ g_assert (cache != NULL);
+ g_assert (what != NULL);
+ g_assert (with != NULL);
+
+ class_id = rspamd_re_cache_class_id (type, type_data, datalen);
+ re_class = g_hash_table_lookup (cache->re_classes, &class_id);
+
+ if (re_class != NULL) {
+ re_id = rspamd_regexp_get_cache_id (what);
+
+ g_assert (re_id != RSPAMD_INVALID_ID);
+ src = g_hash_table_lookup (re_class->re, what);
+
+ if (src) {
+ g_hash_table_replace (re_class->re, what, with);
+ }
+ }
}
void
rspamd_re_cache_init (struct rspamd_re_cache *cache)
{
- GHashTableIter it;
+ GHashTableIter it, cit;
gpointer k, v;
struct rspamd_re_class *re_class;
rspamd_cryptobox_hash_state_t st;
rspamd_cryptobox_hash_init (&st, NULL, 0);
rspamd_cryptobox_hash_update (&st, (gpointer)&re_class->id,
sizeof (re_class->id));
+ g_hash_table_iter_init (&cit, re_class->re);
- for (i = 0; i < re_class->all_re->len; i ++) {
- re = g_ptr_array_index (re_class->all_re, i);
+ while (g_hash_table_iter_next (&cit, &k, &v)) {
+ re = v;
rspamd_cryptobox_hash_update (&st, rspamd_regexp_get_id (re),
rspamd_cryptobox_HASHBYTES);
}
void rspamd_re_cache_add (struct rspamd_re_cache *cache, rspamd_regexp_t *re,
enum rspamd_re_type type, gpointer type_data, gsize datalen);
+/**
+ * Replace regexp in the cache with another regexp
+ * @param cache cache object
+ * @param what re to replace
+ * @param type type of object
+ * @param type_data associated data with the type (e.g. header name)
+ * @param datalen associated data length
+ * @param with regexp object to replace the origin
+ */
+void rspamd_re_cache_replace (struct rspamd_re_cache *cache,
+ rspamd_regexp_t *what,
+ enum rspamd_re_type type,
+ gpointer type_data,
+ gsize datalen,
+ rspamd_regexp_t *with);
+
/**
* Initialize and optimize re cache structure
*/