]> git.ipfire.org Git - thirdparty/rspamd.git/commitdiff
[Rework] Try to fix the mess with types & flags
authorVsevolod Stakhov <vsevolod@rspamd.com>
Sun, 10 Apr 2022 11:51:49 +0000 (12:51 +0100)
committerVsevolod Stakhov <vsevolod@rspamd.com>
Sun, 10 Apr 2022 11:51:49 +0000 (12:51 +0100)
src/libserver/symcache/symcache_c.cxx
src/libserver/symcache/symcache_impl.cxx
src/libserver/symcache/symcache_internal.hxx

index 7255f9d10cd59427d9fd635e31bc801252fecdd3..7c204b04e6019e422d7cabb3909bd7d42e3d1b88 100644 (file)
@@ -46,3 +46,11 @@ rspamd_symcache_init (struct rspamd_symcache *cache)
 
        return real_cache->init();
 }
+
+void
+rspamd_symcache_save (struct rspamd_symcache *cache)
+{
+       auto *real_cache = C_API_SYMCACHE(cache);
+
+       real_cache->save_items();
+}
index aadd53b8f2d7af9888fd321ab50d9bfa6a17c9c9..0cae79873742463a6c9cc67b86f331af49b322da 100644 (file)
@@ -17,6 +17,7 @@
 #include "symcache_internal.hxx"
 #include "unix-std.h"
 #include "libutil/cxx/locked_file.hxx"
+#include "fmt/core.h"
 
 #include <cmath>
 
@@ -223,7 +224,7 @@ auto symcache::load_items() -> bool
                                }
                        }
 
-                       if (item->is_virtual() && !(item->type & SYMBOL_TYPE_GHOST)) {
+                       if (item->is_virtual() && !item->is_ghost()) {
                                const auto &parent = item->get_parent(*this);
 
                                if (parent) {
@@ -613,29 +614,11 @@ auto cache_item::process_deps(const symcache &cache) -> void
                                 */
                                auto ok_dep = false;
 
-                               if (is_filter()) {
-                                       if (dit->is_filter()) {
-                                               ok_dep = true;
-                                       }
-                                       else if (dit->type & SYMBOL_TYPE_PREFILTER) {
-                                               ok_dep = true;
-                                       }
+                               if (dit->get_type() == type) {
+                                       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;
-                                       }
+                               else if (type < dit->get_type()) {
+                                       ok_dep = true;
                                }
 
                                if (!ok_dep) {
@@ -683,4 +666,81 @@ auto virtual_item::get_parent(const symcache &cache) const -> const cache_item *
        return cache.get_item_by_id(parent_id, false);
 }
 
+auto item_type_from_c(enum rspamd_symbol_type type) -> tl::expected<std::pair<symcache_item_type, int>, std::string>
+{
+       constexpr const auto trivial_types = SYMBOL_TYPE_CONNFILTER|SYMBOL_TYPE_PREFILTER
+                                                  |SYMBOL_TYPE_POSTFILTER|SYMBOL_TYPE_IDEMPOTENT
+                                                  |SYMBOL_TYPE_COMPOSITE|SYMBOL_TYPE_CLASSIFIER
+                                                  |SYMBOL_TYPE_VIRTUAL;
+
+       constexpr auto all_but_one_ty = [&](int type, int exclude_bit) -> auto {
+               return type & (trivial_types & ~exclude_bit);
+       };
+
+       if (type & trivial_types) {
+               auto check_trivial = [&](auto flag, symcache_item_type ty) ->  tl::expected<std::pair<symcache_item_type, int>, std::string> {
+                       if (all_but_one_ty(type, flag)) {
+                               return tl::make_unexpected(fmt::format("invalid flags for a symbol: {}", type));
+                       }
+
+                       return std::make_pair(ty, type & ~flag);
+               };
+               if (type & SYMBOL_TYPE_CONNFILTER) {
+                       return check_trivial(SYMBOL_TYPE_CONNFILTER, symcache_item_type::CONNFILTER);
+               }
+               else if (type & SYMBOL_TYPE_PREFILTER) {
+                       return check_trivial(SYMBOL_TYPE_PREFILTER, symcache_item_type::PREFILTER);
+               }
+               else if (type & SYMBOL_TYPE_POSTFILTER) {
+                       return check_trivial(SYMBOL_TYPE_POSTFILTER, symcache_item_type::POSTFILTER);
+               }
+               else if (type & SYMBOL_TYPE_IDEMPOTENT) {
+                       return check_trivial(SYMBOL_TYPE_IDEMPOTENT, symcache_item_type::IDEMPOTENT);
+               }
+               else if (type & SYMBOL_TYPE_COMPOSITE) {
+                       return check_trivial(SYMBOL_TYPE_COMPOSITE, symcache_item_type::COMPOSITE);
+               }
+               else if (type & SYMBOL_TYPE_CLASSIFIER) {
+                       return check_trivial(SYMBOL_TYPE_CLASSIFIER, symcache_item_type::CLASSIFIER);
+               }
+               else if (type & SYMBOL_TYPE_VIRTUAL) {
+                       return check_trivial(SYMBOL_TYPE_VIRTUAL, symcache_item_type::VIRTUAL);
+               }
+
+               return tl::make_unexpected(fmt::format("internal error: impossible flags combination", type));
+       }
+
+       /* Maybe check other flags combination here? */
+       return std::make_pair(symcache_item_type::FILTER, type);
+}
+
+bool operator<(symcache_item_type lhs, symcache_item_type rhs)
+{
+       auto ret = false;
+       switch(lhs) {
+       case symcache_item_type::CONNFILTER:
+               break;
+       case symcache_item_type::PREFILTER:
+               if (rhs == symcache_item_type::CONNFILTER) {
+                       ret = true;
+               }
+               break;
+       case symcache_item_type::FILTER:
+               if (rhs == symcache_item_type::CONNFILTER || rhs == symcache_item_type::PREFILTER) {
+                       ret = true;
+               }
+               break;
+       case symcache_item_type::POSTFILTER:
+               if (rhs != symcache_item_type::IDEMPOTENT) {
+                       ret = true;
+               }
+               break;
+       case symcache_item_type::IDEMPOTENT:
+       default:
+               break;
+       }
+
+       return ret;
+}
+
 }
\ No newline at end of file
index 7dd664e5ca95ca43c6f1cf096fa63056393af97e..62b8e8d99935013cf4960b402d1f460e84663f42 100644 (file)
@@ -32,7 +32,7 @@
 #include <memory>
 #include <variant>
 #include "contrib/robin-hood/robin_hood.h"
-
+#include "contrib/expected/expected.hpp"
 #include "cfg_file.h"
 #include "lua/lua_common.h"
 
@@ -90,6 +90,29 @@ using order_generation_ptr = std::shared_ptr<order_generation>;
 
 class symcache;
 
+enum class symcache_item_type {
+       CONNFILTER, /* Executed on connection stage */
+       PREFILTER, /* Executed before all filters */
+       FILTER, /* Normal symbol with a callback */
+       POSTFILTER, /* Executed after all filters */
+       IDEMPOTENT, /* Executed after postfilters, cannot change results */
+       CLASSIFIER, /* A virtual classifier symbol */
+       COMPOSITE, /* A virtual composite symbol */
+       VIRTUAL, /* A virtual symbol... */
+};
+
+/*
+ * Compare item types: earlier stages symbols are > than later stages symbols
+ * Order for virtual stuff is not defined.
+ */
+bool operator < (symcache_item_type lhs, symcache_item_type rhs);
+/**
+ * This is a public helper to convert a legacy C type to a more static type
+ * @param type input type as a C enum
+ * @return pair of type safe symcache_item_type + the remaining flags or an error
+ */
+auto item_type_from_c(enum rspamd_symbol_type type) -> tl::expected<std::pair<symcache_item_type, int>, std::string>;
+
 struct item_condition {
 private:
        lua_State *L;
@@ -151,7 +174,8 @@ struct cache_item : std::enable_shared_from_this<cache_item> {
        std::uint64_t last_count = 0;
        std::string symbol;
        std::string_view type_descr;
-       int type;
+       symcache_item_type type;
+       int flags;
 
        /* Callback data */
        std::variant<normal_item, virtual_item> specific;
@@ -196,16 +220,16 @@ public:
        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;
+                       (type == symcache_item_type::FILTER);
+       }
+       auto is_ghost() const -> bool {
+               return flags & SYMBOL_TYPE_GHOST;
        }
        auto get_parent(const symcache &cache) const -> const cache_item *;
+       auto get_type() const -> auto {
+               return type;
+       }
        auto add_condition(lua_State *L, int cbref) -> bool {
                if (!is_virtual()) {
                        auto &normal = std::get<normal_item>(specific);
@@ -271,7 +295,6 @@ private:
 private:
        /* Internal methods */
        auto load_items() -> bool;
-       auto save_items() const -> bool;
        auto resort() -> void;
        /* Helper for g_hash_table_foreach */
        static auto metric_connect_cb(void *k, void *v, void *ud) -> void;
@@ -297,6 +320,12 @@ public:
                }
        }
 
+       /**
+        * Saves items on disk (if possible)
+        * @return
+        */
+       auto save_items() const -> bool;
+
        /**
         * Get an item by ID
         * @param id
@@ -342,9 +371,20 @@ public:
                return cfg->checksum;
        }
 
+       /**
+        * Helper to return a memory pool associated with the cache
+        * @return
+        */
        auto get_pool() const {
                return static_pool;
        }
+
+       auto add_symbol_with_callback(std::string_view name,
+                                                                 int priority,
+                                                                 symbol_func_t func,
+                                                                 void *user_data,
+                                                                 enum rspamd_symbol_type type) -> int;
+       auto add_virtual_symbol() -> int;
 };
 
 /*