diff options
author | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2018-10-26 15:25:41 +0100 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2018-10-26 15:25:41 +0100 |
commit | c6ccb8d28f6e45742760043333b5ae374e9fbd12 (patch) | |
tree | a4406762354c28eb67d1ca958199dccf7e42f07a | |
parent | 7f702c6f3416f85238a48794c86bc8cb334e4df6 (diff) | |
download | rspamd-c6ccb8d28f6e45742760043333b5ae374e9fbd12.tar.gz rspamd-c6ccb8d28f6e45742760043333b5ae374e9fbd12.zip |
[Rework] Completely rework symbols cache management
-rw-r--r-- | CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/libserver/symbols_cache.c | 778 | ||||
-rw-r--r-- | src/libserver/symbols_cache.h | 20 | ||||
-rw-r--r-- | src/lua/lua_config.c | 4 | ||||
-rw-r--r-- | src/plugins/regexp.c | 4 |
5 files changed, 410 insertions, 397 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 95895cd2d..4f4eb9a00 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -795,6 +795,7 @@ ENDIF() IF(SUPPORT_STD11_FLAG) SET(CMAKE_C_WARN_FLAGS "${CMAKE_C_WARN_FLAGS} -std=c11") ELSE(SUPPORT_STD11_FLAG) + MESSAGE("C11 compatible compiler is strongly recommended") IF(SUPPORT_STD99_FLAG) SET(CMAKE_C_WARN_FLAGS "${CMAKE_C_WARN_FLAGS} -std=c99") ENDIF(SUPPORT_STD99_FLAG) diff --git a/src/libserver/symbols_cache.c b/src/libserver/symbols_cache.c index 5584d48cf..a98f4317a 100644 --- a/src/libserver/symbols_cache.c +++ b/src/libserver/symbols_cache.c @@ -25,6 +25,10 @@ #include "libserver/worker_util.h" #include <math.h> +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L +# include <stdalign.h> +#endif + #define msg_err_cache(...) rspamd_default_log_function (G_LOG_LEVEL_CRITICAL, \ cache->static_pool->tag.tagname, cache->cfg->checksum, \ G_STRFUNC, \ @@ -49,19 +53,19 @@ INIT_LOG_MODULE(symcache) #define CHECK_START_BIT(checkpoint, item) \ - isset((checkpoint)->started_bits, (item)->id) + isset((checkpoint)->cur_bits->started, (item)->id) #define SET_START_BIT(checkpoint, item) \ - setbit((checkpoint)->started_bits, (item)->id ) + setbit((checkpoint)->cur_bits->started, (item)->id ) #define CHECK_FINISH_BIT(checkpoint, item) \ - isset((checkpoint)->finished_bits, (item)->id) + isset((checkpoint)->cur_bits->finished, (item)->id) #define SET_FINISH_BIT(checkpoint, item) \ - setbit((checkpoint)->finished_bits, (item)->id) + setbit((checkpoint)->cur_bits->finished, (item)->id) static const guchar rspamd_symbols_cache_magic[8] = {'r', 's', 'c', 2, 0, 0, 0, 0 }; -static gint rspamd_symbols_cache_find_symbol_parent (struct symbols_cache *cache, - const gchar *name); +static gint rspamd_symbols_cache_find_filter (struct symbols_cache *cache, + const gchar *name); struct rspamd_symbols_cache_header { guchar magic[8]; @@ -80,11 +84,12 @@ struct symbols_cache { /* Hash table for fast access */ GHashTable *items_by_symbol; struct symbols_cache_order *items_by_order; - GPtrArray *items_by_id; + GPtrArray *filters; GPtrArray *prefilters; GPtrArray *postfilters; GPtrArray *composites; GPtrArray *idempotent; + GPtrArray *virtual; GList *delayed_deps; GList *delayed_conditions; rspamd_mempool_t *static_pool; @@ -115,7 +120,6 @@ struct rspamd_symcache_item { struct item_stat *st; guint64 last_count; - /* Per process counter */ gdouble start_ticks; guint async_events; @@ -124,15 +128,23 @@ struct rspamd_symcache_item { enum rspamd_symbol_type type; /* Callback data */ - symbol_func_t func; - gpointer user_data; + union { + struct { + symbol_func_t func; + gpointer user_data; + gint condition_cb; + } normal; + struct { + gint parent; + } virtual; + } specific; /* Condition of execution */ - gint condition_cb; gboolean enabled; + /* Used for async stuff checks */ + gboolean is_filter; + gboolean is_virtual; - /* Parent symbol id for virtual symbols */ - gint parent; /* Priority */ gint priority; /* Topological order */ @@ -172,16 +184,33 @@ enum rspamd_cache_savepoint_stage { RSPAMD_CACHE_PASS_DONE, }; +struct cache_bits { +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L + _Alignas(guint64) guint8 *started; + _Alignas(guint64) guint8 *finished; +#else +#warning "outdated compiler, please use C11 compiler" + guint8 *started; + guint8 *finished; +#endif +}; + struct cache_savepoint { - guchar *started_bits; - guchar *finished_bits; enum rspamd_cache_savepoint_stage pass; guint version; + guint items_inflight; + struct rspamd_metric_result *rs; gdouble lim; + struct rspamd_symcache_item *cur_item; - guint items_inflight; + struct cache_bits *cur_bits; struct symbols_cache_order *order; + + struct cache_bits prefilters; + struct cache_bits filters; + struct cache_bits postfilters; + struct cache_bits idempotent; }; struct rspamd_cache_refresh_cbdata { @@ -217,12 +246,6 @@ static void rspamd_symbols_cache_enable_symbol_checkpoint (struct rspamd_task *t static void rspamd_symbols_cache_disable_all_symbols (struct rspamd_task *task, struct symbols_cache *cache); -static GQuark -rspamd_symbols_cache_quark (void) -{ - return g_quark_from_static_string ("symbols-cache"); -} - static void rspamd_symbols_cache_order_dtor (gpointer p) { @@ -391,20 +414,13 @@ rspamd_symbols_cache_resort (struct symbols_cache *cache) guint64 total_hits = 0; struct rspamd_symcache_item *it; - ord = rspamd_symbols_cache_order_new (cache, cache->used_items); + ord = rspamd_symbols_cache_order_new (cache, cache->filters->len); - for (i = 0; i < cache->used_items; i ++) { - it = g_ptr_array_index (cache->items_by_id, i); + for (i = 0; i < cache->filters->len; i ++) { + it = g_ptr_array_index (cache->filters, i); total_hits += it->st->total_hits; - - if (!(it->type & (SYMBOL_TYPE_PREFILTER| - SYMBOL_TYPE_POSTFILTER| - SYMBOL_TYPE_COMPOSITE))) { - if (it->parent == -1 && it->func) { - it->order = 0; - g_ptr_array_add (ord->d, it); - } - } + it->order = 0; + g_ptr_array_add (ord->d, it); } /* Topological sort, intended to be O(N) but my implementation @@ -450,9 +466,10 @@ rspamd_symbols_cache_post_init (struct symbols_cache *cache) while (cur) { ddep = cur->data; - id = rspamd_symbols_cache_find_symbol_parent (cache, ddep->from); + id = rspamd_symbols_cache_find_filter (cache, ddep->from); + if (id != -1) { - it = g_ptr_array_index (cache->items_by_id, id); + it = g_ptr_array_index (cache->filters, id); } else { it = NULL; @@ -475,13 +492,7 @@ rspamd_symbols_cache_post_init (struct symbols_cache *cache) while (cur) { dcond = cur->data; - id = rspamd_symbols_cache_find_symbol_parent (cache, dcond->sym); - if (id != -1) { - it = g_ptr_array_index (cache->items_by_id, id); - } - else { - it = NULL; - } + it = g_hash_table_lookup (cache->items_by_symbol, dcond->sym); if (it == NULL) { msg_err_cache ( @@ -490,23 +501,23 @@ rspamd_symbols_cache_post_init (struct symbols_cache *cache) luaL_unref (dcond->L, LUA_REGISTRYINDEX, dcond->cbref); } else { - rspamd_symbols_cache_add_condition (cache, it->id, dcond->L, - dcond->cbref); + it->specific.normal.condition_cb = dcond->cbref; } cur = g_list_next (cur); } - for (i = 0; i < cache->items_by_id->len; i ++) { - it = g_ptr_array_index (cache->items_by_id, i); + for (i = 0; i < cache->filters->len; i ++) { + it = g_ptr_array_index (cache->filters, i); for (j = 0; j < it->deps->len; j ++) { dep = g_ptr_array_index (it->deps, j); dit = g_hash_table_lookup (cache->items_by_symbol, dep->sym); if (dit != NULL) { - if (dit->parent != -1) { - dit = g_ptr_array_index (cache->items_by_id, dit->parent); + if (dit->is_virtual != -1) { + dit = g_ptr_array_index (cache->filters, + dit->specific.virtual.parent); } if (dit->id == i) { @@ -517,6 +528,7 @@ rspamd_symbols_cache_post_init (struct symbols_cache *cache) else { rdep = rspamd_mempool_alloc (cache->static_pool, sizeof (*rdep)); + rdep->sym = dep->sym; rdep->item = it; rdep->id = i; @@ -688,10 +700,10 @@ rspamd_symbols_cache_load_items (struct symbols_cache *cache, const gchar *name) } } - if ((item->type & SYMBOL_TYPE_VIRTUAL) && - !(item->type & SYMBOL_TYPE_SQUEEZED) && item->parent != -1) { - g_assert (item->parent < (gint)cache->items_by_id->len); - parent = g_ptr_array_index (cache->items_by_id, item->parent); + if (item->is_virtual) { + g_assert (item->specific.virtual.parent < (gint)cache->filters->len); + parent = g_ptr_array_index (cache->filters, + item->specific.virtual.parent); if (parent->st->weight < item->st->weight) { parent->st->weight = item->st->weight; @@ -812,12 +824,12 @@ rspamd_symbols_cache_save_items (struct symbols_cache *cache, const gchar *name) gint rspamd_symbols_cache_add_symbol (struct symbols_cache *cache, - const gchar *name, - gint priority, - symbol_func_t func, - gpointer user_data, - enum rspamd_symbol_type type, - gint parent) + const gchar *name, + gint priority, + symbol_func_t func, + gpointer user_data, + enum rspamd_symbol_type type, + gint parent) { struct rspamd_symcache_item *item = NULL; @@ -848,7 +860,6 @@ rspamd_symbols_cache_add_symbol (struct symbols_cache *cache, sizeof (struct rspamd_symcache_item)); item->st = rspamd_mempool_alloc0_shared (cache->static_pool, sizeof (*item->st)); - item->condition_cb = -1; item->enabled = TRUE; /* @@ -857,8 +868,6 @@ rspamd_symbols_cache_add_symbol (struct symbols_cache *cache, */ item->cd = rspamd_mempool_alloc0 (cache->static_pool, sizeof (struct rspamd_counter_data)); - item->func = func; - item->user_data = user_data; item->priority = priority; item->type = type; @@ -867,8 +876,59 @@ rspamd_symbols_cache_add_symbol (struct symbols_cache *cache, item->priority = 1; } - item->id = cache->used_items; - item->parent = parent; + if (func) { + /* Non-virtual symbol */ + g_assert (parent == -1); + + if (item->type & SYMBOL_TYPE_PREFILTER) { + item->id = cache->prefilters->len; + g_ptr_array_add (cache->prefilters, item); + } + else if (item->type & SYMBOL_TYPE_IDEMPOTENT) { + item->id = cache->idempotent->len; + g_ptr_array_add (cache->idempotent, item); + } + else if (item->type & SYMBOL_TYPE_POSTFILTER) { + item->id = cache->postfilters->len; + g_ptr_array_add (cache->postfilters, item); + } + else { + item->id = cache->filters->len; + item->is_filter = TRUE; + g_ptr_array_add (cache->filters, item); + } + + item->specific.normal.func = func; + item->specific.normal.user_data = user_data; + item->specific.normal.condition_cb = -1; + } + else { + /* + * Three possibilities here when no function is specified: + * - virtual symbol + * - classifier symbol + * - composite symbol + */ + if (item->type & SYMBOL_TYPE_COMPOSITE) { + item->id = cache->composites->len; + g_ptr_array_add (cache->composites, item); + } + else if (item->type & SYMBOL_TYPE_CLASSIFIER) { + /* Treat it as virtual */ + item->id = cache->virtual->len; + g_ptr_array_add (cache->virtual, item); + } + else { + /* Require parent */ + g_assert (parent != -1); + + item->is_virtual = TRUE; + item->specific.virtual.parent = parent; + item->id = cache->virtual->len; + g_ptr_array_add (cache->virtual, item); + } + } + cache->used_items ++; cache->id ++; @@ -890,67 +950,28 @@ rspamd_symbols_cache_add_symbol (struct symbols_cache *cache, msg_debug_cache ("used items: %d, added symbol: %s, %d", cache->used_items, name, item->id); } else { + g_assert (func != NULL); msg_debug_cache ("used items: %d, added unnamed symbol: %d", cache->used_items, item->id); } - g_ptr_array_add (cache->items_by_id, item); - item->deps = g_ptr_array_new (); - item->rdeps = g_ptr_array_new (); - rspamd_mempool_add_destructor (cache->static_pool, - rspamd_ptr_array_free_hard, item->deps); - rspamd_mempool_add_destructor (cache->static_pool, - rspamd_ptr_array_free_hard, item->rdeps); + if (item->is_filter) { + /* Only plain filters can have deps and rdeps */ + item->deps = g_ptr_array_new (); + item->rdeps = g_ptr_array_new (); + rspamd_mempool_add_destructor (cache->static_pool, + rspamd_ptr_array_free_hard, item->deps); + rspamd_mempool_add_destructor (cache->static_pool, + rspamd_ptr_array_free_hard, item->rdeps); + } if (name != NULL) { g_hash_table_insert (cache->items_by_symbol, item->symbol, item); } - if (item->type & SYMBOL_TYPE_PREFILTER) { - g_ptr_array_add (cache->prefilters, item); - } - else if (item->type & SYMBOL_TYPE_IDEMPOTENT) { - g_ptr_array_add (cache->idempotent, item); - } - else if (item->type & SYMBOL_TYPE_POSTFILTER) { - g_ptr_array_add (cache->postfilters, item); - } - else if (item->type & SYMBOL_TYPE_COMPOSITE) { - g_ptr_array_add (cache->composites, item); - } - return item->id; } -gboolean -rspamd_symbols_cache_add_condition (struct symbols_cache *cache, gint id, - lua_State *L, gint cbref) -{ - struct rspamd_symcache_item *item; - - g_assert (cache != NULL); - - if (id < 0 || id >= (gint)cache->items_by_id->len) { - return FALSE; - } - - item = g_ptr_array_index (cache->items_by_id, id); - - if (item->condition_cb != -1) { - /* We already have a condition, so we need to remove old cbref first */ - msg_warn_cache ("rewriting condition for symbol %s", item->symbol); - luaL_unref (L, LUA_REGISTRYINDEX, item->condition_cb); - } - - item->condition_cb = cbref; - cache->id ++; - - msg_debug_cache ("adding condition at lua ref %d to %s (%d)", - cbref, item->symbol, item->id); - - return TRUE; -} - void rspamd_symbols_cache_set_peak_callback (struct symbols_cache *cache, gint cbref) @@ -970,19 +991,11 @@ gboolean rspamd_symbols_cache_add_condition_delayed (struct symbols_cache *cache, const gchar *sym, lua_State *L, gint cbref) { - gint id; struct delayed_cache_condition *ncond; g_assert (cache != NULL); g_assert (sym != NULL); - id = rspamd_symbols_cache_find_symbol_parent (cache, sym); - - if (id != -1) { - /* We already know id, so just register a direct condition */ - return rspamd_symbols_cache_add_condition (cache, id, L, cbref); - } - ncond = g_malloc0 (sizeof (*ncond)); ncond->sym = g_strdup (sym); ncond->cbref = cbref; @@ -1049,7 +1062,7 @@ rspamd_symbols_cache_destroy (struct symbols_cache *cache) g_hash_table_destroy (cache->items_by_symbol); rspamd_mempool_delete (cache->static_pool); - g_ptr_array_free (cache->items_by_id, TRUE); + g_ptr_array_free (cache->filters, TRUE); g_ptr_array_free (cache->prefilters, TRUE); g_ptr_array_free (cache->postfilters, TRUE); g_ptr_array_free (cache->idempotent, TRUE); @@ -1074,11 +1087,12 @@ rspamd_symbols_cache_new (struct rspamd_config *cfg) rspamd_mempool_new (rspamd_mempool_suggest_size (), "symcache"); cache->items_by_symbol = g_hash_table_new (rspamd_str_hash, rspamd_str_equal); - cache->items_by_id = g_ptr_array_new (); + cache->filters = g_ptr_array_new (); cache->prefilters = g_ptr_array_new (); cache->postfilters = g_ptr_array_new (); cache->idempotent = g_ptr_array_new (); cache->composites = g_ptr_array_new (); + cache->virtual = g_ptr_array_new (); cache->reload_time = cfg->cache_reload_time; cache->total_hits = 1; cache->total_weight = 1.0; @@ -1170,10 +1184,10 @@ rspamd_symbols_cache_validate_cb (gpointer k, gpointer v, gpointer ud) item->priority ++; } - if ((item->type & SYMBOL_TYPE_VIRTUAL) && - !(item->type & SYMBOL_TYPE_SQUEEZED) && item->parent != -1) { - g_assert (item->parent < (gint)cache->items_by_id->len); - parent = g_ptr_array_index (cache->items_by_id, item->parent); + if (item->is_virtual) { + g_assert (item->specific.virtual.parent < (gint)cache->filters->len); + parent = g_ptr_array_index (cache->filters, + item->specific.virtual.parent); if (fabs (parent->st->weight) < fabs (item->st->weight)) { parent->st->weight = item->st->weight; @@ -1241,7 +1255,6 @@ rspamd_symbols_cache_validate (struct symbols_cache *cache, if (sym_def && (sym_def->flags & RSPAMD_SYMBOL_FLAG_IGNORE)) { ignore_symbol = TRUE; - break; } if (!ignore_symbol) { @@ -1312,89 +1325,82 @@ rspamd_symbols_cache_check_symbol (struct rspamd_task *task, lua_State *L; gboolean check = TRUE; - if (item->func) { + g_assert (!item->is_virtual); - g_assert (item->func != NULL); - if (CHECK_START_BIT (checkpoint, item)) { - /* - * This can actually happen when deps span over different layers - */ + g_assert (item->specific.normal.func != NULL); + if (CHECK_START_BIT (checkpoint, item)) { + /* + * This can actually happen when deps span over different layers + */ + return CHECK_FINISH_BIT (checkpoint, item); + } - return CHECK_FINISH_BIT (checkpoint, item); - } - /* Check has been started */ - SET_START_BIT (checkpoint, item); + /* Check has been started */ + SET_START_BIT (checkpoint, item); - if (!item->enabled || - (RSPAMD_TASK_IS_EMPTY (task) && !(item->type & SYMBOL_TYPE_EMPTY))) { - check = FALSE; - } - else if (item->condition_cb != -1) { - /* We also executes condition callback to check if we need this symbol */ - L = task->cfg->lua_state; - lua_rawgeti (L, LUA_REGISTRYINDEX, item->condition_cb); - ptask = lua_newuserdata (L, sizeof (struct rspamd_task *)); - rspamd_lua_setclass (L, "rspamd{task}", -1); - *ptask = task; + if (!item->enabled || + (RSPAMD_TASK_IS_EMPTY (task) && !(item->type & SYMBOL_TYPE_EMPTY))) { + check = FALSE; + } + else if (item->specific.normal.condition_cb != -1) { + /* We also executes condition callback to check if we need this symbol */ + L = task->cfg->lua_state; + lua_rawgeti (L, LUA_REGISTRYINDEX, item->specific.normal.condition_cb); + ptask = lua_newuserdata (L, sizeof (struct rspamd_task *)); + rspamd_lua_setclass (L, "rspamd{task}", -1); + *ptask = task; - if (lua_pcall (L, 1, 1, 0) != 0) { - msg_info_task ("call to condition for %s failed: %s", - item->symbol, lua_tostring (L, -1)); - lua_pop (L, 1); - } - else { - check = lua_toboolean (L, -1); - lua_pop (L, 1); - } + if (lua_pcall (L, 1, 1, 0) != 0) { + msg_info_task ("call to condition for %s failed: %s", + item->symbol, lua_tostring (L, -1)); + lua_pop (L, 1); + } + else { + check = lua_toboolean (L, -1); + lua_pop (L, 1); } + } - if (check) { - msg_debug_cache_task ("execute %s, %d", item->symbol, item->id); + if (check) { + msg_debug_cache_task ("execute %s, %d", item->symbol, item->id); #ifdef HAVE_EVENT_NO_CACHE_TIME_FUNC - struct timeval tv; + struct timeval tv; - event_base_update_cache_time (task->ev_base); - event_base_gettimeofday_cached (task->ev_base, &tv); - t1 = tv_to_double (&tv); + event_base_update_cache_time (task->ev_base); + event_base_gettimeofday_cached (task->ev_base, &tv); + t1 = tv_to_double (&tv); #else - t1 = rspamd_get_ticks (FALSE); + t1 = rspamd_get_ticks (FALSE); #endif - item->start_ticks = t1; - item->async_events = 0; - g_assert (checkpoint->cur_item == NULL); - checkpoint->cur_item = item; - checkpoint->items_inflight ++; - /* Callback now must finalize itself */ - item->func (task, item, item->user_data); - checkpoint->cur_item = NULL; + item->start_ticks = t1; + item->async_events = 0; + g_assert (checkpoint->cur_item == NULL); + checkpoint->cur_item = item; + checkpoint->items_inflight ++; + /* Callback now must finalize itself */ + item->specific.normal.func (task, item, item->specific.normal.user_data); + checkpoint->cur_item = NULL; - if (checkpoint->items_inflight == 0) { - - return TRUE; - } - - if (item->async_events == 0 && !CHECK_FINISH_BIT (checkpoint, item)) { - msg_err_cache ("critical error: item %s has no async events pending, " - "but it is not finalised", item->symbol); - g_assert_not_reached (); - } + if (checkpoint->items_inflight == 0) { - return FALSE; + return TRUE; } - else { - msg_debug_cache_task ("skipping check of %s as its start condition is false", - item->symbol); - SET_FINISH_BIT (checkpoint, item); - return TRUE; + if (item->async_events == 0 && !CHECK_FINISH_BIT (checkpoint, item)) { + msg_err_cache ("critical error: item %s has no async events pending, " + "but it is not finalised", item->symbol); + g_assert_not_reached (); } + + return FALSE; } else { - SET_START_BIT (checkpoint, item); + msg_debug_cache_task ("skipping check of %s as its start condition is false", + item->symbol); SET_FINISH_BIT (checkpoint, item); - - return TRUE; } + + return TRUE; } static gboolean @@ -1488,13 +1494,14 @@ rspamd_symbols_cache_check_deps (struct rspamd_task *task, return ret; } -static void -rspamd_symbols_cache_continuation (void *data) -{ - struct rspamd_task *task = data; - - rspamd_task_process (task, RSPAMD_TASK_PROCESS_ALL); -} +#define BITS_PER_UINT64 (NBBY * sizeof (guint64)) +#define UINT64_BITMAP_SIZE(nbits) (((nbits) + BITS_PER_UINT64 - 1) / BITS_PER_UINT64) +#define ALLOC_BITMAP(bmap, nelts) do { \ + (bmap).started = rspamd_mempool_alloc0 (task->task_pool, \ + UINT64_BITMAP_SIZE (nelts) * sizeof (guint64)); \ + (bmap).finished = rspamd_mempool_alloc0 (task->task_pool, \ + UINT64_BITMAP_SIZE (nelts) * sizeof (guint64)); \ +} while (0) static struct cache_savepoint * rspamd_symbols_cache_make_checkpoint (struct rspamd_task *task, @@ -1513,17 +1520,21 @@ rspamd_symbols_cache_make_checkpoint (struct rspamd_task *task, } checkpoint = rspamd_mempool_alloc0 (task->task_pool, sizeof (*checkpoint)); - checkpoint->started_bits = rspamd_mempool_alloc0 (task->task_pool, - NBYTES (cache->used_items)); - checkpoint->finished_bits = rspamd_mempool_alloc0 (task->task_pool, - NBYTES (cache->used_items)); + + ALLOC_BITMAP (checkpoint->prefilters, cache->prefilters->len); + ALLOC_BITMAP (checkpoint->filters, cache->filters->len); + ALLOC_BITMAP (checkpoint->postfilters, cache->postfilters->len); + ALLOC_BITMAP (checkpoint->idempotent, cache->idempotent->len); + g_assert (cache->items_by_order != NULL); checkpoint->version = cache->items_by_order->d->len; checkpoint->order = cache->items_by_order; REF_RETAIN (checkpoint->order); rspamd_mempool_add_destructor (task->task_pool, rspamd_symbols_cache_order_unref, checkpoint->order); + checkpoint->pass = RSPAMD_CACHE_PASS_INIT; + checkpoint->cur_bits = &checkpoint->prefilters; task->checkpoint = checkpoint; task->result = task->result; @@ -1666,6 +1677,7 @@ rspamd_symbols_cache_process_symbols (struct rspamd_task * task, /* Check for prefilters */ saved_priority = G_MININT; all_done = TRUE; + checkpoint->cur_bits = &checkpoint->prefilters; for (i = 0; i < (gint)cache->prefilters->len; i ++) { item = g_ptr_array_index (cache->prefilters, i); @@ -1716,6 +1728,7 @@ rspamd_symbols_cache_process_symbols (struct rspamd_task * task, * we just save it for another pass */ all_done = TRUE; + checkpoint->cur_bits = &checkpoint->filters; for (i = 0; i < (gint)checkpoint->version; i ++) { if (RSPAMD_TASK_IS_SKIPPED (task)) { @@ -1772,6 +1785,7 @@ rspamd_symbols_cache_process_symbols (struct rspamd_task * task, /* Check for postfilters */ saved_priority = G_MININT; all_done = TRUE; + checkpoint->cur_bits = &checkpoint->postfilters; for (i = 0; i < (gint)cache->postfilters->len; i ++) { if (RSPAMD_TASK_IS_SKIPPED (task)) { @@ -1824,6 +1838,7 @@ rspamd_symbols_cache_process_symbols (struct rspamd_task * task, case RSPAMD_CACHE_PASS_IDEMPOTENT: /* Check for postfilters */ saved_priority = G_MININT; + checkpoint->cur_bits = &checkpoint->idempotent; for (i = 0; i < (gint)cache->idempotent->len; i ++) { item = g_ptr_array_index (cache->idempotent, i); @@ -1855,6 +1870,7 @@ rspamd_symbols_cache_process_symbols (struct rspamd_task * task, case RSPAMD_CACHE_PASS_WAIT_IDEMPOTENT: all_done = TRUE; + checkpoint->cur_bits = &checkpoint->idempotent; for (i = 0; i < (gint)cache->idempotent->len; i ++) { item = g_ptr_array_index (cache->idempotent, i); @@ -1888,54 +1904,51 @@ struct counters_cbdata { #define ROUND_DOUBLE(x) (floor((x) * 100.0) / 100.0) static void -rspamd_symbols_cache_counters_cb (gpointer v, gpointer ud) +rspamd_symbols_cache_counters_cb (gpointer k, gpointer v, gpointer ud) { struct counters_cbdata *cbd = ud; ucl_object_t *obj, *top; struct rspamd_symcache_item *item = v, *parent; + const gchar *symbol = k; top = cbd->top; - if (!(item->type & SYMBOL_TYPE_CALLBACK)) { - obj = ucl_object_typed_new (UCL_OBJECT); - ucl_object_insert_key (obj, ucl_object_fromstring (item->symbol), - "symbol", 0, false); - - if ((item->type & SYMBOL_TYPE_VIRTUAL) && - !(item->type & SYMBOL_TYPE_SQUEEZED) && item->parent != -1) { - g_assert (item->parent < (gint)cbd->cache->items_by_id->len); - parent = g_ptr_array_index (cbd->cache->items_by_id, - item->parent); - ucl_object_insert_key (obj, - ucl_object_fromdouble (ROUND_DOUBLE (item->st->weight)), - "weight", 0, false); - ucl_object_insert_key (obj, - ucl_object_fromdouble (ROUND_DOUBLE (parent->st->avg_frequency)), - "frequency", 0, false); - ucl_object_insert_key (obj, - ucl_object_fromint (parent->st->total_hits), - "hits", 0, false); - ucl_object_insert_key (obj, - ucl_object_fromdouble (ROUND_DOUBLE (parent->st->avg_time)), - "time", 0, false); - } - else { - ucl_object_insert_key (obj, - ucl_object_fromdouble (ROUND_DOUBLE (item->st->weight)), - "weight", 0, false); - ucl_object_insert_key (obj, - ucl_object_fromdouble (ROUND_DOUBLE (item->st->avg_frequency)), - "frequency", 0, false); - ucl_object_insert_key (obj, - ucl_object_fromint (item->st->total_hits), - "hits", 0, false); - ucl_object_insert_key (obj, - ucl_object_fromdouble (ROUND_DOUBLE (item->st->avg_time)), - "time", 0, false); - } - - ucl_array_append (top, obj); + obj = ucl_object_typed_new (UCL_OBJECT); + ucl_object_insert_key (obj, ucl_object_fromstring (symbol ? symbol : "unknown"), + "symbol", 0, false); + + if (item->is_virtual) { + parent = g_ptr_array_index (cbd->cache->filters, + item->specific.virtual.parent); + ucl_object_insert_key (obj, + ucl_object_fromdouble (ROUND_DOUBLE (item->st->weight)), + "weight", 0, false); + ucl_object_insert_key (obj, + ucl_object_fromdouble (ROUND_DOUBLE (parent->st->avg_frequency)), + "frequency", 0, false); + ucl_object_insert_key (obj, + ucl_object_fromint (parent->st->total_hits), + "hits", 0, false); + ucl_object_insert_key (obj, + ucl_object_fromdouble (ROUND_DOUBLE (parent->st->avg_time)), + "time", 0, false); + } + else { + ucl_object_insert_key (obj, + ucl_object_fromdouble (ROUND_DOUBLE (item->st->weight)), + "weight", 0, false); + ucl_object_insert_key (obj, + ucl_object_fromdouble (ROUND_DOUBLE (item->st->avg_frequency)), + "frequency", 0, false); + ucl_object_insert_key (obj, + ucl_object_fromint (item->st->total_hits), + "hits", 0, false); + ucl_object_insert_key (obj, + ucl_object_fromdouble (ROUND_DOUBLE (item->st->avg_time)), + "time", 0, false); } + + ucl_array_append (top, obj); } #undef ROUND_DOUBLE @@ -1950,7 +1963,7 @@ rspamd_symbols_cache_counters (struct symbols_cache * cache) top = ucl_object_typed_new (UCL_ARRAY); cbd.top = top; cbd.cache = cache; - g_ptr_array_foreach (cache->items_by_id, + g_hash_table_foreach (cache->items_by_symbol, rspamd_symbols_cache_counters_cb, &cbd); return top; @@ -1990,7 +2003,7 @@ rspamd_symbols_cache_resort_cb (gint fd, short what, gpointer ud) gdouble tm; struct rspamd_cache_refresh_cbdata *cbdata = ud; struct symbols_cache *cache; - struct rspamd_symcache_item *item, *parent; + struct rspamd_symcache_item *item; guint i; gdouble cur_ticks; static const double decay_rate = 0.7; @@ -2006,10 +2019,10 @@ rspamd_symbols_cache_resort_cb (gint fd, short what, gpointer ud) double_to_tv (tm, &tv); event_add (&cbdata->resort_ev, &tv); - if (rspamd_worker_is_primary_controller (cbdata->w)) + if (rspamd_worker_is_primary_controller (cbdata->w)) { /* Gather stats from shared execution times */ - for (i = 0; i < cache->items_by_id->len; i ++) { - item = g_ptr_array_index (cache->items_by_id, i); + for (i = 0; i < cache->filters->len; i ++) { + item = g_ptr_array_index (cache->filters, i); item->st->total_hits += item->st->hits; g_atomic_int_set (&item->st->hits, 0); @@ -2018,7 +2031,7 @@ rspamd_symbols_cache_resort_cb (gint fd, short what, gpointer ud) gdouble cur_err, cur_value; cur_value = (item->st->total_hits - item->last_count) / - (cur_ticks - cbdata->last_resort); + (cur_ticks - cbdata->last_resort); rspamd_set_counter_ema (&item->st->frequency_counter, cur_value, decay_rate); item->st->avg_frequency = item->st->frequency_counter.mean; @@ -2036,15 +2049,15 @@ rspamd_symbols_cache_resort_cb (gint fd, short what, gpointer ud) * TODO: replace magic number */ if (item->st->frequency_counter.number > 10 && - cur_err > sqrt (item->st->stddev_frequency) * 3) { + cur_err > sqrt (item->st->stddev_frequency) * 3) { item->frequency_peaks ++; msg_debug_cache ("peak found for %s is %.2f, avg: %.2f, " - "stddev: %.2f, error: %.2f, peaks: %d", - item->symbol, cur_value, - item->st->avg_frequency, - item->st->stddev_frequency, - cur_err, - item->frequency_peaks); + "stddev: %.2f, error: %.2f, peaks: %d", + item->symbol, cur_value, + item->st->avg_frequency, + item->st->stddev_frequency, + cur_err, + item->frequency_peaks); if (cache->peak_cb != -1) { rspamd_symbols_cache_call_peak_cb (cbdata->ev_base, @@ -2067,21 +2080,10 @@ rspamd_symbols_cache_resort_cb (gint fd, short what, gpointer ud) } } - /* Sync virtual symbols */ - for (i = 0; i < cache->items_by_id->len; i ++) { - item = g_ptr_array_index (cache->items_by_id, i); - - if (item->parent != -1) { - parent = g_ptr_array_index (cache->items_by_id, item->parent); - if (parent) { - item->st->avg_time = parent->st->avg_time; - } - } + cbdata->last_resort = cur_ticks; + /* We don't do actual sorting due to topological guarantees */ } - - cbdata->last_resort = cur_ticks; - /* We don't do actual sorting due to topological guarantees */ } void @@ -2132,9 +2134,9 @@ rspamd_symbols_cache_add_dependency (struct symbols_cache *cache, struct rspamd_symcache_item *source; struct cache_dependency *dep; - g_assert (id_from < (gint)cache->items_by_id->len); + g_assert (id_from >= 0 && id_from < (gint)cache->filters->len); - source = g_ptr_array_index (cache->items_by_id, id_from); + source = g_ptr_array_index (cache->filters, id_from); dep = rspamd_mempool_alloc (cache->static_pool, sizeof (*dep)); dep->id = id_from; dep->sym = rspamd_mempool_strdup (cache->static_pool, to); @@ -2210,8 +2212,8 @@ rspamd_symbols_cache_stat_symbol (struct symbols_cache *cache, } static gint -rspamd_symbols_cache_find_symbol_parent (struct symbols_cache *cache, - const gchar *name) +rspamd_symbols_cache_find_filter (struct symbols_cache *cache, + const gchar *name) { struct rspamd_symcache_item *item; @@ -2224,12 +2226,11 @@ rspamd_symbols_cache_find_symbol_parent (struct symbols_cache *cache, item = g_hash_table_lookup (cache->items_by_symbol, name); if (item != NULL) { - - while (item != NULL && item->parent != -1) { - item = g_ptr_array_index (cache->items_by_id, item->parent); + if (!item->is_filter) { + return -1; } - return item ? item->id : -1; + return item->id; } return -1; @@ -2243,11 +2244,11 @@ rspamd_symbols_cache_symbol_by_id (struct symbols_cache *cache, g_assert (cache != NULL); - if (id < 0 || id >= (gint)cache->items_by_id->len) { + if (id < 0 || id >= (gint)cache->filters->len) { return NULL; } - item = g_ptr_array_index (cache->items_by_id, id); + item = g_ptr_array_index (cache->filters, id); return item->symbol; } @@ -2260,6 +2261,11 @@ rspamd_symbols_cache_stats_symbols_count (struct symbols_cache *cache) return cache->stats_symbols_count; } +#define DISABLE_BITS(what) do { \ + memset (checkpoint->what.started, 0xff, NBYTES (cache->what->len)); \ + memset (checkpoint->what.finished, 0xff, NBYTES (cache->what->len)); \ +} while(0) + static void rspamd_symbols_cache_disable_all_symbols (struct rspamd_task *task, struct symbols_cache *cache) @@ -2275,10 +2281,47 @@ rspamd_symbols_cache_disable_all_symbols (struct rspamd_task *task, } /* Set all symbols as started + finished to disable their execution */ - memset (checkpoint->started_bits, 0xff, - NBYTES (cache->used_items)); - memset (checkpoint->finished_bits, 0xff, - NBYTES (cache->used_items)); + DISABLE_BITS(prefilters); + DISABLE_BITS(filters); + DISABLE_BITS(postfilters); + DISABLE_BITS(idempotent); +} + +#undef DISABLE_BITS + +static struct rspamd_symcache_item * +rspamd_symbols_cache_get_item_and_bits (struct rspamd_task *task, + struct symbols_cache *cache, + struct cache_savepoint *checkpoint, + const gchar *symbol, + struct cache_bits **bits) +{ + struct rspamd_symcache_item *item; + + item = g_hash_table_lookup (cache->items_by_symbol, symbol); + + if (item) { + if (item->is_virtual) { + item = g_ptr_array_index (cache->filters, item->specific.virtual.parent); + *bits = &checkpoint->filters; + } + else { + if (item->type & SYMBOL_TYPE_PREFILTER) { + *bits = &checkpoint->prefilters; + } + else if (item->type & SYMBOL_TYPE_POSTFILTER) { + *bits = &checkpoint->postfilters; + } + else if (item->type & SYMBOL_TYPE_IDEMPOTENT) { + *bits = &checkpoint->idempotent; + } + else { + *bits = &checkpoint->filters; + } + } + } + + return item; } static void @@ -2287,7 +2330,7 @@ rspamd_symbols_cache_disable_symbol_checkpoint (struct rspamd_task *task, { struct cache_savepoint *checkpoint; struct rspamd_symcache_item *item; - gint id; + struct cache_bits *bits = NULL; if (task->checkpoint == NULL) { checkpoint = rspamd_symbols_cache_make_checkpoint (task, cache); @@ -2297,20 +2340,18 @@ rspamd_symbols_cache_disable_symbol_checkpoint (struct rspamd_task *task, checkpoint = task->checkpoint; } - id = rspamd_symbols_cache_find_symbol_parent (cache, symbol); + item = rspamd_symbols_cache_get_item_and_bits (task, cache, checkpoint, + symbol, &bits); - if (id >= 0) { - /* Set executed and finished flags */ - item = g_ptr_array_index (cache->items_by_id, id); + if (item) { if (!(item->type & SYMBOL_TYPE_SQUEEZED)) { - SET_START_BIT (checkpoint, item); - SET_FINISH_BIT (checkpoint, item); - + setbit (bits->started, item->id); + setbit (bits->finished, item->id); msg_debug_cache_task ("disable execution of %s", symbol); } else { - msg_debug_cache_task ("skip squeezed symbol %s", symbol); + msg_debug_cache_task ("skip disabling squeezed symbol %s", symbol); } } else { @@ -2324,7 +2365,7 @@ rspamd_symbols_cache_enable_symbol_checkpoint (struct rspamd_task *task, { struct cache_savepoint *checkpoint; struct rspamd_symcache_item *item; - gint id; + struct cache_bits *bits = NULL; if (task->checkpoint == NULL) { checkpoint = rspamd_symbols_cache_make_checkpoint (task, cache); @@ -2334,16 +2375,19 @@ rspamd_symbols_cache_enable_symbol_checkpoint (struct rspamd_task *task, checkpoint = task->checkpoint; } - id = rspamd_symbols_cache_find_symbol_parent (cache, symbol); + item = rspamd_symbols_cache_get_item_and_bits (task, cache, checkpoint, + symbol, &bits); - if (id >= 0) { - /* Set executed and finished flags */ - item = g_ptr_array_index (cache->items_by_id, id); - - clrbit (checkpoint->started_bits, item->id); - clrbit (checkpoint->finished_bits, item->id); + if (item) { - msg_debug_cache_task ("enable execution of %s (%d)", symbol, id); + if (!(item->type & SYMBOL_TYPE_SQUEEZED)) { + clrbit (bits->started, item->id); + clrbit (bits->finished, item->id); + msg_debug_cache_task ("enable execution of %s", symbol); + } + else { + msg_debug_cache_task ("skip enabling of squeezed symbol %s", symbol); + } } else { msg_info_task ("cannot enable %s: not found", symbol); @@ -2354,65 +2398,49 @@ struct rspamd_abstract_callback_data* rspamd_symbols_cache_get_cbdata (struct symbols_cache *cache, const gchar *symbol) { - gint id; struct rspamd_symcache_item *item; g_assert (cache != NULL); g_assert (symbol != NULL); - id = rspamd_symbols_cache_find_symbol_parent (cache, symbol); - - if (id < 0) { - return NULL; - } - - item = g_ptr_array_index (cache->items_by_id, id); - - return item->user_data; -} - -gboolean -rspamd_symbols_cache_set_cbdata (struct symbols_cache *cache, - const gchar *symbol, struct rspamd_abstract_callback_data *cbdata) -{ - gint id; - struct rspamd_symcache_item *item; + item = g_hash_table_lookup (cache->items_by_symbol, symbol); - g_assert (cache != NULL); - g_assert (symbol != NULL); + if (item) { - id = rspamd_symbols_cache_find_symbol_parent (cache, symbol); + if (item->is_virtual) { + item = g_ptr_array_index (cache->filters, item->specific.virtual.parent); + } - if (id < 0) { - return FALSE; + return item->specific.normal.user_data; } - item = g_ptr_array_index (cache->items_by_id, id); - item->user_data = cbdata; - - return TRUE; + return NULL; } gboolean rspamd_symbols_cache_is_checked (struct rspamd_task *task, struct symbols_cache *cache, const gchar *symbol) { - gint id; struct cache_savepoint *checkpoint; + struct rspamd_symcache_item *item; + struct cache_bits *bits = NULL; g_assert (cache != NULL); g_assert (symbol != NULL); - id = rspamd_symbols_cache_find_symbol_parent (cache, symbol); - - if (id < 0) { - return FALSE; + if (task->checkpoint == NULL) { + checkpoint = rspamd_symbols_cache_make_checkpoint (task, cache); + task->checkpoint = checkpoint; + } + else { + checkpoint = task->checkpoint; } - checkpoint = task->checkpoint; + item = rspamd_symbols_cache_get_item_and_bits (task, cache, checkpoint, + symbol, &bits); - if (checkpoint) { - return isset (checkpoint->started_bits, id); + if (item) { + return isset (bits->started, item->id); } return FALSE; @@ -2422,16 +2450,14 @@ void rspamd_symbols_cache_disable_symbol (struct symbols_cache *cache, const gchar *symbol) { - gint id; struct rspamd_symcache_item *item; g_assert (cache != NULL); g_assert (symbol != NULL); - id = rspamd_symbols_cache_find_symbol_parent (cache, symbol); + item = g_hash_table_lookup (cache->items_by_symbol, symbol); - if (id >= 0) { - item = g_ptr_array_index (cache->items_by_id, id); + if (item) { item->enabled = FALSE; } } @@ -2440,16 +2466,14 @@ void rspamd_symbols_cache_enable_symbol (struct symbols_cache *cache, const gchar *symbol) { - gint id; struct rspamd_symcache_item *item; g_assert (cache != NULL); g_assert (symbol != NULL); - id = rspamd_symbols_cache_find_symbol_parent (cache, symbol); + item = g_hash_table_lookup (cache->items_by_symbol, symbol); - if (id >= 0) { - item = g_ptr_array_index (cache->items_by_id, id); + if (item) { item->enabled = TRUE; } } @@ -2467,46 +2491,46 @@ gboolean rspamd_symbols_cache_is_symbol_enabled (struct rspamd_task *task, struct symbols_cache *cache, const gchar *symbol) { - gint id; struct cache_savepoint *checkpoint; struct rspamd_symcache_item *item; lua_State *L; struct rspamd_task **ptask; + struct cache_bits *bits = NULL; gboolean ret = TRUE; g_assert (cache != NULL); g_assert (symbol != NULL); - id = rspamd_symbols_cache_find_symbol_parent (cache, symbol); - - if (id < 0) { - return FALSE; - } - checkpoint = task->checkpoint; - item = g_ptr_array_index (cache->items_by_id, id); + if (checkpoint) { - if (CHECK_START_BIT (checkpoint, item)) { - ret = FALSE; - } - else { - if (item->condition_cb != -1) { - /* We also executes condition callback to check if we need this symbol */ - L = task->cfg->lua_state; - lua_rawgeti (L, LUA_REGISTRYINDEX, item->condition_cb); - ptask = lua_newuserdata (L, sizeof (struct rspamd_task *)); - rspamd_lua_setclass (L, "rspamd{task}", -1); - *ptask = task; - - if (lua_pcall (L, 1, 1, 0) != 0) { - msg_info_task ("call to condition for %s failed: %s", - item->symbol, lua_tostring (L, -1)); - lua_pop (L, 1); - } - else { - ret = lua_toboolean (L, -1); - lua_pop (L, 1); + item = rspamd_symbols_cache_get_item_and_bits (task, cache, checkpoint, + symbol, &bits); + + if (item) { + if (CHECK_START_BIT (checkpoint, item)) { + ret = FALSE; + } + else { + if (item->specific.normal.condition_cb != -1) { + /* We also executes condition callback to check if we need this symbol */ + L = task->cfg->lua_state; + lua_rawgeti (L, LUA_REGISTRYINDEX, + item->specific.normal.condition_cb); + ptask = lua_newuserdata (L, sizeof (struct rspamd_task *)); + rspamd_lua_setclass (L, "rspamd{task}", -1); + *ptask = task; + + if (lua_pcall (L, 1, 1, 0) != 0) { + msg_info_task ("call to condition for %s failed: %s", + item->symbol, lua_tostring (L, -1)); + lua_pop (L, 1); + } + else { + ret = lua_toboolean (L, -1); + lua_pop (L, 1); + } } } } @@ -2520,10 +2544,14 @@ rspamd_symbols_cache_foreach (struct symbols_cache *cache, void (*func)(gint , const gchar *, gint , gpointer ), gpointer ud) { - guint i; struct rspamd_symcache_item *item; + GHashTableIter it; + gpointer k, v; - PTR_ARRAY_FOREACH (cache->items_by_id, i, item) { + g_hash_table_iter_init (&it, cache->items_by_symbol); + + while (g_hash_table_iter_next (&it, &k, &v)) { + item = (struct rspamd_symcache_item *)v; func (item->id, item->symbol, item->type, ud); } } @@ -2570,7 +2598,7 @@ rspamd_symbols_cache_finalize_item (struct rspamd_task *task, { struct cache_savepoint *checkpoint = task->checkpoint; struct cache_dependency *rdep; - gdouble total_ticks = 0, t2, diff; + gdouble t2, diff; guint i; struct timeval tv; const gdouble slow_diff_limit = 0.1; diff --git a/src/libserver/symbols_cache.h b/src/libserver/symbols_cache.h index 5845840ab..4dce60b46 100644 --- a/src/libserver/symbols_cache.h +++ b/src/libserver/symbols_cache.h @@ -100,17 +100,6 @@ gint rspamd_symbols_cache_add_symbol (struct symbols_cache *cache, gint parent); /** - * Add condition to the specific symbol in cache - * @param cache - * @param id id of symbol - * @param L lua state pointer - * @param cbref callback reference (returned by luaL_ref) - * @return TRUE if condition has been added - */ -gboolean rspamd_symbols_cache_add_condition (struct symbols_cache *cache, - gint id, lua_State *L, gint cbref); - -/** * Add callback to be executed whenever symbol has peak value * @param cache * @param cbref @@ -251,15 +240,6 @@ void rspamd_symbols_cache_enable_symbol (struct symbols_cache *cache, struct rspamd_abstract_callback_data* rspamd_symbols_cache_get_cbdata ( struct symbols_cache *cache, const gchar *symbol); -/** - * Sets new callback data for a symbol in cache - * @param cache - * @param symbol - * @param cbdata - * @return - */ -gboolean rspamd_symbols_cache_set_cbdata (struct symbols_cache *cache, - const gchar *symbol, struct rspamd_abstract_callback_data *cbdata); /** * Process settings for task diff --git a/src/lua/lua_config.c b/src/lua/lua_config.c index 404251592..69f50acff 100644 --- a/src/lua/lua_config.c +++ b/src/lua/lua_config.c @@ -2379,7 +2379,9 @@ lua_config_newindex (lua_State *L) /* Here we pop function from the stack, so no lua_pop is required */ condref = luaL_ref (L, LUA_REGISTRYINDEX); - rspamd_symbols_cache_add_condition (cfg->cache, id, L, condref); + g_assert (name != NULL); + rspamd_symbols_cache_add_condition_delayed (cfg->cache, + name, L, condref); } else { lua_pop (L, 1); diff --git a/src/plugins/regexp.c b/src/plugins/regexp.c index c08568839..0f7bb4ff8 100644 --- a/src/plugins/regexp.c +++ b/src/plugins/regexp.c @@ -257,8 +257,10 @@ regexp_module_config (struct rspamd_config *cfg) if (elt != NULL && ucl_object_type (elt) == UCL_USERDATA) { struct ucl_lua_funcdata *conddata; + g_assert (cur_item->symbol != NULL); conddata = ucl_object_toclosure (elt); - rspamd_symbols_cache_add_condition (cfg->cache, id, + rspamd_symbols_cache_add_condition_delayed (cfg->cache, + cur_item->symbol, conddata->L, conddata->idx); } |