diff options
author | Vsevolod Stakhov <vsevolod@rspamd.com> | 2022-10-22 14:55:52 +0100 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@rspamd.com> | 2022-10-22 14:55:52 +0100 |
commit | fc3bfa4f62f6296e7ada58a74e0eaefa1c5a737b (patch) | |
tree | 18833228895601fc45e910674616501481912578 | |
parent | 272503b1ba88fe9802192ef65a1f7674e0a51f2b (diff) | |
download | rspamd-fc3bfa4f62f6296e7ada58a74e0eaefa1c5a737b.tar.gz rspamd-fc3bfa4f62f6296e7ada58a74e0eaefa1c5a737b.zip |
[Project] Start C API implementation
-rw-r--r-- | src/libserver/hyperscan_tools.cxx | 75 | ||||
-rw-r--r-- | src/libserver/hyperscan_tools.h | 54 |
2 files changed, 127 insertions, 2 deletions
diff --git a/src/libserver/hyperscan_tools.cxx b/src/libserver/hyperscan_tools.cxx index 1272aa452..309f821dd 100644 --- a/src/libserver/hyperscan_tools.cxx +++ b/src/libserver/hyperscan_tools.cxx @@ -25,6 +25,7 @@ #include "hs.h" #include "logger.h" #include "worker_util.h" +#include "hyperscan_tools.h" #include <glob.h> /* for glob */ #include <unistd.h> /* for unlink */ @@ -35,7 +36,10 @@ "hyperscan", "", \ RSPAMD_LOG_FUNC, \ __VA_ARGS__) - +#define msg_err_hyperscan(...) rspamd_default_log_function (G_LOG_LEVEL_CRITICAL, \ + "hyperscan", "", \ + RSPAMD_LOG_FUNC, \ + __VA_ARGS__) #define msg_debug_hyperscan(...) rspamd_conditional_debug_fast (NULL, NULL, \ rspamd_hyperscan_log_id, "hyperscan", "", \ RSPAMD_LOG_FUNC, \ @@ -45,6 +49,12 @@ INIT_LOG_MODULE_PUBLIC(hyperscan) namespace rspamd::util { +/* + * A singleton class that is responsible for deletion of the outdated hyperscan files + * One issue is that it must know about HS files in all workers, which is a problem + * TODO: we need to export hyperscan caches from all workers to a single place where + * we can clean them up (probably, to the main process) + */ class hs_known_files_cache { private: // These fields are filled when we add new known cache files @@ -136,7 +146,7 @@ public: * This is a higher level representation of the cached hyperscan file */ struct hs_shared_database { - hs_database_t *db; /**< internal database (might be in a shared memory) */ + hs_database_t *db = nullptr; /**< internal database (might be in a shared memory) */ std::optional<raii_mmaped_file> maybe_map; ~hs_shared_database() { @@ -148,6 +158,16 @@ struct hs_shared_database { explicit hs_shared_database(raii_mmaped_file &&map, hs_database_t *db) : db(db), maybe_map(std::move(map)) {} explicit hs_shared_database(hs_database_t *db) : db(db), maybe_map(std::nullopt) {} + hs_shared_database(const hs_shared_database &other) = delete; + hs_shared_database() = default; + hs_shared_database(hs_shared_database &&other) noexcept { + *this = std::move(other); + } + hs_shared_database& operator=(hs_shared_database &&other) noexcept { + std::swap(db, other.db); + std::swap(maybe_map, other.maybe_map); + return *this; + } }; static auto @@ -286,5 +306,56 @@ auto load_cached_hs_file(const char *fname) -> tl::expected<hs_shared_database, } } // namespace rspamd::util +/* C API */ + +#define CXX_DB_FROM_C(obj) (reinterpret_cast<rspamd::util::hs_shared_database *>(obj)) +#define C_DB_FROM_CXX(obj) (reinterpret_cast<rspamd_hyperscan_t *>(obj)) + +rspamd_hyperscan_t * +rspamd_maybe_load_hyperscan(const char *filename) +{ + auto maybe_db = rspamd::util::load_cached_hs_file(filename); + + if (maybe_db.has_value()) { + auto *ndb = new rspamd::util::hs_shared_database; + *ndb = std::move(maybe_db.value()); + return C_DB_FROM_CXX(ndb); + } + else { + auto error = maybe_db.error(); + + switch(error.category) { + case rspamd::util::error_category::CRITICAL: + msg_err_hyperscan("critical error when trying to load cached hyperscan: %s", + error.error_message.data()); + break; + case rspamd::util::error_category::IMPORTANT: + msg_info_hyperscan("error when trying to load cached hyperscan: %s", + error.error_message.data()); + break; + default: + msg_debug_hyperscan("error when trying to load cached hyperscan: %s", + error.error_message.data()); + break; + } + } + + return nullptr; +} + +hs_database_t* +rspamd_hyperscan_get_database(rspamd_hyperscan_t *db) +{ + auto *real_db = CXX_DB_FROM_C(db); + return real_db->db; +} + +void +rspamd_hyperscan_free(rspamd_hyperscan_t *db) +{ + auto *real_db = CXX_DB_FROM_C(db); + + delete real_db; +} #endif // WITH_HYPERSCAN
\ No newline at end of file diff --git a/src/libserver/hyperscan_tools.h b/src/libserver/hyperscan_tools.h new file mode 100644 index 000000000..31139e6af --- /dev/null +++ b/src/libserver/hyperscan_tools.h @@ -0,0 +1,54 @@ +/*- + * Copyright 2022 Vsevolod Stakhov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "config.h" + +#ifndef RSPAMD_HYPERSCAN_TOOLS_H +#define RSPAMD_HYPERSCAN_TOOLS_H + +#ifdef WITH_HYPERSCAN + +#include "hs.h" + +G_BEGIN_DECLS + +/** + * Opaque structure that represents hyperscan (maybe shared/cached database) + */ +typedef struct rspamd_hyperscan_s rspamd_hyperscan_t; + +/** + * Maybe load or mmap shared a hyperscan from a file + * @param filename + * @return cached database if available + */ +rspamd_hyperscan_t *rspamd_hyperscan_maybe_load(const char *filename); +/** + * Get the internal database + * @param db + * @return + */ +hs_database_t* rspamd_hyperscan_get_database(rspamd_hyperscan_t *db); +/** + * Free the database + * @param db + */ +void rspamd_hyperscan_free(rspamd_hyperscan_t *db); + +G_END_DECLS + +#endif + +#endif |