mirror of
https://github.com/FairRootGroup/FairMQ.git
synced 2025-10-13 08:41:16 +00:00
FairMQ: Add static plugin mechanism
* Add skeleton for Take/ReleaseControl API * Add skeleton for control_static builtin plugin
This commit is contained in:
parent
17d7cd8ce4
commit
052ac8487d
|
@ -85,6 +85,8 @@ set(FAIRMQ_HEADER_FILES
|
|||
Plugin.h
|
||||
PluginManager.h
|
||||
PluginServices.h
|
||||
plugins/Builtin.h
|
||||
plugins/ControlStatic.h
|
||||
runFairMQDevice.h
|
||||
shmem/FairMQMessageSHM.h
|
||||
shmem/FairMQPollerSHM.h
|
||||
|
@ -146,6 +148,7 @@ set(FAIRMQ_SOURCE_FILES
|
|||
Plugin.cxx
|
||||
PluginManager.cxx
|
||||
PluginServices.cxx
|
||||
plugins/ControlStatic.cxx
|
||||
shmem/FairMQMessageSHM.cxx
|
||||
shmem/FairMQPollerSHM.cxx
|
||||
shmem/FairMQRegionSHM.cxx
|
||||
|
|
|
@ -70,6 +70,8 @@ class Plugin
|
|||
auto ChangeDeviceState(const DeviceStateTransition next) -> void { fPluginServices->ChangeDeviceState(next); }
|
||||
auto SubscribeToDeviceStateChange(std::function<void(DeviceState)> callback) -> void { fPluginServices->SubscribeToDeviceStateChange(fkName, callback); }
|
||||
auto UnsubscribeFromDeviceStateChange() -> void { fPluginServices->UnsubscribeFromDeviceStateChange(fkName); }
|
||||
auto TakeControl() -> void { fPluginServices->TakeControl(fkName); };
|
||||
auto ReleaseControl() -> void { fPluginServices->ReleaseControl(fkName); };
|
||||
|
||||
// device config API
|
||||
// see <fairmq/PluginServices.h> for docs
|
||||
|
@ -97,7 +99,7 @@ class Plugin
|
|||
} /* namespace fair */
|
||||
|
||||
#define REGISTER_FAIRMQ_PLUGIN(KLASS, NAME, VERSION, MAINTAINER, HOMEPAGE, PROGOPTIONS) \
|
||||
static auto Make_##NAME##_Plugin(fair::mq::PluginServices* pluginServices) -> std::shared_ptr<KLASS> \
|
||||
static auto Make_##NAME##_Plugin(fair::mq::PluginServices* pluginServices) -> std::shared_ptr<fair::mq::Plugin> \
|
||||
{ \
|
||||
return std::make_shared<KLASS>(std::string{#NAME}, VERSION, std::string{MAINTAINER}, std::string{HOMEPAGE}, pluginServices); \
|
||||
} \
|
||||
|
|
|
@ -126,6 +126,11 @@ auto fair::mq::PluginManager::LoadPlugin(const string& pluginName) -> void
|
|||
// Mechanism B: dynamic
|
||||
LoadPluginDynamic(pluginName.substr(2));
|
||||
}
|
||||
else if (pluginName.substr(0,2) == "s:")
|
||||
{
|
||||
// Mechanism C: static (builtin)
|
||||
LoadPluginStatic(pluginName.substr(2));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Mechanism B: dynamic (default)
|
||||
|
@ -141,6 +146,7 @@ auto fair::mq::PluginManager::LoadPluginPrelinkedDynamic(const string& pluginNam
|
|||
try
|
||||
{
|
||||
LoadSymbols(pluginName, dll::program_location());
|
||||
fPluginOrder.push_back(pluginName);
|
||||
}
|
||||
catch (boost::system::system_error& e)
|
||||
{
|
||||
|
@ -181,6 +187,23 @@ auto fair::mq::PluginManager::LoadPluginDynamic(const string& pluginName) -> voi
|
|||
}
|
||||
}
|
||||
|
||||
auto fair::mq::PluginManager::LoadPluginStatic(const string& pluginName) -> void
|
||||
{
|
||||
// Load symbol
|
||||
if (fPluginFactories.find(pluginName) == fPluginFactories.end())
|
||||
{
|
||||
try
|
||||
{
|
||||
LoadSymbols(pluginName, dll::program_location());
|
||||
fPluginOrder.push_back(pluginName);
|
||||
}
|
||||
catch (boost::system::system_error& e)
|
||||
{
|
||||
throw PluginLoadError(ToString("An error occurred while loading static plugin ", pluginName, ": ", e.what()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto fair::mq::PluginManager::InstantiatePlugin(const string& pluginName) -> void
|
||||
{
|
||||
if (fPlugins.find(pluginName) == fPlugins.end())
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include <fairmq/Plugin.h>
|
||||
#include <fairmq/PluginServices.h>
|
||||
#include <fairmq/plugins/Builtin.h>
|
||||
#include <fairmq/Tools.h>
|
||||
#include <FairMQDevice.h>
|
||||
#define BOOST_FILESYSTEM_VERSION 3
|
||||
|
@ -27,7 +28,6 @@
|
|||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
namespace fair
|
||||
|
@ -43,6 +43,7 @@ namespace mq
|
|||
* facilitates two plugin mechanisms:
|
||||
* A prelinked dynamic plugins (shared libraries)
|
||||
* B dynamic plugins (shared libraries)
|
||||
* C static plugins (builtin)
|
||||
*/
|
||||
class PluginManager
|
||||
{
|
||||
|
@ -82,6 +83,7 @@ class PluginManager
|
|||
|
||||
auto LoadPluginPrelinkedDynamic(const std::string& pluginName) -> void;
|
||||
auto LoadPluginDynamic(const std::string& pluginName) -> void;
|
||||
auto LoadPluginStatic(const std::string& pluginName) -> void;
|
||||
template<typename... Args>
|
||||
auto LoadSymbols(const std::string& pluginName, Args&&... args) -> void
|
||||
{
|
||||
|
|
|
@ -119,6 +119,9 @@ class PluginServices
|
|||
});
|
||||
}
|
||||
|
||||
auto TakeControl(const std::string& controller) -> void { };
|
||||
auto ReleaseControl(const std::string& controller) -> void { };
|
||||
|
||||
/// @brief Unsubscribe from device state changes
|
||||
/// @param subscriber id
|
||||
auto UnsubscribeFromDeviceStateChange(const std::string& subscriber) -> void { fDevice->UnsubscribeFromStateChange(subscriber); }
|
||||
|
|
11
fairmq/plugins/Builtin.h
Normal file
11
fairmq/plugins/Builtin.h
Normal file
|
@ -0,0 +1,11 @@
|
|||
/********************************************************************************
|
||||
* Copyright (C) 2017 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* *
|
||||
* This software is distributed under the terms of the *
|
||||
* GNU Lesser General Public Licence (LGPL) version 3, *
|
||||
* copied verbatim in the file "LICENSE" *
|
||||
********************************************************************************/
|
||||
|
||||
// List of all builtin plugin headers (the ones which call REGISTER_FAIRMQ_PLUGIN macro)
|
||||
|
||||
#include <fairmq/plugins/ControlStatic.h>
|
54
fairmq/plugins/ControlStatic.cxx
Normal file
54
fairmq/plugins/ControlStatic.cxx
Normal file
|
@ -0,0 +1,54 @@
|
|||
/********************************************************************************
|
||||
* Copyright (C) 2017 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* *
|
||||
* This software is distributed under the terms of the *
|
||||
* GNU Lesser General Public Licence (LGPL) version 3, *
|
||||
* copied verbatim in the file "LICENSE" *
|
||||
********************************************************************************/
|
||||
|
||||
#include "ControlStatic.h"
|
||||
|
||||
namespace fair
|
||||
{
|
||||
namespace mq
|
||||
{
|
||||
namespace plugins
|
||||
{
|
||||
|
||||
ControlStatic::ControlStatic(
|
||||
const std::string name,
|
||||
const Plugin::Version version,
|
||||
const std::string maintainer,
|
||||
const std::string homepage,
|
||||
PluginServices* pluginServices)
|
||||
: Plugin(name, version, maintainer, homepage, pluginServices)
|
||||
{
|
||||
SubscribeToDeviceStateChange(
|
||||
[&](DeviceState newState){
|
||||
LOG(WARN) << newState;
|
||||
switch (newState)
|
||||
{
|
||||
case DeviceState::InitializingDevice:
|
||||
LOG(WARN) << GetPropertyAsString("custom-example-option");
|
||||
SetProperty("custom-example-option", std::string{"new value"});
|
||||
break;
|
||||
case DeviceState::Exiting:
|
||||
LOG(WARN) << GetProperty<std::string>("custom-example-option");
|
||||
UnsubscribeFromDeviceStateChange();
|
||||
break;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
auto ControlStaticPluginProgramOptions() -> Plugin::ProgOptions
|
||||
{
|
||||
auto plugin_options = boost::program_options::options_description{"Control Static Plugin"};
|
||||
plugin_options.add_options()
|
||||
("custom-example-option", boost::program_options::value<std::string>(), "Custom option.");
|
||||
return plugin_options;
|
||||
}
|
||||
|
||||
} /* namespace plugins */
|
||||
} /* namespace mq */
|
||||
} /* namespace fair */
|
51
fairmq/plugins/ControlStatic.h
Normal file
51
fairmq/plugins/ControlStatic.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
/********************************************************************************
|
||||
* Copyright (C) 2017 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* *
|
||||
* This software is distributed under the terms of the *
|
||||
* GNU Lesser General Public Licence (LGPL) version 3, *
|
||||
* copied verbatim in the file "LICENSE" *
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef FAIR_MQ_PLUGINS_CONTROLSTATIC
|
||||
#define FAIR_MQ_PLUGINS_CONTROLSTATIC
|
||||
|
||||
#include <fairmq/Plugin.h>
|
||||
#include <string>
|
||||
|
||||
namespace fair
|
||||
{
|
||||
namespace mq
|
||||
{
|
||||
namespace plugins
|
||||
{
|
||||
|
||||
class ControlStatic : public Plugin
|
||||
{
|
||||
public:
|
||||
|
||||
ControlStatic(
|
||||
const std::string name,
|
||||
const Plugin::Version version,
|
||||
const std::string maintainer,
|
||||
const std::string homepage,
|
||||
PluginServices* pluginServices
|
||||
);
|
||||
}; /* class ControlStatic */
|
||||
|
||||
auto ControlStaticPluginProgramOptions() -> Plugin::ProgOptions;
|
||||
|
||||
REGISTER_FAIRMQ_PLUGIN(
|
||||
ControlStatic, // Class name
|
||||
control_static, // Plugin name (string, lower case chars only)
|
||||
(Plugin::Version{1,0,0}), // Version
|
||||
"FairRootGroup <fairroot@gsi.de>", // Maintainer
|
||||
"https://github.com/FairRootGroup/FairRoot", // Homepage
|
||||
ControlStaticPluginProgramOptions // Free function which declares custom program options for the plugin
|
||||
// signature: () -> boost::optional<boost::program_options::options_description>
|
||||
)
|
||||
|
||||
} /* namespace plugins */
|
||||
} /* namespace mq */
|
||||
} /* namespace fair */
|
||||
|
||||
#endif /* FAIR_MQ_PLUGINS_CONTROLSTATIC */
|
|
@ -122,10 +122,10 @@ add_testsuite(FairMQ.Plugins
|
|||
TIMEOUT 10
|
||||
)
|
||||
|
||||
add_testsuite(FairMQ.PluginsStatic
|
||||
add_testsuite(FairMQ.PluginsPrelinked
|
||||
SOURCES
|
||||
plugins/runner.cxx
|
||||
plugins/_plugin_manager_static.cxx
|
||||
plugins/_plugin_manager_prelink.cxx
|
||||
|
||||
LINKS FairMQ FairMQPlugin_test_dummy FairMQPlugin_test_dummy2
|
||||
TIMEOUT 10
|
||||
|
|
|
@ -37,11 +37,11 @@ auto control(shared_ptr<FairMQDevice> device) -> void
|
|||
}
|
||||
}
|
||||
|
||||
TEST(PluginManager, LoadPlugin)
|
||||
TEST(PluginManager, LoadPluginDynamic)
|
||||
{
|
||||
FairMQProgOptions config{};
|
||||
auto device = make_shared<FairMQDevice>();
|
||||
auto mgr = PluginManager{};
|
||||
auto device = make_shared<FairMQDevice>();
|
||||
mgr.EmplacePluginServices(&config, device);
|
||||
|
||||
mgr.PrependSearchPath("./lib");
|
||||
|
@ -65,6 +65,31 @@ TEST(PluginManager, LoadPlugin)
|
|||
control(device);
|
||||
}
|
||||
|
||||
TEST(PluginManager, LoadPluginStatic)
|
||||
{
|
||||
FairMQProgOptions config{};
|
||||
auto mgr = PluginManager{};
|
||||
auto device = make_shared<FairMQDevice>();
|
||||
mgr.EmplacePluginServices(&config, device);
|
||||
|
||||
ASSERT_NO_THROW(mgr.LoadPlugin("s:control_static"));
|
||||
|
||||
ASSERT_NO_THROW(mgr.InstantiatePlugins());
|
||||
|
||||
// check order
|
||||
const auto expected = vector<string>{"control_static"};
|
||||
auto actual = vector<string>{};
|
||||
mgr.ForEachPlugin([&](Plugin& plugin){ actual.push_back(plugin.GetName()); });
|
||||
ASSERT_TRUE(actual == expected);
|
||||
|
||||
// program options
|
||||
auto count = 0;
|
||||
mgr.ForEachPluginProgOptions([&count](const options_description& d){ ++count; });
|
||||
ASSERT_EQ(count, 1);
|
||||
|
||||
control(device);
|
||||
}
|
||||
|
||||
TEST(PluginManager, Factory)
|
||||
{
|
||||
const auto args = vector<string>{"-l", "debug", "--help", "-S", ">/lib", "</home/user/lib", "/usr/local/lib", "/usr/lib"};
|
||||
|
|
|
@ -8,10 +8,6 @@
|
|||
|
||||
#include <gtest/gtest.h>
|
||||
#include <fairmq/PluginManager.h>
|
||||
#include <FairMQDevice.h>
|
||||
#include <options/FairMQProgOptions.h>
|
||||
#include <FairMQLogger.h>
|
||||
#include <vector>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
@ -19,7 +15,7 @@ namespace
|
|||
using namespace fair::mq;
|
||||
using namespace std;
|
||||
|
||||
TEST(PluginManager, LoadPluginStatic)
|
||||
TEST(PluginManager, LoadPluginPrelinkedDynamic)
|
||||
{
|
||||
auto mgr = PluginManager{};
|
||||
|
Loading…
Reference in New Issue
Block a user