Simplify structure in DeviceRunner and plugin classes

This commit is contained in:
Alexey Rybalchenko 2018-07-27 18:19:57 +02:00 committed by Dennis Klein
parent ee8afd7d2b
commit ef3eb5f83e
9 changed files with 54 additions and 55 deletions

View File

@ -13,9 +13,9 @@
using namespace fair::mq; using namespace fair::mq;
DeviceRunner::DeviceRunner(int argc, char* const argv[]) DeviceRunner::DeviceRunner(int argc, char* const argv[])
: fDevice(nullptr) : fRawCmdLineArgs(tools::ToStrVector(argc, argv, false))
, fRawCmdLineArgs(tools::ToStrVector(argc, argv, false))
, fConfig() , fConfig()
, fDevice(nullptr)
, fPluginManager(fRawCmdLineArgs) , fPluginManager(fRawCmdLineArgs)
, fEvents() , fEvents()
{} {}
@ -83,7 +83,7 @@ auto DeviceRunner::Run() -> int
fDevice->SetConfig(fConfig); fDevice->SetConfig(fConfig);
// Initialize plugin services // Initialize plugin services
fPluginManager.EmplacePluginServices(&fConfig, *fDevice); fPluginManager.EmplacePluginServices(fConfig, *fDevice);
// Instantiate and run plugins // Instantiate and run plugins
fPluginManager.InstantiatePlugins(); fPluginManager.InstantiatePlugins();

View File

@ -61,9 +61,9 @@ class DeviceRunner
template<typename H> template<typename H>
auto RemoveHook() -> void { fEvents.Unsubscribe<H>("runner"); } auto RemoveHook() -> void { fEvents.Unsubscribe<H>("runner"); }
std::unique_ptr<FairMQDevice> fDevice;
std::vector<std::string> fRawCmdLineArgs; std::vector<std::string> fRawCmdLineArgs;
FairMQProgOptions fConfig; FairMQProgOptions fConfig;
std::unique_ptr<FairMQDevice> fDevice;
PluginManager fPluginManager; PluginManager fPluginManager;
private: private:

View File

@ -116,9 +116,9 @@ class Plugin
} /* namespace fair */ } /* namespace fair */
#define REGISTER_FAIRMQ_PLUGIN(KLASS, NAME, VERSION, MAINTAINER, HOMEPAGE, PROGOPTIONS) \ #define REGISTER_FAIRMQ_PLUGIN(KLASS, NAME, VERSION, MAINTAINER, HOMEPAGE, PROGOPTIONS) \
static auto Make_##NAME##_Plugin(fair::mq::PluginServices* pluginServices) -> std::shared_ptr<fair::mq::Plugin> \ static auto Make_##NAME##_Plugin(fair::mq::PluginServices* pluginServices) -> std::unique_ptr<fair::mq::Plugin> \
{ \ { \
return std::make_shared<KLASS>(std::string{#NAME}, VERSION, std::string{MAINTAINER}, std::string{HOMEPAGE}, pluginServices); \ return fair::mq::tools::make_unique<KLASS>(std::string{#NAME}, VERSION, std::string{MAINTAINER}, std::string{HOMEPAGE}, pluginServices); \
} \ } \
BOOST_DLL_ALIAS(Make_##NAME##_Plugin, make_##NAME##_plugin) \ BOOST_DLL_ALIAS(Make_##NAME##_Plugin, make_##NAME##_plugin) \
BOOST_DLL_ALIAS(PROGOPTIONS, get_##NAME##_plugin_progoptions) BOOST_DLL_ALIAS(PROGOPTIONS, get_##NAME##_plugin_progoptions)

View File

@ -70,7 +70,6 @@ class PluginManager
struct PluginInstantiationError : std::runtime_error { using std::runtime_error::runtime_error; }; struct PluginInstantiationError : std::runtime_error { using std::runtime_error::runtime_error; };
static auto ProgramOptions() -> boost::program_options::options_description; static auto ProgramOptions() -> boost::program_options::options_description;
static auto MakeFromCommandLineOptions(const std::vector<std::string>) -> PluginManager;
struct ProgramOptionsParseError : std::runtime_error { using std::runtime_error::runtime_error; }; struct ProgramOptionsParseError : std::runtime_error { using std::runtime_error::runtime_error; };
static auto LibPrefix() -> const std::string& { return fgkLibPrefix; } static auto LibPrefix() -> const std::string& { return fgkLibPrefix; }

View File

@ -38,7 +38,7 @@ class PluginServices
{ {
public: public:
PluginServices() = delete; PluginServices() = delete;
PluginServices(FairMQProgOptions* config, FairMQDevice& device) PluginServices(FairMQProgOptions& config, FairMQDevice& device)
: fConfig(config) : fConfig(config)
, fDevice(device) , fDevice(device)
, fDeviceController() , fDeviceController()
@ -172,7 +172,7 @@ class PluginServices
// Config API // Config API
struct PropertyNotFoundError : std::runtime_error { using std::runtime_error::runtime_error; }; struct PropertyNotFoundError : std::runtime_error { using std::runtime_error::runtime_error; };
auto PropertyExists(const std::string& key) const -> bool { return fConfig->Count(key) > 0; } auto PropertyExists(const std::string& key) const -> bool { return fConfig.Count(key) > 0; }
/// @brief Set config property /// @brief Set config property
/// @param key /// @param key
@ -187,7 +187,7 @@ class PluginServices
auto currentState = GetCurrentDeviceState(); auto currentState = GetCurrentDeviceState();
if (currentState == DeviceState::InitializingDevice) if (currentState == DeviceState::InitializingDevice)
{ {
fConfig->SetValue(key, val); fConfig.SetValue(key, val);
} }
else else
{ {
@ -205,7 +205,7 @@ class PluginServices
template<typename T> template<typename T>
auto GetProperty(const std::string& key) const -> T { auto GetProperty(const std::string& key) const -> T {
if (PropertyExists(key)) { if (PropertyExists(key)) {
return fConfig->GetValue<T>(key); return fConfig.GetValue<T>(key);
} }
throw PropertyNotFoundError(fair::mq::tools::ToString("Config has no key: ", key)); throw PropertyNotFoundError(fair::mq::tools::ToString("Config has no key: ", key));
} }
@ -217,16 +217,16 @@ class PluginServices
/// If a type is not supported, the user can provide support by overloading the ostream operator for this type /// If a type is not supported, the user can provide support by overloading the ostream operator for this type
auto GetPropertyAsString(const std::string& key) const -> std::string { auto GetPropertyAsString(const std::string& key) const -> std::string {
if (PropertyExists(key)) { if (PropertyExists(key)) {
return fConfig->GetStringValue(key); return fConfig.GetStringValue(key);
} }
throw PropertyNotFoundError(fair::mq::tools::ToString("Config has no key: ", key)); throw PropertyNotFoundError(fair::mq::tools::ToString("Config has no key: ", key));
} }
auto GetChannelInfo() const -> std::unordered_map<std::string, int> { return fConfig->GetChannelInfo(); } auto GetChannelInfo() const -> std::unordered_map<std::string, int> { return fConfig.GetChannelInfo(); }
/// @brief Discover the list of property keys /// @brief Discover the list of property keys
/// @return list of property keys /// @return list of property keys
auto GetPropertyKeys() const -> std::vector<std::string> { return fConfig->GetPropertyKeys(); } auto GetPropertyKeys() const -> std::vector<std::string> { return fConfig.GetPropertyKeys(); }
/// @brief Subscribe to property updates of type T /// @brief Subscribe to property updates of type T
/// @param subscriber /// @param subscriber
@ -236,13 +236,13 @@ class PluginServices
template<typename T> template<typename T>
auto SubscribeToPropertyChange(const std::string& subscriber, std::function<void(const std::string& key, T)> callback) const -> void auto SubscribeToPropertyChange(const std::string& subscriber, std::function<void(const std::string& key, T)> callback) const -> void
{ {
fConfig->Subscribe<T>(subscriber, callback); fConfig.Subscribe<T>(subscriber, callback);
} }
/// @brief Unsubscribe from property updates of type T /// @brief Unsubscribe from property updates of type T
/// @param subscriber /// @param subscriber
template<typename T> template<typename T>
auto UnsubscribeFromPropertyChange(const std::string& subscriber) -> void { fConfig->Unsubscribe<T>(subscriber); } auto UnsubscribeFromPropertyChange(const std::string& subscriber) -> void { fConfig.Unsubscribe<T>(subscriber); }
/// @brief Subscribe to property updates /// @brief Subscribe to property updates
/// @param subscriber /// @param subscriber
@ -251,12 +251,12 @@ class PluginServices
/// Subscribe to property changes with a callback to monitor property changes in an event based fashion. Will convert the property to string. /// Subscribe to property changes with a callback to monitor property changes in an event based fashion. Will convert the property to string.
auto SubscribeToPropertyChangeAsString(const std::string& subscriber, std::function<void(const std::string& key, std::string)> callback) const -> void auto SubscribeToPropertyChangeAsString(const std::string& subscriber, std::function<void(const std::string& key, std::string)> callback) const -> void
{ {
fConfig->SubscribeAsString(subscriber, callback); fConfig.SubscribeAsString(subscriber, callback);
} }
/// @brief Unsubscribe from property updates that convert to string /// @brief Unsubscribe from property updates that convert to string
/// @param subscriber /// @param subscriber
auto UnsubscribeFromPropertyChangeAsString(const std::string& subscriber) -> void { fConfig->UnsubscribeAsString(subscriber); } auto UnsubscribeFromPropertyChangeAsString(const std::string& subscriber) -> void { fConfig.UnsubscribeAsString(subscriber); }
auto CycleLogConsoleSeverityUp() -> void { Logger::CycleConsoleSeverityUp(); } auto CycleLogConsoleSeverityUp() -> void { Logger::CycleConsoleSeverityUp(); }
auto CycleLogConsoleSeverityDown() -> void { Logger::CycleConsoleSeverityDown(); } auto CycleLogConsoleSeverityDown() -> void { Logger::CycleConsoleSeverityDown(); }
@ -271,7 +271,7 @@ class PluginServices
static const std::unordered_map<DeviceStateTransition, FairMQDevice::Event, tools::HashEnum<DeviceStateTransition>> fkDeviceStateTransitionMap; static const std::unordered_map<DeviceStateTransition, FairMQDevice::Event, tools::HashEnum<DeviceStateTransition>> fkDeviceStateTransitionMap;
private: private:
FairMQProgOptions* fConfig; // TODO make it a shared pointer, once old AliceO2 code is cleaned up FairMQProgOptions& fConfig;
FairMQDevice& fDevice; FairMQDevice& fDevice;
boost::optional<std::string> fDeviceController; boost::optional<std::string> fDeviceController;
mutable std::mutex fDeviceControllerMutex; mutable std::mutex fDeviceControllerMutex;

View File

@ -23,39 +23,39 @@ namespace mq
namespace test namespace test
{ {
inline auto control(std::shared_ptr<FairMQDevice> device) -> void inline auto control(FairMQDevice& device) -> void
{ {
for (const auto event : { for (const auto event : {
FairMQDevice::INIT_DEVICE, FairMQDevice::INIT_DEVICE,
FairMQDevice::RESET_DEVICE, FairMQDevice::RESET_DEVICE,
FairMQDevice::END, FairMQDevice::END,
}) { }) {
device->ChangeState(event); device.ChangeState(event);
if (event != FairMQDevice::END) device->WaitForEndOfState(event); if (event != FairMQDevice::END) device.WaitForEndOfState(event);
} }
} }
struct PluginServices : ::testing::Test { struct PluginServices : ::testing::Test {
PluginServices() PluginServices()
: mConfig() : mConfig()
, mDevice{std::make_shared<FairMQDevice>()} , mDevice()
, mServices{&mConfig, mDevice} , mServices(mConfig, mDevice)
, fRunStateMachineThread() , fRunStateMachineThread()
{ {
fRunStateMachineThread = std::thread(&FairMQDevice::RunStateMachine, mDevice.get()); fRunStateMachineThread = std::thread(&FairMQDevice::RunStateMachine, &mDevice);
mDevice->SetTransport("zeromq"); mDevice.SetTransport("zeromq");
} }
~PluginServices() ~PluginServices()
{ {
if (mDevice->GetCurrentState() == FairMQDevice::IDLE) control(mDevice); if (mDevice.GetCurrentState() == FairMQDevice::IDLE) control(mDevice);
if (fRunStateMachineThread.joinable()) { if (fRunStateMachineThread.joinable()) {
fRunStateMachineThread.join(); fRunStateMachineThread.join();
} }
} }
FairMQProgOptions mConfig; FairMQProgOptions mConfig;
std::shared_ptr<FairMQDevice> mDevice; FairMQDevice mDevice;
fair::mq::PluginServices mServices; fair::mq::PluginServices mServices;
std::thread fRunStateMachineThread; std::thread fRunStateMachineThread;
}; };

View File

@ -39,9 +39,9 @@ TEST_F(PluginServices, OnlySingleController)
EXPECT_EQ(mServices.GetDeviceController(), string{"foo"}); EXPECT_EQ(mServices.GetDeviceController(), string{"foo"});
// park device // park device
mDevice->WaitForEndOfState(FairMQDevice::DEVICE_READY); mDevice.WaitForEndOfState(FairMQDevice::DEVICE_READY);
mServices.ChangeDeviceState("foo", DeviceStateTransition::ResetDevice); mServices.ChangeDeviceState("foo", DeviceStateTransition::ResetDevice);
mDevice->WaitForEndOfState(FairMQDevice::RESET_DEVICE); mDevice.WaitForEndOfState(FairMQDevice::RESET_DEVICE);
mServices.ChangeDeviceState("foo", DeviceStateTransition::End); mServices.ChangeDeviceState("foo", DeviceStateTransition::End);
} }
@ -72,7 +72,7 @@ TEST_F(PluginServices, Control)
ASSERT_EQ(mServices.GetCurrentDeviceState(), DeviceState::DeviceReady); ASSERT_EQ(mServices.GetCurrentDeviceState(), DeviceState::DeviceReady);
mServices.ChangeDeviceState("foo", DeviceStateTransition::ResetDevice); mServices.ChangeDeviceState("foo", DeviceStateTransition::ResetDevice);
mDevice->WaitForEndOfState(FairMQDevice::RESET_DEVICE); mDevice.WaitForEndOfState(FairMQDevice::RESET_DEVICE);
mServices.ChangeDeviceState("foo", DeviceStateTransition::End); mServices.ChangeDeviceState("foo", DeviceStateTransition::End);
} }

View File

@ -24,31 +24,31 @@ namespace
using namespace std; using namespace std;
using namespace fair::mq; using namespace fair::mq;
auto control(shared_ptr<FairMQDevice> device) -> void auto control(FairMQDevice& device) -> void
{ {
device->SetTransport("zeromq"); device.SetTransport("zeromq");
for (const auto event : { for (const auto event : {
FairMQDevice::INIT_DEVICE, FairMQDevice::INIT_DEVICE,
FairMQDevice::RESET_DEVICE, FairMQDevice::RESET_DEVICE,
FairMQDevice::END, FairMQDevice::END,
}) { }) {
device->ChangeState(event); device.ChangeState(event);
if (event != FairMQDevice::END) device->WaitForEndOfState(event); if (event != FairMQDevice::END) device.WaitForEndOfState(event);
} }
} }
TEST(Plugin, Operators) TEST(Plugin, Operators)
{ {
FairMQProgOptions config; FairMQProgOptions config;
auto device = make_shared<FairMQDevice>(); FairMQDevice device;
PluginServices services{&config, device}; PluginServices services{config, device};
Plugin p1{"dds", {1, 0, 0}, "Foo Bar <foo.bar@test.net>", "https://git.test.net/dds.git", &services}; Plugin p1{"dds", {1, 0, 0}, "Foo Bar <foo.bar@test.net>", "https://git.test.net/dds.git", &services};
Plugin p2{"dds", {1, 0, 0}, "Foo Bar <foo.bar@test.net>", "https://git.test.net/dds.git", &services}; Plugin p2{"dds", {1, 0, 0}, "Foo Bar <foo.bar@test.net>", "https://git.test.net/dds.git", &services};
Plugin p3{"file", {1, 0, 0}, "Foo Bar <foo.bar@test.net>", "https://git.test.net/file.git", &services}; Plugin p3{"file", {1, 0, 0}, "Foo Bar <foo.bar@test.net>", "https://git.test.net/file.git", &services};
EXPECT_EQ(p1, p2); EXPECT_EQ(p1, p2);
EXPECT_NE(p1, p3); EXPECT_NE(p1, p3);
thread t(control, device); thread t(control, std::ref(device));
device->RunStateMachine(); device.RunStateMachine();
if (t.joinable()) { if (t.joinable()) {
t.join(); t.join();
} }
@ -57,14 +57,14 @@ TEST(Plugin, Operators)
TEST(Plugin, OstreamOperators) TEST(Plugin, OstreamOperators)
{ {
FairMQProgOptions config; FairMQProgOptions config;
auto device = make_shared<FairMQDevice>(); FairMQDevice device;
PluginServices services{&config, device}; PluginServices services{config, device};
Plugin p1{"dds", {1, 0, 0}, "Foo Bar <foo.bar@test.net>", "https://git.test.net/dds.git", &services}; Plugin p1{"dds", {1, 0, 0}, "Foo Bar <foo.bar@test.net>", "https://git.test.net/dds.git", &services};
stringstream ss; stringstream ss;
ss << p1; ss << p1;
EXPECT_EQ(ss.str(), string{"'dds', version '1.0.0', maintainer 'Foo Bar <foo.bar@test.net>', homepage 'https://git.test.net/dds.git'"}); EXPECT_EQ(ss.str(), string{"'dds', version '1.0.0', maintainer 'Foo Bar <foo.bar@test.net>', homepage 'https://git.test.net/dds.git'"});
thread t(control, device); thread t(control, std::ref(device));
device->RunStateMachine(); device.RunStateMachine();
if (t.joinable()) { if (t.joinable()) {
t.join(); t.join();
} }

View File

@ -25,25 +25,25 @@ using namespace boost::filesystem;
using namespace boost::program_options; using namespace boost::program_options;
using namespace std; using namespace std;
auto control(shared_ptr<FairMQDevice> device) -> void auto control(FairMQDevice& device) -> void
{ {
device->SetTransport("zeromq"); device.SetTransport("zeromq");
for (const auto event : { for (const auto event : {
FairMQDevice::INIT_DEVICE, FairMQDevice::INIT_DEVICE,
FairMQDevice::RESET_DEVICE, FairMQDevice::RESET_DEVICE,
FairMQDevice::END, FairMQDevice::END,
}) { }) {
device->ChangeState(event); device.ChangeState(event);
if (event != FairMQDevice::END) device->WaitForEndOfState(event); if (event != FairMQDevice::END) device.WaitForEndOfState(event);
} }
} }
TEST(PluginManager, LoadPluginDynamic) TEST(PluginManager, LoadPluginDynamic)
{ {
FairMQProgOptions config; FairMQProgOptions config;
FairMQDevice device;
PluginManager mgr; PluginManager mgr;
auto device = make_shared<FairMQDevice>(); mgr.EmplacePluginServices(config, device);
mgr.EmplacePluginServices(&config, device);
mgr.PrependSearchPath("./test"); mgr.PrependSearchPath("./test");
@ -63,8 +63,8 @@ TEST(PluginManager, LoadPluginDynamic)
mgr.ForEachPluginProgOptions([&count](const options_description& /*d*/){ ++count; }); mgr.ForEachPluginProgOptions([&count](const options_description& /*d*/){ ++count; });
ASSERT_EQ(count, 1); ASSERT_EQ(count, 1);
thread t(control, device); thread t(control, std::ref(device));
device->RunStateMachine(); device.RunStateMachine();
if (t.joinable()) { if (t.joinable()) {
t.join(); t.join();
} }
@ -72,16 +72,16 @@ TEST(PluginManager, LoadPluginDynamic)
TEST(PluginManager, LoadPluginStatic) TEST(PluginManager, LoadPluginStatic)
{ {
FairMQDevice device;
PluginManager mgr; PluginManager mgr;
auto device = make_shared<FairMQDevice>(); device.SetTransport("zeromq");
device->SetTransport("zeromq");
ASSERT_NO_THROW(mgr.LoadPlugin("s:control")); ASSERT_NO_THROW(mgr.LoadPlugin("s:control"));
FairMQProgOptions config; FairMQProgOptions config;
config.SetValue<string>("control", "static"); config.SetValue<string>("control", "static");
config.SetValue("catch-signals", 0); config.SetValue("catch-signals", 0);
mgr.EmplacePluginServices(&config, device); mgr.EmplacePluginServices(config, device);
ASSERT_NO_THROW(mgr.InstantiatePlugins()); ASSERT_NO_THROW(mgr.InstantiatePlugins());
@ -96,7 +96,7 @@ TEST(PluginManager, LoadPluginStatic)
mgr.ForEachPluginProgOptions([&count](const options_description&){ ++count; }); mgr.ForEachPluginProgOptions([&count](const options_description&){ ++count; });
ASSERT_EQ(count, 1); ASSERT_EQ(count, 1);
device->RunStateMachine(); device.RunStateMachine();
mgr.WaitForPluginsToReleaseDeviceControl(); mgr.WaitForPluginsToReleaseDeviceControl();
} }