Initial version
This commit is contained in:
commit
04b878f078
28 changed files with 1771 additions and 0 deletions
144
example/include/health/ui/plugin_registry.hpp
Normal file
144
example/include/health/ui/plugin_registry.hpp
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
#ifndef HEALTH_UI_PLUGIN_REGISTRY_HPP
|
||||
#define HEALTH_UI_PLUGIN_REGISTRY_HPP
|
||||
|
||||
#include <list>
|
||||
|
||||
#include <infra/log.hpp>
|
||||
|
||||
#include <util/shared_object.hpp>
|
||||
|
||||
#include <health/ui/plugin_api.hpp>
|
||||
#include <health/ui/error_or.hpp>
|
||||
|
||||
namespace health::ui {
|
||||
// coverity[autosar_cpp14_a11_0_1_violation] we do not need a class
|
||||
struct LoadedPlugin {
|
||||
// coverity[autosar_cpp14_m11_0_1_violation] we do not need a class
|
||||
std::string name;
|
||||
// coverity[autosar_cpp14_m11_0_1_violation] we do not need a class
|
||||
std::filesystem::path file;
|
||||
// coverity[autosar_cpp14_m11_0_1_violation] we do not need a class
|
||||
std::unique_ptr<util::shared::Library> library;
|
||||
// coverity[autosar_cpp14_m11_0_1_violation] we do not need a class
|
||||
std::unique_ptr<health::ui::PluginApi> api;
|
||||
// coverity[autosar_cpp14_m11_0_1_violation] we do not need a class
|
||||
std::unique_ptr<health::ui::Adapter> adapter;
|
||||
};
|
||||
|
||||
class PluginRegistry : public Adapter {
|
||||
public:
|
||||
// coverity[autosar_cpp14_a8_4_7_violation : FALSE] parameter gets moved
|
||||
PluginRegistry(const util::shared::Loader& loader, infra::log::LoggerPtr logger, std::shared_ptr<asap::Participant> participant)
|
||||
: m_loader { loader }
|
||||
, m_logger { std::move(logger) }
|
||||
, m_participant { std::move(participant) }
|
||||
, m_plugins {}
|
||||
{
|
||||
}
|
||||
|
||||
[[nodiscard]] bool is_compatible(const Version our, const Version their) const
|
||||
{
|
||||
return is_compatible_impl(our, their);
|
||||
}
|
||||
|
||||
// load plugin(s) from the given path
|
||||
//
|
||||
// NB: we currently do not support loading plugins from a directory
|
||||
util::ErrorOr<std::string> load(const std::filesystem::path& path)
|
||||
{
|
||||
// coverity[autosar_cpp14_a5_1_4_violation : FALSE] objects get moved
|
||||
return load_impl(path).and_then([this](LoadedPlugin& p) -> util::ErrorOr<std::string> {
|
||||
const auto plugin_name { p.name };
|
||||
m_logger->info("Loaded plugin '{}' from '{}'", p.name, p.file);
|
||||
m_plugins.push_back(std::move(p));
|
||||
return { plugin_name };
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
// coverity[autosar_cpp14_a7_1_8_violation : FALSE] nodiscard ignored
|
||||
[[nodiscard]] virtual bool is_compatible_impl(const Version our, const Version their) const
|
||||
{
|
||||
return our == their; // be conservative right now
|
||||
}
|
||||
|
||||
virtual util::ErrorOr<LoadedPlugin> load_impl(const std::filesystem::path& path) const
|
||||
{
|
||||
// we currently do not support loading directories, so just delegate to load_file for now
|
||||
return load_file(path);
|
||||
}
|
||||
|
||||
std::unique_ptr<PluginApi> create_api(const std::string& name) const
|
||||
{
|
||||
class PluginApiImpl : public PluginApi {
|
||||
public:
|
||||
// coverity[autosar_cpp14_a8_4_7_violation : FALSE] parameter gets moved
|
||||
PluginApiImpl(std::shared_ptr<asap::Participant> participant, infra::log::LoggerPtr logger)
|
||||
: m_participant { std::move(participant) }
|
||||
, m_logger { std::move(logger) }
|
||||
{
|
||||
}
|
||||
|
||||
[[nodiscard]] std::shared_ptr<asap::Participant> get_participant() const override
|
||||
{
|
||||
return m_participant;
|
||||
}
|
||||
|
||||
[[nodiscard]] ::infra::log::LoggerPtr get_logger() const override
|
||||
{
|
||||
return m_logger;
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<asap::Participant> m_participant;
|
||||
infra::log::LoggerPtr m_logger;
|
||||
};
|
||||
|
||||
return std::make_unique<PluginApiImpl>(m_participant, m_logger->get_child(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Main functionality for our class
|
||||
*/
|
||||
virtual util::ErrorOr<LoadedPlugin> load_file(const std::filesystem::path& file) const
|
||||
{
|
||||
auto lib { m_loader.load(file) };
|
||||
if (const auto version { lib->get<Version>("health_ui_version") }; !is_compatible(health::ui::PLUGIN_API_VERSION, version)) {
|
||||
return { std::make_error_code(std::errc::protocol_not_supported), "plugin has an incompatible version" };
|
||||
} else {
|
||||
return load_plugin(file, std::move(lib));
|
||||
}
|
||||
}
|
||||
|
||||
// coverity[autosar_cpp14_a8_4_7_violation : FALSE] move semantics
|
||||
virtual util::ErrorOr<LoadedPlugin> load_plugin(const std::filesystem::path& file, std::unique_ptr<util::shared::Library> lib) const
|
||||
{
|
||||
m_logger->debug("Trying to load compatible plugin from '{}'", file);
|
||||
const auto plugin_info { lib->get<PluginInfo*>("health_ui_info") };
|
||||
std::string name { plugin_info->name };
|
||||
|
||||
auto api { create_api(name) };
|
||||
|
||||
// coverity[autosar_cpp14_a5_1_4_violation : FALSE] objects get moved
|
||||
return plugin_info->create(*api).and_then([&name, &file, &lib, &api](AdapterPtr& adapter) -> util::ErrorOr<LoadedPlugin> {
|
||||
return LoadedPlugin { std::move(name), file, std::move(lib), std::move(api), std::move(adapter) };
|
||||
});
|
||||
}
|
||||
|
||||
void update_internal(const ::health::Snapshot& system_state, const ::health::monitoring::HealthData& health_data) override
|
||||
{
|
||||
m_logger->debug("Updating {} ui-adapters...", m_plugins.size());
|
||||
for (const auto& plugin : m_plugins) {
|
||||
m_logger->trace("Updating '{}'...", plugin.name);
|
||||
plugin.adapter->update(system_state, health_data);
|
||||
}
|
||||
}
|
||||
|
||||
const util::shared::Loader& m_loader;
|
||||
infra::log::LoggerPtr m_logger;
|
||||
std::shared_ptr<asap::Participant> m_participant;
|
||||
std::list<LoadedPlugin> m_plugins;
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* HEALTH_UI_PLUGIN_REGISTRY_HPP */
|
||||
Loading…
Add table
Add a link
Reference in a new issue