From b85096f6499fbb629edb4ae324acc1a902a22a38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20L=C3=BCke?= Date: Mon, 30 Dec 2024 18:59:04 +0100 Subject: [PATCH] pass --plugin-args to mana c sink plugins --- README.md | 2 +- src/CMakeLists.txt | 3 +- src/internal/mana_lib.hpp | 38 +++++++++++++++++++++++ src/internal/mana_nng.hpp | 5 +-- src/mana_plugin_c_test.c | 6 +++- src/tools/CMakeLists.txt | 11 +++---- src/tools/mana_auto_replay.cc | 57 ++++++++++------------------------- src/tools/mana_nng_client.cc | 53 +++++++++----------------------- 8 files changed, 84 insertions(+), 91 deletions(-) diff --git a/README.md b/README.md index 21f1742..b76880a 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ ## How to build -Requires git, ninja, cmake, gcc or clang, boost-filesystem, boost-system. +Requires: git ninja cmake gcc/clang libboost-filesystem-dev libboost-system-dev libboost-program-options-dev If building under msys2 use ucrt64. diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ff19ec2..c1c808b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -14,8 +14,9 @@ target_link_libraries(mesytec-mnode PUBLIC nng mnode-proto PRIVATE spdlog) target_compile_features(mesytec-mnode PRIVATE cxx_std_17) target_compile_options(mesytec-mnode PRIVATE ${MVLC_NNG_MNODE_WARN_FLAGS}) +find_package(Boost CONFIG COMPONENTS filesystem program_options system REQUIRED) add_library(mana INTERFACE) -target_link_libraries(mana INTERFACE nlohmann_json::nlohmann_json mesytec-mvlc) +target_link_libraries(mana INTERFACE nlohmann_json::nlohmann_json mesytec-mvlc Boost::filesystem Boost::program_options Boost::system) target_include_directories(mana INTERFACE $ INTERFACE $) diff --git a/src/internal/mana_lib.hpp b/src/internal/mana_lib.hpp index eb2e3fe..d8363dd 100644 --- a/src/internal/mana_lib.hpp +++ b/src/internal/mana_lib.hpp @@ -3,6 +3,8 @@ #include "mana_api.hpp" #include "mana_arena.h" +#include +#include #include #include #include @@ -304,6 +306,42 @@ struct ObjectPath } }; +struct PluginWrapper +{ + boost::dll::shared_library pluginHandle; + std::unique_ptr manaCppPlugin; + std::unique_ptr destSink; +}; + +PluginWrapper load_mana_plugin(const std::string &filename, + const std::vector &pluginArgs) +{ + PluginWrapper result; + result.pluginHandle = boost::dll::shared_library(filename); + + if (auto entryPoint = result.pluginHandle.get("mana_get_sink_plugin")) + { + std::vector argv; + for (const auto &arg: pluginArgs) + argv.push_back(arg.data()); + result.destSink = std::make_unique(entryPoint(), argv.size(), argv.data()); + } + else if (auto entryPoint = result.pluginHandle.get("mana_get_plugin")) + { + result.manaCppPlugin = std::unique_ptr(entryPoint()); + if (!result.manaCppPlugin) + throw std::runtime_error("plugin {}: mana_get_plugin() returned nullptr"); + result.destSink = result.manaCppPlugin->makeSink(); + } + + return result; +} + +PluginWrapper load_mana_plugin(const std::string &filename, const std::string &cmdline) +{ + return load_mana_plugin(filename, boost::program_options::split_unix(cmdline)); +} + } // namespace mesytec::mnode::mana #endif /* AAB5E4D2_A05B_4F2F_B76A_406A5A569D55 */ diff --git a/src/internal/mana_nng.hpp b/src/internal/mana_nng.hpp index 8aceffb..f338adc 100644 --- a/src/internal/mana_nng.hpp +++ b/src/internal/mana_nng.hpp @@ -22,8 +22,6 @@ struct MessageHeader u32 messageType; }; -// TODO: don't need sizeBytes as the client can infer from the descriptor in begin_run() -// could transmit eventindex and array count as u16|u16 or sequence number and eventindex struct EventDataHeader { u16 eventIndex; @@ -31,6 +29,9 @@ struct EventDataHeader u32 sizeBytes; }; +// EventData message layout: MessageHeader, repeated(EventDataHeader + +// mana_offset_array_t[arrayCount]) + class NngServerSink: public IManaSink { public: diff --git a/src/mana_plugin_c_test.c b/src/mana_plugin_c_test.c index 1973912..ace8a3c 100644 --- a/src/mana_plugin_c_test.c +++ b/src/mana_plugin_c_test.c @@ -11,7 +11,11 @@ MANA_DEFINE_PLUGIN_INIT(init) { log_set_level(LOG_INFO); struct Context *ctx = calloc(1, sizeof(*ctx)); - log_info("init: ctx=%p", ctx); + log_info("init: ctx=%p, argc=%d", ctx, plugin_argc); + for (int i = 0; i < plugin_argc; ++i) + { + log_info("init: argv[%d]=%s", i, plugin_argv[i]); + } return ctx; } diff --git a/src/tools/CMakeLists.txt b/src/tools/CMakeLists.txt index f83477d..f10c70d 100644 --- a/src/tools/CMakeLists.txt +++ b/src/tools/CMakeLists.txt @@ -21,13 +21,10 @@ add_mnode_dev_executable(mesy_nng_push_pull_main) add_mnode_dev_executable(mesy_nng_pub_producer) add_mnode_dev_executable(mesy_nng_sub_consumer) -find_package(Boost CONFIG COMPONENTS filesystem system REQUIRED) -if (Boost_FOUND) - add_mnode_dev_executable(mana_auto_replay) - target_link_libraries(mana_auto_replay PRIVATE nlohmann_json::nlohmann_json mnode::resources Boost::filesystem Boost::system) - add_mnode_dev_executable(mana_nng_client) - target_link_libraries(mana_nng_client PRIVATE nlohmann_json::nlohmann_json mnode::resources Boost::filesystem Boost::system) -endif() +add_mnode_dev_executable(mana_auto_replay) +target_link_libraries(mana_auto_replay PRIVATE mana mnode::resources) +add_mnode_dev_executable(mana_nng_client) +target_link_libraries(mana_nng_client PRIVATE mana mnode::resources) add_mnode_proto_dev_executable(mnode_proto_test1) add_mnode_proto_dev_executable(mnode_proto_ping_client) diff --git a/src/tools/mana_auto_replay.cc b/src/tools/mana_auto_replay.cc index 366e48a..cf175dd 100644 --- a/src/tools/mana_auto_replay.cc +++ b/src/tools/mana_auto_replay.cc @@ -32,7 +32,6 @@ // -> want plugins. similar to the mvme listfile_reader but on analysis data #include -#include #include // mnode::resources #include #include @@ -375,13 +374,16 @@ struct NngPairStrategy: public ReplayStrategy void usage(const char *self) { - std::cout << fmt::format( - "usage: {} [--plugin=] [--replay-strategy=] \n", self); + std::cout << fmt::format("usage: {} [--plugin ] [--plugin-args ] " + "[--replay-strategy=] \n", + self); std::cout - << " --plugin= Load a plugin to process the data. Default is a " + << " --plugin Load a plugin to process the data. Default is a " "simple counting plugin.\n" + << " --plugin-args Optional arguments to pass to the plugin.\n" + << " --replay-strategy= Use a specific replay strategy. " "Available: 'single-threaded', 'multi-threaded'. Default: 'multi-threaded'\n" @@ -397,8 +399,8 @@ int main(int argc, char *argv[]) auto f = cmrc::mnode::resources::get_filesystem().open("data/vme_module_data_sources.json"); const auto jModuleDataSources = nlohmann::json::parse(f.begin(), f.end()); - argh::parser parser( - {"-h", "--help", "--plugin", "--replay-strategy", "--analysis-strategy", "--log-level"}); + argh::parser parser({"-h", "--help", "--plugin", "--plugin-args", "--replay-strategy", + "--analysis-strategy", "--log-level"}); parser.parse(argc, argv); @@ -425,57 +427,30 @@ int main(int argc, char *argv[]) return 1; } - boost::dll::shared_library pluginHandle; - std::unique_ptr manaCppPlugin; - std::unique_ptr destSink; + mana::PluginWrapper plugin; if (parser("--plugin")) { auto pluginFile = parser("--plugin").str(); + try { - pluginHandle = boost::dll::shared_library(pluginFile); - - try - { - if (auto entryPoint = - pluginHandle.get("mana_get_sink_plugin")) - { - destSink = std::make_unique(entryPoint(), 0, nullptr); - } - } - catch (const std::exception &e) - { - } - - if (!destSink) - { - if (auto entryPoint = pluginHandle.get("mana_get_plugin")) - { - manaCppPlugin = std::unique_ptr(entryPoint()); - if (!manaCppPlugin) - throw std::runtime_error("plugin {}: mana_get_plugin() returned nullptr"); - destSink = manaCppPlugin->makeSink(); - } - } + plugin = mana::load_mana_plugin(pluginFile, parser("--plugin-args").str()); } catch (const std::exception &e) { - std::cerr << fmt::format("Error loading shared library {}: {}\n", pluginFile, e.what()); - return 1; - } - - if (!destSink) - { - std::cerr << fmt::format("Error: plugin {} does not provide a sink\n", pluginFile); + std::cerr << fmt::format("Error loading mana plugin from {}: {}\n", pluginFile, + e.what()); return 1; } } else { - destSink = std::make_unique(); + plugin.destSink = std::make_unique(); } + auto &destSink = plugin.destSink; + std::string strategyName = "multi-threaded"; if (parser("--replay-strategy")) diff --git a/src/tools/mana_nng_client.cc b/src/tools/mana_nng_client.cc index 53b0de9..71cdbbb 100644 --- a/src/tools/mana_nng_client.cc +++ b/src/tools/mana_nng_client.cc @@ -13,12 +13,15 @@ using namespace mesytec::mnode; void usage(const char *self) { - std::cout << fmt::format("usage: {} [--plugin=] \n", self); + std::cout << fmt::format("usage: {} [--plugin ] [--plugin-args ] \n", + self); std::cout - << " --plugin= Load a plugin to process the data. Default is a " + << " --plugin Load a plugin to process the data. Default is a " "simple counting plugin.\n" + << " --plugin-args Optional arguments to pass to the plugin.\n" + << " --log-level= One of 'trace', 'debug', 'info', 'warn', 'error', " "'off'.\n"; } @@ -30,7 +33,8 @@ void run(nng_socket socket_, mana::IManaSink *sink, std::atomic &quit) int main(int argc, char *argv[]) { - argh::parser parser({"-h", "--help", "--plugin", "--log-level"}); + argh::parser parser( + {"-h", "--help", "--plugin", "--plugin-args", "--plugin-args", "--log-level"}); parser.parse(argc, argv); auto url = parser[1]; @@ -48,57 +52,30 @@ int main(int argc, char *argv[]) spdlog::set_level(spdlog::level::from_str(parser("--log-level").str())); } - boost::dll::shared_library pluginHandle; - std::unique_ptr manaCppPlugin; - std::unique_ptr destSink; + mana::PluginWrapper plugin; if (parser("--plugin")) { auto pluginFile = parser("--plugin").str(); + try { - pluginHandle = boost::dll::shared_library(pluginFile); - - try - { - if (auto entryPoint = - pluginHandle.get("mana_get_sink_plugin")) - { - destSink = std::make_unique(entryPoint(), 0, nullptr); - } - } - catch (const std::exception &e) - { - } - - if (!destSink) - { - if (auto entryPoint = pluginHandle.get("mana_get_plugin")) - { - manaCppPlugin = std::unique_ptr(entryPoint()); - if (!manaCppPlugin) - throw std::runtime_error("plugin {}: mana_get_plugin() returned nullptr"); - destSink = manaCppPlugin->makeSink(); - } - } + plugin = mana::load_mana_plugin(pluginFile, parser("--plugin-args").str()); } catch (const std::exception &e) { - std::cerr << fmt::format("Error loading shared library {}: {}\n", pluginFile, e.what()); - return 1; - } - - if (!destSink) - { - std::cerr << fmt::format("Error: plugin {} does not provide a sink\n", pluginFile); + std::cerr << fmt::format("Error loading mana plugin from {}: {}\n", pluginFile, + e.what()); return 1; } } else { - destSink = std::make_unique(); + plugin.destSink = std::make_unique(); } + auto &destSink = plugin.destSink; + auto manaSink = std::make_unique(destSink.get()); nng_socket socket = nng::make_pair_socket();