From: Vsevolod Stakhov Date: Mon, 7 Jul 2025 14:45:43 +0000 (+0100) Subject: [Minor] Use more efficient approach for iterations X-Git-Tag: 3.13.0~47^2~6 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c491e3e056eb6810ce9234b0cc4f4bea0c1f81fc;p=thirdparty%2Frspamd.git [Minor] Use more efficient approach for iterations --- diff --git a/src/hs_helper.c b/src/hs_helper.c index c5a42ad12a..f3edbd64bb 100644 --- a/src/hs_helper.c +++ b/src/hs_helper.c @@ -449,11 +449,24 @@ rspamd_rs_compile(struct hs_helper_ctx *ctx, struct rspamd_worker *worker, return TRUE; } - /* Get all scope names */ - char **scope_names = rspamd_re_cache_get_scope_names(ctx->cfg->re_cache); + /* Count scopes and prepare compilation data */ + struct rspamd_re_cache *scope; + unsigned int total_scopes = 0; + + /* Count valid scopes first */ + for (scope = rspamd_re_cache_scope_first(ctx->cfg->re_cache); + scope != NULL; + scope = rspamd_re_cache_scope_next(scope)) { + const char *scope_name = rspamd_re_cache_scope_name(scope); + const char *scope_for_check = (strcmp(scope_name, "default") == 0) ? NULL : scope_name; + + if (rspamd_re_cache_is_loaded(ctx->cfg->re_cache, scope_for_check)) { + total_scopes++; + } + } - if (!scope_names) { - /* Failed to get scope names, use standard compilation for default scope */ + if (total_scopes == 0) { + /* No loaded scopes, use standard compilation for default scope */ struct rspamd_hs_helper_single_compile_cbdata *single_cbd = g_malloc0(sizeof(*single_cbd)); single_cbd->worker = worker; @@ -474,41 +487,28 @@ rspamd_rs_compile(struct hs_helper_ctx *ctx, struct rspamd_worker *worker, compile_cbd->worker = worker; compile_cbd->ctx = ctx; compile_cbd->total_compiled = 0; - compile_cbd->scopes_remaining = g_strv_length(scope_names); + compile_cbd->scopes_remaining = total_scopes; compile_cbd->forced = forced; compile_cbd->workers_ready = ctx->workers_ready; - /* Compile each scope */ - for (const char **cur_scope = scope_names; *cur_scope; cur_scope++) { - const char *scope = strcmp(*cur_scope, "default") == 0 ? NULL : *cur_scope; - struct rspamd_re_cache *scope_cache = rspamd_re_cache_find_scope(ctx->cfg->re_cache, scope); + /* Compile each loaded scope */ + for (scope = rspamd_re_cache_scope_first(ctx->cfg->re_cache); + scope != NULL; + scope = rspamd_re_cache_scope_next(scope)) { + const char *scope_name = rspamd_re_cache_scope_name(scope); + const char *scope_for_compile = (strcmp(scope_name, "default") == 0) ? NULL : scope_name; - if (scope_cache && rspamd_re_cache_is_loaded(ctx->cfg->re_cache, scope)) { - rspamd_re_cache_compile_hyperscan_scoped_single(scope_cache, scope, + if (rspamd_re_cache_is_loaded(ctx->cfg->re_cache, scope_for_compile)) { + rspamd_re_cache_compile_hyperscan_scoped_single(scope, scope_for_compile, ctx->hs_dir, ctx->max_time, !forced, ctx->event_loop, rspamd_rs_compile_scoped_cb, compile_cbd); } else { - /* Scope not loaded, skip it */ - compile_cbd->scopes_remaining--; - msg_debug("skipping unloaded scope: %s", scope ? scope : "default"); - - /* Check if we're done */ - if (compile_cbd->scopes_remaining == 0) { - /* No scopes to compile, send final notification immediately */ - if (compile_cbd->workers_ready) { - rspamd_rs_send_final_notification(compile_cbd); - } - else { - ctx->loaded = TRUE; - } - } + msg_debug("skipping unloaded scope: %s", scope_name); } } - - g_strfreev(scope_names); return TRUE; } diff --git a/src/libserver/maps/map.c b/src/libserver/maps/map.c index 8ebf55317b..6de694eb3c 100644 --- a/src/libserver/maps/map.c +++ b/src/libserver/maps/map.c @@ -3376,35 +3376,28 @@ void rspamd_map_trigger_hyperscan_compilation(struct rspamd_map *map) return; } - /* Get scope names and compile those that are loaded */ - char **scope_names = rspamd_re_cache_get_scope_names(map->cfg->re_cache), - **cur_scope; - - if (scope_names) { - for (cur_scope = scope_names; *cur_scope; cur_scope++) { - const char *scope = strcmp(*cur_scope, "default") == 0 ? NULL : *cur_scope; - - /* Only compile loaded scopes */ - if (rspamd_re_cache_is_loaded(map->cfg->re_cache, scope)) { - struct rspamd_re_cache *scope_cache = rspamd_re_cache_find_scope(map->cfg->re_cache, scope); - - if (scope_cache) { - msg_info_map("triggering hyperscan compilation for scope: %s after map update", - scope ? scope : "default"); - - /* Use default settings for compilation */ - rspamd_re_cache_compile_hyperscan_scoped_single(scope_cache, scope, - map->cfg->hs_cache_dir ? map->cfg->hs_cache_dir : RSPAMD_DBDIR "/", - 1.0, /* max_time */ - FALSE, /* silent */ - worker->ctx ? ((struct rspamd_abstract_worker_ctx *) worker->ctx)->event_loop : NULL, - NULL, /* callback */ - NULL); /* cbdata */ - } - } + /* Iterate through scopes and compile those that are loaded */ + struct rspamd_re_cache *scope; + + for (scope = rspamd_re_cache_scope_first(map->cfg->re_cache); + scope != NULL; + scope = rspamd_re_cache_scope_next(scope)) { + const char *scope_name = rspamd_re_cache_scope_name(scope); + const char *scope_for_check = (strcmp(scope_name, "default") == 0) ? NULL : scope_name; + + /* Only compile loaded scopes */ + if (rspamd_re_cache_is_loaded(map->cfg->re_cache, scope_for_check)) { + msg_info_map("triggering hyperscan compilation for scope: %s after map update", + scope_name); + + /* Use default settings for compilation */ + rspamd_re_cache_compile_hyperscan_scoped_single(scope, scope_for_check, + map->cfg->hs_cache_dir ? map->cfg->hs_cache_dir : RSPAMD_DBDIR "/", + 1.0, /* max_time */ + FALSE, /* silent */ + worker->ctx ? ((struct rspamd_abstract_worker_ctx *) worker->ctx)->event_loop : NULL, + NULL, /* callback */ + NULL); /* cbdata */ } - - /* Clean up scope names */ - g_strfreev(scope_names); } } diff --git a/src/libserver/re_cache.c b/src/libserver/re_cache.c index 22b9b3b59f..5313e157a0 100644 --- a/src/libserver/re_cache.c +++ b/src/libserver/re_cache.c @@ -3204,6 +3204,53 @@ unsigned int rspamd_re_cache_count_scopes(struct rspamd_re_cache *cache_head) return count; } +struct rspamd_re_cache *rspamd_re_cache_scope_first(struct rspamd_re_cache *cache_head) +{ + return cache_head; +} + +struct rspamd_re_cache *rspamd_re_cache_scope_next(struct rspamd_re_cache *current) +{ + return current ? current->next : NULL; +} + +const char *rspamd_re_cache_scope_name(struct rspamd_re_cache *scope) +{ + if (!scope) { + return "unknown"; + } + + return scope->scope ? scope->scope : "default"; +} + +void rspamd_re_cache_scope_set_flags(struct rspamd_re_cache *scope, unsigned int flags) +{ + if (scope) { + scope->flags |= flags; + } +} + +void rspamd_re_cache_scope_clear_flags(struct rspamd_re_cache *scope, unsigned int flags) +{ + if (scope) { + scope->flags &= ~flags; + } +} + +unsigned int rspamd_re_cache_scope_get_flags(struct rspamd_re_cache *scope) +{ + return scope ? scope->flags : 0; +} + +gboolean rspamd_re_cache_scope_is_loaded(struct rspamd_re_cache *scope) +{ + if (!scope) { + return FALSE; + } + + return (scope->flags & RSPAMD_RE_CACHE_FLAG_LOADED) != 0; +} + void rspamd_re_cache_set_flags(struct rspamd_re_cache *cache_head, const char *scope, unsigned int flags) { struct rspamd_re_cache *target; @@ -3254,43 +3301,6 @@ gboolean rspamd_re_cache_is_loaded(struct rspamd_re_cache *cache_head, const cha return (flags & RSPAMD_RE_CACHE_FLAG_LOADED) != 0; } -char **rspamd_re_cache_get_scope_names(struct rspamd_re_cache *cache_head) -{ - struct rspamd_re_cache *cur; - char **names = NULL; - unsigned int i = 0, count = 0; - - if (!cache_head) { - return NULL; - } - - /* First count scopes */ - DL_COUNT(cache_head, cur, count); - - if (count == 0) { - return NULL; - } - - /* Allocate array with extra slot for NULL terminator */ - names = g_malloc(sizeof(char *) * (count + 1)); - - /* Fill array */ - DL_FOREACH(cache_head, cur) - { - if (cur->scope) { - names[i] = g_strdup(cur->scope); - } - else { - names[i] = g_strdup("default"); - } - i++; - } - - /* NULL terminate the array for g_strfreev compatibility */ - names[count] = NULL; - - return names; -} static gboolean rspamd_re_cache_create_scope_lock(const char *cache_dir, const char *scope, int *lock_fd) diff --git a/src/libserver/re_cache.h b/src/libserver/re_cache.h index 5ae9ecdb72..c5c8627d89 100644 --- a/src/libserver/re_cache.h +++ b/src/libserver/re_cache.h @@ -308,20 +308,69 @@ struct rspamd_re_cache *rspamd_re_cache_find_scope(struct rspamd_re_cache *cache */ gboolean rspamd_re_cache_remove_scope(struct rspamd_re_cache **cache_head, const char *scope); +/** + * Get array of scope names from the cache list + * @param cache_head head of cache list + * @return NULL-terminated array of scope names (must be freed with g_strfreev), or NULL if no scopes + */ +char **rspamd_re_cache_get_scope_names(struct rspamd_re_cache *cache_head); + /** * Count the number of scopes in the cache list */ unsigned int rspamd_re_cache_count_scopes(struct rspamd_re_cache *cache_head); /** - * Get array of scope names from the cache list + * Get the first scope in the cache list for iteration * @param cache_head head of cache list - * @return NULL-terminated array of scope names (must be freed with g_strfreev), or NULL if no scopes + * @return first scope, or NULL if no scopes */ -char **rspamd_re_cache_get_scope_names(struct rspamd_re_cache *cache_head); +struct rspamd_re_cache *rspamd_re_cache_scope_first(struct rspamd_re_cache *cache_head); + +/** + * Get the next scope in iteration + * @param current current scope + * @return next scope, or NULL if at end + */ +struct rspamd_re_cache *rspamd_re_cache_scope_next(struct rspamd_re_cache *current); + +/** + * Get the scope name (for display/logging purposes) + * @param scope the scope + * @return scope name ("default" for NULL scope name), never returns NULL + */ +const char *rspamd_re_cache_scope_name(struct rspamd_re_cache *scope); + +/** + * Set flags on a scope (efficient version that works directly on scope object) + * @param scope the scope object (from iterator) + * @param flags flags to set + */ +void rspamd_re_cache_scope_set_flags(struct rspamd_re_cache *scope, unsigned int flags); + +/** + * Clear flags on a scope (efficient version that works directly on scope object) + * @param scope the scope object (from iterator) + * @param flags flags to clear + */ +void rspamd_re_cache_scope_clear_flags(struct rspamd_re_cache *scope, unsigned int flags); + +/** + * Get flags from a scope (efficient version that works directly on scope object) + * @param scope the scope object (from iterator) + * @return flags value + */ +unsigned int rspamd_re_cache_scope_get_flags(struct rspamd_re_cache *scope); + +/** + * Check if a scope is loaded (efficient version that works directly on scope object) + * @param scope the scope object (from iterator) + * @return TRUE if scope is loaded + */ +gboolean rspamd_re_cache_scope_is_loaded(struct rspamd_re_cache *scope); /** - * Set flags for a specific scope + * Set flags for a specific scope (legacy function - less efficient, searches by name) * @param cache_head head of cache list * @param scope scope name (NULL for default scope) * @param flags flags to set @@ -329,7 +378,7 @@ char **rspamd_re_cache_get_scope_names(struct rspamd_re_cache *cache_head); void rspamd_re_cache_set_flags(struct rspamd_re_cache *cache_head, const char *scope, unsigned int flags); /** - * Clear flags for a specific scope + * Clear flags for a specific scope (legacy function - less efficient, searches by name) * @param cache_head head of cache list * @param scope scope name (NULL for default scope) * @param flags flags to clear @@ -337,7 +386,7 @@ void rspamd_re_cache_set_flags(struct rspamd_re_cache *cache_head, const char *s void rspamd_re_cache_clear_flags(struct rspamd_re_cache *cache_head, const char *scope, unsigned int flags); /** - * Get flags for a specific scope + * Get flags for a specific scope (legacy function - less efficient, searches by name) * @param cache_head head of cache list * @param scope scope name (NULL for default scope) * @return flags value @@ -345,7 +394,7 @@ void rspamd_re_cache_clear_flags(struct rspamd_re_cache *cache_head, const char unsigned int rspamd_re_cache_get_flags(struct rspamd_re_cache *cache_head, const char *scope); /** - * Check if a scope is loaded + * Check if a scope is loaded (legacy function - less efficient, searches by name) * @param cache_head head of cache list * @param scope scope name (NULL for default scope) * @return TRUE if scope is loaded and ready for use diff --git a/src/lua/lua_config.c b/src/lua/lua_config.c index 0fe98b2edb..5416eae3cf 100644 --- a/src/lua/lua_config.c +++ b/src/lua/lua_config.c @@ -5268,21 +5268,18 @@ lua_config_list_regexp_scopes(lua_State *L) struct rspamd_config *cfg = lua_check_config(L, 1); if (cfg) { - char **scope_names, **cur_scope; - unsigned int i; - - scope_names = rspamd_re_cache_get_scope_names(cfg->re_cache); + struct rspamd_re_cache *scope; + unsigned int i = 0; lua_newtable(L); - if (scope_names) { - for (cur_scope = scope_names, i = 0; *cur_scope != NULL; cur_scope++, i++) { - lua_pushinteger(L, i + 1); - lua_pushstring(L, scope_names[i]); - lua_settable(L, -3); - } - - g_strfreev(scope_names); + for (scope = rspamd_re_cache_scope_first(cfg->re_cache); + scope != NULL; + scope = rspamd_re_cache_scope_next(scope)) { + lua_pushinteger(L, i + 1); + lua_pushstring(L, rspamd_re_cache_scope_name(scope)); + lua_settable(L, -3); + i++; } } else {