Skip to content

Commit

Permalink
Re-introduce the Action class, allowing for modules to be targeted by
Browse files Browse the repository at this point in the history
UID by an ActionStep in an ActionPlan.
  • Loading branch information
eflumerf committed Aug 27, 2024
1 parent 5665ce2 commit 98208e9
Show file tree
Hide file tree
Showing 6 changed files with 168 additions and 38 deletions.
10 changes: 10 additions & 0 deletions include/appfwk/Issues.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,16 @@ ERS_DECLARE_ISSUE(appfwk,
ERS_DECLARE_ISSUE(appfwk, InvalidConfigurationURI, "Cannot get a configuration using URI " << uri, ((std::string)uri))

ERS_DECLARE_ISSUE(appfwk, ConfigurationRetreival, "Failed to retrieve configuration: " << uri, ((std::string)uri))

ERS_DECLARE_ISSUE(appfwk,
ActionPlanNotFound,
"No action plan found for command " << cmd << ", taking the following action: " << message,
((std::string)cmd)((std::string)message))

ERS_DECLARE_ISSUE(appfwk,
ActionPlanValidationFailed,
"Error validating action plan " << cmd << ", module " << module << ": " << message,
((std::string)cmd)((std::string)module)((std::string)message))
// Re-enable coverage collection LCOV_EXCL_STOP
} // namespace dunedaq

Expand Down
33 changes: 26 additions & 7 deletions src/DAQModuleManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "appfwk/DAQModule.hpp"

#include "confmodel/ActionStep.hpp"
#include "confmodel/Action.hpp"
#include "confmodel/Session.hpp"

#include "iomanager/IOManager.hpp"
Expand Down Expand Up @@ -54,10 +55,26 @@ DAQModuleManager::initialize(std::shared_ptr<ConfigurationManager> cfgMgr, opmon
auto cmd = plan_pair.first;

for (auto& step : plan_pair.second->get_steps()) {
for (auto& mod_type : step->get_modules()) {
for (auto& action : step->get_actions()) {
auto mod_type = action->get_module_class();
if (!m_modules_by_type.count(mod_type) || m_modules_by_type[mod_type].size() == 0) {
throw ActionPlanValidationFailed(ERS_HERE, cmd, mod_type, "Module does not exist");
}

auto mod_name = action->get_module_id();
if (mod_name != "*") {
bool match = false;
for (auto& mod_id : m_modules_by_type[mod_type]) {
if (mod_id == mod_name) {
match = true;
break;
}
}
if (!match) {
throw ActionPlanValidationFailed(ERS_HERE, cmd, mod_type, "No module with id " + mod_name + " found.");
}
}

auto module_test = m_module_map[m_modules_by_type[mod_type][0]];
if (!module_test->has_command(cmd)) {
throw ActionPlanValidationFailed(ERS_HERE, cmd, mod_type, "Module does not have method " + cmd);
Expand Down Expand Up @@ -140,14 +157,16 @@ DAQModuleManager::execute_action_plan_step(std::string const& cmd,
std::string failed_mod_names("");
std::unordered_map<std::string, std::future<bool>> futures;

for (auto& mod_class : step->get_modules()) {
for (auto& action : step->get_actions()) {
auto mod_class = action->get_module_class();
auto modules = m_modules_by_type[mod_class];
for (auto& mod_name : modules) {

auto data_obj = get_dataobj_for_module(mod_name, cmd_data);
TLOG_DEBUG(1) << "Executing action " << cmd << " on module " << mod_name << " (class " << mod_class << ")";
futures[mod_name] =
std::async(std::launch::async, &DAQModuleManager::execute_action, this, mod_name, cmd, data_obj);
if (mod_name == action->get_module_id() || action->get_module_id() == "*") {
auto data_obj = get_dataobj_for_module(mod_name, cmd_data);
TLOG_DEBUG(1) << "Executing action " << cmd << " on module " << mod_name << " (class " << mod_class << ")";
futures[mod_name] =
std::async(std::launch::async, &DAQModuleManager::execute_action, this, mod_name, cmd, data_obj);
}
}
}

Expand Down
9 changes: 0 additions & 9 deletions src/DAQModuleManager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,15 +68,6 @@ ERS_DECLARE_ISSUE_BASE(appfwk,
((std::string)message) ///< This class params
)

ERS_DECLARE_ISSUE(appfwk,
ActionPlanNotFound,
"No action plan found for command " << cmd << ", taking the following action: " << message,
((std::string)cmd)((std::string)message))

ERS_DECLARE_ISSUE(appfwk,
ActionPlanValidationFailed,
"Error validating action plan " << cmd << ", module " << module << ": " << message,
((std::string)cmd)((std::string)module)((std::string)message))
// Re-enable coverage collection LCOV_EXCL_STOP

namespace appfwk {
Expand Down
19 changes: 15 additions & 4 deletions src/ModuleConfiguration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
*/

#include "appfwk/ModuleConfiguration.hpp"
#include "appfwk/Issues.hpp"
#include "appmodel/SmartDaqApplication.hpp"
#include "conffwk/Configuration.hpp"
#include "confmodel/DaqApplication.hpp"
Expand Down Expand Up @@ -41,17 +42,27 @@ ModuleConfiguration::ModuleConfiguration(std::shared_ptr<ConfigurationManager> c
m_modules = smartDaqApp->generate_modules(confdb.get(), oksFile, session);

for (auto& plan : smartDaqApp->get_action_plans()) {
TLOG_DBG(6) << "Registering action plan " << plan->UID() << " for cmd " << plan->get_fsm()->get_cmd();
m_action_plans[plan->get_fsm()->get_cmd()] = plan;
auto cmd = plan->get_fsm()->get_cmd();
TLOG_DBG(6) << "Registering action plan " << plan->UID() << " for cmd " << cmd;
if (m_action_plans.count(cmd)) {
throw ActionPlanValidationFailed(
ERS_HERE, cmd,"N/A", "Multiple ActionPlans registered for cmd, conflicting plan is " + plan->UID());
}
m_action_plans[cmd] = plan;
}
} else {
auto daqApp = application->cast<confmodel::DaqApplication>();
if (daqApp) {
m_modules = daqApp->get_modules();

for (auto& plan : daqApp->get_action_plans()) {
TLOG_DBG(6) << "Registering action plan " << plan->UID() << " for cmd " << plan->get_fsm()->get_cmd();
m_action_plans[plan->get_fsm()->get_cmd()] = plan;
auto cmd = plan->get_fsm()->get_cmd();
TLOG_DBG(6) << "Registering action plan " << plan->UID() << " for cmd " << cmd;
if (m_action_plans.count(cmd)) {
throw ActionPlanValidationFailed(
ERS_HERE, cmd, "N/A", "Multiple ActionPlans registered for cmd, conflicting plan is " + plan->UID());
}
m_action_plans[cmd] = plan;
}
} else {
throw(NotADaqApplication(ERS_HERE, application->UID()));
Expand Down
96 changes: 79 additions & 17 deletions test/config/appfwk.data.xml
Original file line number Diff line number Diff line change
Expand Up @@ -96,43 +96,67 @@
<attr name="optional" type="bool" val="0"/>
</obj>

<obj class="Action" id="all_DummyModules_action">
<attr name="module_class" type="class" val="DummyModule"/>
<attr name="module_id" type="string" val="*"/>
</obj>

<obj class="Action" id="dummyModule_0_action">
<attr name="module_class" type="class" val="DummyModule"/>
<attr name="module_id" type="string" val="dummy_module_0"/>
</obj>

<obj class="Action" id="dummyModule_1_action">
<attr name="module_class" type="class" val="DummyModule"/>
<attr name="module_id" type="string" val="dummy_module_1"/>
</obj>

<obj class="ActionPlan" id="bad_action">
<rel name="fsm" class="FSMCommand" id="bad_action"/>
<rel name="steps">
<ref class="ActionStep" id="bad_action_step_1"/>
<ref class="ActionStep" id="run_on_all_dummymodules_step"/>
</rel>
</obj>

<obj class="ActionPlan" id="bad_stuff">
<rel name="fsm" class="FSMCommand" id="bad_stuff"/>
<rel name="steps">
<ref class="ActionStep" id="bad_stuff_step_1"/>
<ref class="ActionStep" id="run_on_all_dummymodules_step"/>
</rel>
</obj>

<obj class="ActionPlan" id="bad_stuff_conflict">
<rel name="fsm" class="FSMCommand" id="bad_stuff"/>
<rel name="steps">
<ref class="ActionStep" id="run_on_all_dummymodules_step"/>
</rel>
</obj>

<obj class="ActionPlan" id="stuff_targeted">
<rel name="fsm" class="FSMCommand" id="stuff"/>
<rel name="steps">
<ref class="ActionStep" id="run_on_both_dummymodules_step"/>
</rel>
</obj>

<obj class="ActionPlan" id="stuff">
<rel name="fsm" class="FSMCommand" id="stuff"/>
<rel name="steps">
<ref class="ActionStep" id="stuff_step_1"/>
<ref class="ActionStep" id="run_on_all_dummymodules_step"/>
</rel>
</obj>

<obj class="ActionStep" id="bad_action_step_1">
<attr name="modules" type="class">
<data val="DummyModule"/>
</attr>
</obj>

<obj class="ActionStep" id="bad_stuff_step_1">
<attr name="modules" type="class">
<data val="DummyModule"/>
</attr>
<obj class="ActionStep" id="run_on_all_dummymodules_step">
<rel name="actions">
<ref class="Action" id="all_DummyModules_action"/>
</rel>
</obj>

<obj class="ActionStep" id="stuff_step_1">
<attr name="modules" type="class">
<data val="DummyModule"/>
</attr>
<obj class="ActionStep" id="run_on_both_dummymodules_step">
<rel name="actions">
<ref class="Action" id="dummyModule_0_action"/>
<ref class="Action" id="dummyModule_1_action"/>
</rel>
</obj>

<obj class="DaqApplication" id="MissingMethodApp">
Expand All @@ -146,13 +170,36 @@
</rel>
</obj>

<obj class="DaqApplication" id="ConflictingActionPlansApp">
<attr name="application_name" type="string" val="daq_application"/>
<rel name="runs_on" class="VirtualHost" id="vlocalhost"/>
<rel name="modules">
<ref class="DummyModule" id="dummy_module_0"/>
</rel>
<rel name="action_plans">
<ref class="ActionPlan" id="bad_stuff"/>
<ref class="ActionPlan" id="bad_stuff_conflict"/>
</rel>
</obj>

<obj class="DaqApplication" id="MissingModuleApp">
<attr name="application_name" type="string" val="daq_application"/>
<rel name="runs_on" class="VirtualHost" id="vlocalhost"/>
<rel name="action_plans">
<ref class="ActionPlan" id="stuff"/>
</rel>
</obj>

<obj class="DaqApplication" id="MissingModuleApp_TargetedAction">
<attr name="application_name" type="string" val="daq_application"/>
<rel name="runs_on" class="VirtualHost" id="vlocalhost"/>
<rel name="action_plans">
<ref class="ActionPlan" id="stuff_targeted"/>
</rel>
<rel name="modules">
<ref class="DummyModule" id="dummy_module_0"/>
</rel>
</obj>

<obj class="DaqApplication" id="TestApp">
<attr name="application_name" type="string" val="daq_application"/>
Expand All @@ -165,8 +212,23 @@
<ref class="ActionPlan" id="bad_stuff"/>
</rel>
</obj>

<obj class="DaqApplication" id="TestApp_TargetedAction">
<attr name="application_name" type="string" val="daq_application"/>
<rel name="runs_on" class="VirtualHost" id="vlocalhost"/>
<rel name="modules">
<ref class="DummyModule" id="dummy_module_0"/>
<ref class="DummyModule" id="dummy_module_1"/>
</rel>
<rel name="action_plans">
<ref class="ActionPlan" id="stuff_targeted"/>
<ref class="ActionPlan" id="bad_stuff"/>
</rel>
</obj>

<obj class="DummyModule" id="dummy_module_0">
</obj>
<obj class="DummyModule" id="dummy_module_1">
</obj>

</oks-data>
39 changes: 38 additions & 1 deletion unittest/DAQModuleManager_test.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -125,11 +125,26 @@ BOOST_AUTO_TEST_CASE(InvalidActionPlan)
BOOST_REQUIRE_EXCEPTION(
mgr.initialize(cfgMgr, opmgr), ActionPlanValidationFailed, [&](ActionPlanValidationFailed) { return true; });

dunedaq::opmonlib::TestOpMonManager opmgr2;
dunedaq::get_iomanager()->reset();
appName = "MissingMethodApp";
cfgMgr = std::make_shared<dunedaq::appfwk::ConfigurationManager>(oksConfig, appName, sessionName);
BOOST_REQUIRE_EXCEPTION(
mgr.initialize(cfgMgr, opmgr), ActionPlanValidationFailed, [&](ActionPlanValidationFailed) { return true; });
mgr.initialize(cfgMgr, opmgr2), ActionPlanValidationFailed, [&](ActionPlanValidationFailed) { return true; });

dunedaq::opmonlib::TestOpMonManager opmgr3;
dunedaq::get_iomanager()->reset();
appName = "ConflictingActionPlansApp";
cfgMgr = std::make_shared<dunedaq::appfwk::ConfigurationManager>(oksConfig, appName, sessionName);
BOOST_REQUIRE_EXCEPTION(
mgr.initialize(cfgMgr, opmgr3), ActionPlanValidationFailed, [&](ActionPlanValidationFailed) { return true; });

dunedaq::opmonlib::TestOpMonManager opmgr4;
dunedaq::get_iomanager()->reset();
appName = "MissingModuleApp_TargetedAction";
cfgMgr = std::make_shared<dunedaq::appfwk::ConfigurationManager>(oksConfig, appName, sessionName);
BOOST_REQUIRE_EXCEPTION(
mgr.initialize(cfgMgr, opmgr4), ActionPlanValidationFailed, [&](ActionPlanValidationFailed) { return true; });
}

BOOST_AUTO_TEST_CASE(CommandModules)
Expand All @@ -148,7 +163,29 @@ BOOST_AUTO_TEST_CASE(CommandModules)

BOOST_REQUIRE_EXCEPTION(
mgr.execute("bad_stuff", cmd_data), CommandDispatchingFailed, [&](CommandDispatchingFailed) { return true; });
}

BOOST_AUTO_TEST_CASE(CommandModules_Targeted)
{

dunedaq::get_iomanager()->reset();
auto mgr = DAQModuleManager();
BOOST_REQUIRE_EQUAL(mgr.initialized(), false);

std::string oksConfig = "oksconflibs:test/config/appSession.data.xml";
std::string appName = "TestApp_TargetedAction";
std::string sessionName = "test-session";

dunedaq::opmonlib::TestOpMonManager opmgr;
auto cfgMgr = make_config_mgr();
mgr.initialize(cfgMgr, opmgr);

BOOST_REQUIRE_EQUAL(mgr.initialized(), true);
nlohmann::json cmd_data;
mgr.execute("stuff", cmd_data);

BOOST_REQUIRE_EXCEPTION(
mgr.execute("bad_stuff", cmd_data), CommandDispatchingFailed, [&](CommandDispatchingFailed) { return true; });
}

BOOST_AUTO_TEST_CASE(CommandMatchingModules)
Expand Down

0 comments on commit 98208e9

Please sign in to comment.