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;
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;
}
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);
}
}
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;
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)
*/
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
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
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
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
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 {