From: Vsevolod Stakhov Date: Sat, 22 Oct 2022 13:55:52 +0000 (+0100) Subject: [Project] Start C API implementation X-Git-Tag: 3.4~34 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=fc3bfa4f62f6296e7ada58a74e0eaefa1c5a737b;p=rspamd.git [Project] Start C API implementation --- 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 /* for glob */ #include /* 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 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(obj)) +#define C_DB_FROM_CXX(obj) (reinterpret_cast(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