]> source.dussan.org Git - rspamd.git/commitdiff
[Rework] Further work on deps processing
authorVsevolod Stakhov <vsevolod@rspamd.com>
Sat, 9 Apr 2022 20:59:34 +0000 (21:59 +0100)
committerVsevolod Stakhov <vsevolod@rspamd.com>
Sat, 9 Apr 2022 20:59:34 +0000 (21:59 +0100)
src/libserver/symcache/symcache_impl.cxx
src/libserver/symcache/symcache_internal.hxx

index e1f3cafbb233a115b8310e752f49e20cdb791e29..a7afae6d9d5f044c98ed48a755bebbc736e33084 100644 (file)
@@ -408,6 +408,132 @@ auto cache_item::get_parent(const symcache &cache) const -> const cache_item *
        return nullptr;
 }
 
+auto cache_item::process_deps(const symcache &cache) -> void
+{
+       /* Allow logging macros to work */
+       auto log_tag = [&](){ return cache.log_tag(); };
+
+       for (auto &dep : deps) {
+               msg_debug_cache ("process real dependency %s on %s", symbol.c_str(), dep.sym.c_str());
+               auto *dit = cache.get_item_by_name_mut(dep.sym, true);
+
+               if (dep.vid >= 0) {
+                       /* Case of the virtual symbol that depends on another (maybe virtual) symbol */
+                       const auto *vdit = cache.get_item_by_name(dep.sym, false);
+
+                       if (!vdit) {
+                               if (dit) {
+                                       msg_err_cache ("cannot add dependency from %s on %s: no dependency symbol registered",
+                                                       dep.sym.c_str(), dit->symbol.c_str());
+                               }
+                       }
+                       else {
+                               msg_debug_cache ("process virtual dependency %s(%d) on %s(%d)", symbol.c_str(),
+                                               dep.vid, vdit->symbol.c_str(), vdit->id);
+
+                               std::size_t nids = 0;
+
+                               msg_debug_cache ("check id propagation for dependency %s from %s",
+                                               symbol.c_str(), dit->symbol.c_str());
+
+                               const auto *ids = dit->allowed_ids.get_ids(nids);
+
+                               /* TODO: merge? */
+                               if (nids > 0) {
+                                       msg_info_cache ("propagate allowed ids from %s to %s",
+                                                       dit->symbol.c_str(), symbol.c_str());
+
+                                       rspamd_symcache_set_allowed_settings_ids (cache, it->symbol, ids,
+                                                       nids);
+                               }
+
+                               ids = rspamd_symcache_get_forbidden_settings_ids (cache, dit->symbol, &nids);
+
+                               if (nids > 0) {
+                                       msg_info_cache ("propagate forbidden ids from %s to %s",
+                                                       dit->symbol, it->symbol);
+
+                                       rspamd_symcache_set_forbidden_settings_ids (cache, it->symbol, ids,
+                                                       nids);
+                               }
+                       }
+               }
+
+               if (dit != nullptr) {
+                       if (!dit->is_filter()) {
+                               /*
+                                * Check sanity:
+                                * - filters -> prefilter dependency is OK and always satisfied
+                                * - postfilter -> (filter, prefilter) dep is ok
+                                * - idempotent -> (any) dep is OK
+                                *
+                                * Otherwise, emit error
+                                * However, even if everything is fine this dep is useless ¯\_(ツ)_/¯
+                                */
+                               auto ok_dep = false;
+
+                               if (is_filter()) {
+                                       if (dit->is_filter()) {
+                                               ok_dep = true;
+                                       }
+                                       else if (dit->type & SYMBOL_TYPE_PREFILTER) {
+                                               ok_dep = true;
+                                       }
+                               }
+                               else if (type & SYMBOL_TYPE_POSTFILTER) {
+                                       if (dit->type & SYMBOL_TYPE_PREFILTER) {
+                                               ok_dep = true;
+                                       }
+                               }
+                               else if (type & SYMBOL_TYPE_IDEMPOTENT) {
+                                       if (dit->type & (SYMBOL_TYPE_PREFILTER|SYMBOL_TYPE_POSTFILTER)) {
+                                               ok_dep = true;
+                                       }
+                               }
+                               else if (type & SYMBOL_TYPE_PREFILTER) {
+                                       if (priority < dit->priority) {
+                                               /* Also OK */
+                                               ok_dep = true;
+                                       }
+                               }
+
+                               if (!ok_dep) {
+                                       msg_err_cache ("cannot add dependency from %s on %s: invalid symbol types",
+                                                       dep.sym.c_str(), symbol.c_str());
+
+                                       continue;
+                               }
+                       }
+                       else {
+                               if (dit->id == id) {
+                                       msg_err_cache ("cannot add dependency on self: %s -> %s "
+                                                                  "(resolved to %s)",
+                                                       symbol.c_str(), dep.sym.c_str(), dit->symbol.c_str());
+                               } else {
+                                       /* Create a reverse dep */
+                                       dit->rdeps.emplace_back(getptr(), dep.sym, id, -1);
+                                       dep.item = dit->getptr();
+                                       dep.id = dit->id;
+
+                                       msg_debug_cache ("add dependency from %d on %d", id,
+                                                       dit->id);
+                               }
+                       }
+               }
+               else if (dep.id >= 0) {
+                       msg_err_cache ("cannot find dependency on symbol %s for symbol %s",
+                                       dep.sym.c_str(), symbol.c_str());
+
+                       return;
+               }
+
+               if (vdit) {
+                       /* Use virtual symbol to propagate deps */
+                       rspamd_symcache_propagate_dep (cache, it, vdit);
+               }
+       }
+}
+
 auto virtual_item::get_parent(const symcache &cache) const -> const cache_item *
 {
        if (parent) {
index b7e18ec1eb2acfe4d5917e01128f562a4adbf749..cb7d206b0be3ec04ed3712d7e79020409c0bce34 100644 (file)
@@ -25,6 +25,7 @@
 #include <cmath>
 #include <cstdlib>
 #include <cstdint>
+#include <utility>
 #include <vector>
 #include <string>
 #include <string_view>
 #include "lua/lua_common.h"
 
 #define msg_err_cache(...) rspamd_default_log_function (G_LOG_LEVEL_CRITICAL, \
-        static_pool->tag.tagname, cfg->checksum, \
+        "symcache", log_tag(), \
         RSPAMD_LOG_FUNC, \
         __VA_ARGS__)
 #define msg_warn_cache(...)   rspamd_default_log_function (G_LOG_LEVEL_WARNING, \
-        static_pool->tag.tagname, cfg->checksum, \
+        "symcache", log_tag(), \
         RSPAMD_LOG_FUNC, \
         __VA_ARGS__)
 #define msg_info_cache(...)   rspamd_default_log_function (G_LOG_LEVEL_INFO, \
-        static_pool->tag.tagname, cfg->checksum, \
+        "symcache", log_tag(), \
         RSPAMD_LOG_FUNC, \
         __VA_ARGS__)
 #define msg_debug_cache(...)  rspamd_conditional_debug_fast (NULL, NULL, \
-        rspamd_symcache_log_id, "symcache", cfg->checksum, \
+        rspamd_symcache_log_id, "symcache", log_tag(), \
         RSPAMD_LOG_FUNC, \
         __VA_ARGS__)
 #define msg_debug_cache_task(...)  rspamd_conditional_debug_fast (NULL, NULL, \
@@ -171,6 +172,8 @@ struct id_list {
                        }
                }
        }
+
+
 };
 
 class symcache;
@@ -222,14 +225,18 @@ struct cache_dependency {
        std::string sym; /* Symbolic dep name */
        int id; /* Real from */
        int vid; /* Virtual from */
+public:
+       /* Default piecewise constructor */
+       cache_dependency(cache_item_ptr _item, std::string _sym, int _id, int _vid) :
+               item(std::move(_item)), sym(std::move(_sym)), id(_id), vid(_vid) {}
 };
 
-struct cache_item {
+struct cache_item : std::enable_shared_from_this<cache_item> {
        /* This block is likely shared */
        struct rspamd_symcache_item_stat *st;
        struct rspamd_counter_data *cd;
 
-       std::uint64_t last_count;
+       std::uint64_t last_count = 0;
        std::string symbol;
        std::string_view type_descr;
        int type;
@@ -238,16 +245,16 @@ struct cache_item {
        std::variant<normal_item, virtual_item> specific;
 
        /* Condition of execution */
-       bool enabled;
+       bool enabled = true;
 
        /* Priority */
-       int priority;
+       int priority = 0;
        /* Topological order */
-       unsigned int order;
+       unsigned int order = 0;
        /* Unique id - counter */
-       int id;
+       int id = 0;
 
-       int frequency_peaks;
+       int frequency_peaks = 0;
        /* Settings ids */
        id_list allowed_ids;
        /* Allows execution but not symbols insertion */
@@ -259,7 +266,33 @@ struct cache_item {
        /* Reverse dependencies */
        std::vector<cache_item_ptr> rdeps;
 
+public:
+       [[nodiscard]] static auto create() -> cache_item_ptr {
+               return std::shared_ptr<cache_item>(new cache_item());
+       }
+       /**
+        * Share ownership on the item
+        * @return
+        */
+       auto getptr() -> cache_item_ptr {
+               return shared_from_this();
+       }
+       /**
+        * Process and resolve dependencies for the item
+        * @param cache
+        */
+       auto process_deps(const symcache &cache) -> void;
        auto is_virtual() const -> bool { return std::holds_alternative<virtual_item>(specific); }
+       auto is_filter() const -> bool {
+               static constexpr const auto forbidden_flags = SYMBOL_TYPE_PREFILTER|
+                               SYMBOL_TYPE_COMPOSITE|
+                               SYMBOL_TYPE_CONNFILTER|
+                               SYMBOL_TYPE_POSTFILTER|
+                               SYMBOL_TYPE_IDEMPOTENT;
+
+               return std::holds_alternative<normal_item>(specific) &&
+                       (type & forbidden_flags) == 0;
+       }
        auto get_parent(const symcache &cache) const -> const cache_item *;
        auto add_condition(lua_State *L, int cbref) -> bool {
                if (!is_virtual()) {
@@ -271,6 +304,9 @@ struct cache_item {
 
                return false;
        }
+
+private:
+       cache_item() = default;
 };
 
 struct delayed_cache_dependency {
@@ -377,11 +413,19 @@ public:
         */
        auto add_dependency(int id_from, std::string_view to, int virtual_id_from) -> void;
 
-       /*
+       /**
         * Initialises the symbols cache, must be called after all symbols are added
         * and the config file is loaded
         */
        auto init() -> bool;
+
+       /**
+        * Log helper that returns cfg checksum
+        * @return
+        */
+       auto log_tag() const -> const char* {
+               return cfg->checksum;
+       }
 };
 
 /*
@@ -396,14 +440,6 @@ struct cache_dynamic_item {
        std::uint32_t async_events;
 };
 
-
-struct cache_dependency {
-       cache_item_ptr item; /* Owning pointer to the real dep */
-       std::string_view sym; /* Symbolic dep name */
-       int id; /* Real from */
-       int vid; /* Virtual from */
-};
-
 struct cache_savepoint {
        unsigned order_gen;
        unsigned items_inflight;