1 #include "otsdaq-core/ConfigurationPluginDataFormats/XDAQContextConfiguration.h"
2 #include "otsdaq-core/Macros/ConfigurationPluginMacros.h"
3 #include "otsdaq-core/ConfigurationInterface/ConfigurationManager.h"
12 #define XDAQ_RUN_FILE std::string(getenv("XDAQ_CONFIGURATION_DATA_PATH")) + "/" + std::string(getenv("XDAQ_CONFIGURATION_XML")) + ".xml"
13 #define APP_PRIORITY_FILE std::string(getenv("XDAQ_CONFIGURATION_DATA_PATH")) + "/" + "xdaqAppStateMachinePriority"
18 const std::string XDAQContextConfiguration::DEPRECATED_SUPERVISOR_CLASS =
"ots::Supervisor";
19 const std::string XDAQContextConfiguration::GATEWAY_SUPERVISOR_CLASS =
"ots::GatewaySupervisor";
20 const std::string XDAQContextConfiguration::WIZARD_SUPERVISOR_CLASS =
"ots::WizardSupervisor";
21 const std::set<std::string> XDAQContextConfiguration::FETypeClassNames_ = {
"ots::FESupervisor",
"ots::FEDataManagerSupervisor",
"ots::ARTDAQFEDataManagerSupervisor"};
22 const std::set<std::string> XDAQContextConfiguration::DMTypeClassNames_ = {
"ots::DataManagerSupervisor",
"ots::FEDataManagerSupervisor",
"ots::ARTDAQFEDataManagerSupervisor"};
23 const std::set<std::string> XDAQContextConfiguration::LogbookTypeClassNames_ = {
"ots::LogbookSupervisor"};
24 const std::set<std::string> XDAQContextConfiguration::MacroMakerTypeClassNames_ = {
"ots::MacroMakerSupervisor"};
25 const std::set<std::string> XDAQContextConfiguration::ChatTypeClassNames_ = {
"ots::ChatSupervisor"};
26 const std::set<std::string> XDAQContextConfiguration::ConsoleTypeClassNames_ = {
"ots::ConsoleSupervisor"};
27 const std::set<std::string> XDAQContextConfiguration::ConfigurationGUITypeClassNames_ = {
"ots::ConfigurationGUISupervisor"};
29 const std::string XDAQContextConfiguration::ARTDAQ_OFFSET_PORT =
"OffsetPort";
32 XDAQContextConfiguration::XDAQContextConfiguration(
void)
60 XDAQContextConfiguration::~XDAQContextConfiguration(
void)
66 extractContexts(configManager);
72 fs.open(XDAQ_RUN_FILE, std::fstream::out | std::fstream::trunc);
75 __SS__ <<
"Failed to open XDAQ run file: " << XDAQ_RUN_FILE << std::endl;
76 throw std::runtime_error(ss.str());
78 outputXDAQXML((std::ostream &)fs);
85 bool XDAQContextConfiguration::isARTDAQContext(
const std::string &contextUID)
87 return (contextUID.find(
"ART") == 0 ||
88 contextUID.find(
"ARTDAQ") == 0);
98 unsigned int XDAQContextConfiguration::getARTDAQAppRank(
const std::string &contextUID)
const
103 if (artdaqBoardReaders_.size() == 0 &&
104 artdaqEventBuilders_.size() == 0 &&
105 artdaqAggregators_.size() == 0)
107 __COUT_WARN__ <<
"Assuming since there are 0 active ARTDAQ context UID(s), we can ignore rank failure." << std::endl;
112 auto localGetRank = [](
const XDAQContext& context) ->
unsigned int {
113 if(context.applications_.size() != 1)
115 __SS__ <<
"Invalid number of ARTDAQ applications in context '" <<
116 context.contextUID_ <<
117 ".' Must be 1. Currently is " << context.applications_.size() <<
"." << __E__;
121 return context.applications_[0].id_;
125 for (
auto &i : artdaqBoardReaders_)
126 if (contexts_[i].contextUID_ == contextUID)
127 return localGetRank(contexts_[i]);
129 for (
auto &i : artdaqEventBuilders_)
130 if (contexts_[i].contextUID_ == contextUID)
131 return localGetRank(contexts_[i]);
133 for (
auto &i : artdaqAggregators_)
134 if (contexts_[i].contextUID_ == contextUID)
135 return localGetRank(contexts_[i]);
142 __SS__ <<
"ARTDAQ rank could not be found for context UID '" <<
143 contextUID <<
".'" << std::endl;
148 std::string XDAQContextConfiguration::getContextAddress(
const std::string &contextUID,
bool wantHttp)
const
150 if (contextUID ==
"X")
return "";
151 for (
auto& context : contexts_)
153 if (context.contextUID_ == contextUID)
155 if (wantHttp)
return context.address_;
156 auto address = context.address_;
157 if (address.find(
"http://") == 0) { address = address.replace(0,7,
""); }
158 if (address.find(
"https://") == 0) { address = address.replace(0,8,
""); }
165 unsigned int XDAQContextConfiguration::getARTDAQDataPort(
const ConfigurationManager *configManager,
166 const std::string &contextUID)
const
168 if (contextUID ==
"X")
return 0;
169 for (
auto& context : contexts_)
171 if (context.contextUID_ == contextUID)
173 if(context.applications_.size() != 1)
175 __SS__ <<
"Invalid number of ARTDAQ applications in context '" <<
177 ".' Must be 1. Currently is " << context.applications_.size() <<
"." << __E__;
181 if(context.applications_[0].class_ ==
"ots::ARTDAQDataManagerSupervisor")
183 auto processors = getSupervisorConfigNode(configManager,
184 context.contextUID_, context.applications_[0].applicationUID_).getNode(
185 "LinkToDataManagerConfiguration").getChildren()[0].second.getNode(
186 "LinkToDataBufferConfiguration").getChildren();
188 std::string processorType;
191 for(
auto& processor : processors)
193 processorType = processor.second.getNode(
194 "ProcessorPluginName").getValue<std::string>();
195 __COUTV__(processorType);
197 if(processorType ==
"ARTDAQConsumer" ||
198 processorType ==
"ARTDAQProducer")
199 return processor.second.getNode(
200 "LinkToProcessorConfiguration").getNode(
201 XDAQContextConfiguration::ARTDAQ_OFFSET_PORT).getValue<
unsigned int>();
204 __SS__ <<
"No ARTDAQ processor was found while looking for data port." << __E__;
208 return getSupervisorConfigNode(configManager,
209 context.contextUID_, context.applications_[0].applicationUID_).getNode(
210 XDAQContextConfiguration::ARTDAQ_OFFSET_PORT).getValue<
unsigned int>();
218 std::vector<const XDAQContextConfiguration::XDAQContext *> XDAQContextConfiguration::getBoardReaderContexts()
const
220 std::vector<const XDAQContext *> retVec;
221 for (
auto &i : artdaqBoardReaders_)
222 retVec.push_back(&contexts_[i]);
226 std::vector<const XDAQContextConfiguration::XDAQContext *> XDAQContextConfiguration::getEventBuilderContexts()
const
228 std::vector<const XDAQContext *> retVec;
229 for (
auto &i : artdaqEventBuilders_)
230 retVec.push_back(&contexts_[i]);
235 std::vector<const XDAQContextConfiguration::XDAQContext *> XDAQContextConfiguration::getAggregatorContexts()
const
237 std::vector<const XDAQContext *> retVec;
238 for (
auto &i : artdaqAggregators_)
239 retVec.push_back(&contexts_[i]);
245 const std::string &contextUID)
const
247 return configManager->__SELF_NODE__.getNode(
253 const std::string &contextUID,
const std::string &appUID)
const
255 return configManager->__SELF_NODE__.getNode(
257 colContext_.colLinkToApplicationConfiguration_ +
"/" +
263 const std::string &contextUID,
const std::string &appUID)
const
265 return configManager->__SELF_NODE__.getNode(
267 colContext_.colLinkToApplicationConfiguration_ +
"/" +
269 colApplication_.colLinkToSupervisorConfiguration_);
285 auto children = configManager->__SELF_NODE__.getChildren();
290 artdaqBoardReaders_.clear();
291 artdaqEventBuilders_.clear();
292 artdaqAggregators_.clear();
296 std::set<
unsigned int > appIdSet;
298 for (
auto &child : children)
300 contexts_.push_back(XDAQContext());
304 contexts_.back().contextUID_ = child.first;
306 contexts_.back().sourceConfig_ = child.second.getConfigurationName() +
"_v" +
307 child.second.getConfigurationVersion().toString() +
" @ " +
308 std::to_string(child.second.getConfigurationCreationTime());
309 child.second.getNode(colContext_.colContextUID_).getValue(contexts_.back().contextUID_);
310 child.second.getNode(colContext_.colStatus_).getValue(contexts_.back().status_);
311 child.second.getNode(colContext_.colId_).getValue(contexts_.back().id_);
312 child.second.getNode(colContext_.colAddress_).getValue(contexts_.back().address_);
313 child.second.getNode(colContext_.colPort_).getValue(contexts_.back().port_);
317 auto appLink = child.second.getNode(colContext_.colLinkToApplicationConfiguration_);
318 if (appLink.isDisconnected())
320 __SS__ <<
"Application link is disconnected!" << std::endl;
321 throw std::runtime_error(ss.str());
325 auto appChildren = appLink.getChildren();
326 for (
auto appChild : appChildren)
330 contexts_.back().applications_.push_back(XDAQApplication());
332 contexts_.back().applications_.back().applicationGroupID_ = child.first;
333 contexts_.back().applications_.back().sourceConfig_ = appChild.second.getConfigurationName() +
"_v" +
334 appChild.second.getConfigurationVersion().toString() +
" @ " +
335 std::to_string(appChild.second.getConfigurationCreationTime());
337 appChild.second.getNode(colApplication_.colApplicationUID_).getValue(contexts_.back().applications_.back().applicationUID_);
338 appChild.second.getNode(colApplication_.colStatus_).getValue(contexts_.back().applications_.back().status_);
339 appChild.second.getNode(colApplication_.colClass_).getValue(contexts_.back().applications_.back().class_);
340 appChild.second.getNode(colApplication_.colId_).getValue(contexts_.back().applications_.back().id_);
343 if((contexts_.back().applications_.back().id_ == 200 &&
344 contexts_.back().applications_.back().class_ != XDAQContextConfiguration::GATEWAY_SUPERVISOR_CLASS &&
345 contexts_.back().applications_.back().class_ != XDAQContextConfiguration::DEPRECATED_SUPERVISOR_CLASS) ||
346 (contexts_.back().applications_.back().id_ != 200 &&
347 (contexts_.back().applications_.back().class_ == XDAQContextConfiguration::GATEWAY_SUPERVISOR_CLASS ||
348 contexts_.back().applications_.back().class_ == XDAQContextConfiguration::DEPRECATED_SUPERVISOR_CLASS)))
350 __SS__ <<
"XDAQ Application ID of 200 is reserved for the Gateway Supervisor " <<
351 XDAQContextConfiguration::GATEWAY_SUPERVISOR_CLASS <<
". Conflict specifically at id=" <<
352 contexts_.back().applications_.back().id_ <<
" appName=" <<
353 contexts_.back().applications_.back().applicationUID_ << std::endl;
358 if(contexts_.back().status_ && contexts_.back().applications_.back().status_)
361 if(appIdSet.find(contexts_.back().applications_.back().id_) != appIdSet.end())
363 __SS__ <<
"XDAQ Application IDs are not unique. Specifically at id=" <<
364 contexts_.back().applications_.back().id_ <<
" appName=" <<
365 contexts_.back().applications_.back().applicationUID_ << std::endl;
366 __COUT_ERR__ <<
"\n" << ss.str();
367 throw std::runtime_error(ss.str());
369 appIdSet.insert(contexts_.back().applications_.back().id_);
373 if (appChild.second.getNode(colApplication_.colInstance_).isDefaultValue())
374 contexts_.back().applications_.back().instance_ = 1;
376 appChild.second.getNode(colApplication_.colInstance_).getValue(contexts_.back().applications_.back().instance_);
378 if (appChild.second.getNode(colApplication_.colNetwork_).isDefaultValue())
379 contexts_.back().applications_.back().network_ =
"local";
381 appChild.second.getNode(colApplication_.colNetwork_).getValue(contexts_.back().applications_.back().network_);
383 if (appChild.second.getNode(colApplication_.colGroup_).isDefaultValue())
384 contexts_.back().applications_.back().group_ =
"daq";
386 appChild.second.getNode(colApplication_.colGroup_).getValue(contexts_.back().applications_.back().group_);
388 appChild.second.getNode(colApplication_.colModule_).getValue(contexts_.back().applications_.back().module_);
392 appChild.second.getNode(colApplication_.colConfigurePriority_).getValue(contexts_.back().applications_.back().stateMachineCommandPriority_[
"Configure"]);
393 appChild.second.getNode(colApplication_.colStartPriority_).getValue(contexts_.back().applications_.back().stateMachineCommandPriority_[
"Start"]);
394 appChild.second.getNode(colApplication_.colStopPriority_).getValue(contexts_.back().applications_.back().stateMachineCommandPriority_[
"Stop"]);
398 __COUT__ <<
"Ignoring missing state machine priorities..." << __E__;
402 auto appPropertyLink = appChild.second.getNode(colApplication_.colLinkToPropertyConfiguration_);
403 if (!appPropertyLink.isDisconnected())
407 auto appPropertyChildren = appPropertyLink.getChildren();
411 for (
auto appPropertyChild : appPropertyChildren)
413 contexts_.back().applications_.back().properties_.push_back(XDAQApplicationProperty());
414 contexts_.back().applications_.back().properties_.back().status_ =
415 appPropertyChild.second.getNode(colAppProperty_.colStatus_).getValue<
bool>();
416 contexts_.back().applications_.back().properties_.back().name_ =
417 appPropertyChild.second.getNode(colAppProperty_.colPropertyName_).getValue<std::string>();
418 contexts_.back().applications_.back().properties_.back().type_ =
419 appPropertyChild.second.getNode(colAppProperty_.colPropertyType_).getValue<std::string>();
420 contexts_.back().applications_.back().properties_.back().value_ =
421 appPropertyChild.second.getNode(colAppProperty_.colPropertyValue_).getValue<std::string>();
431 if (isARTDAQContext(contexts_.back().contextUID_))
435 if (contexts_.back().applications_.size() != 1)
437 __SS__ <<
"ARTDAQ Context '" << contexts_.back().contextUID_ <<
438 "' must have one Application! " <<
439 contexts_.back().applications_.size() <<
" were found. " << std::endl;
440 throw std::runtime_error(ss.str());
443 if (!contexts_.back().status_)
continue;
445 if (contexts_.back().applications_[0].class_ ==
446 "ots::ARTDAQDataManagerSupervisor")
447 artdaqBoardReaders_.push_back(contexts_.size() - 1);
448 else if (contexts_.back().applications_[0].class_ ==
449 "ots::EventBuilderApp")
450 artdaqEventBuilders_.push_back(contexts_.size() - 1);
451 else if (contexts_.back().applications_[0].class_ ==
452 "ots::DataLoggerApp" ||
453 contexts_.back().applications_[0].class_ ==
454 "ots::DispatcherApp")
455 artdaqAggregators_.push_back(contexts_.size() - 1);
458 __SS__ <<
"ARTDAQ Context must be have Application of an allowed class type:\n " <<
459 "\tots::ARTDAQDataManagerSupervisor\n" <<
460 "\tots::EventBuilderApp\n" <<
461 "\tots::DataLoggerApp\n" <<
462 "\tots::DispatcherApp\n" <<
463 "\nClass found was " <<
464 contexts_.back().applications_[0].class_ << std::endl;
465 throw std::runtime_error(ss.str());
695 void XDAQContextConfiguration::outputXDAQXML(std::ostream &out)
704 out <<
"<?xml version='1.0'?>\n" <<
705 "<xc:Partition \txmlns:xsi\t= \"http://www.w3.org/2001/XMLSchema-instance\"\n" <<
706 "\t\txmlns:soapenc\t= \"http://schemas.xmlsoap.org/soap/encoding/\"\n" <<
707 "\t\txmlns:xc\t= \"http://xdaq.web.cern.ch/xdaq/xsd/2004/XMLConfiguration-30\">\n\n";
719 for (XDAQContext &context : contexts_)
724 sprintf(tmp,
"\t<!-- ContextUID='%s' sourceConfig='%s' -->",
725 context.contextUID_.c_str(), context.sourceConfig_.c_str());
728 if (!context.status_)
731 sprintf(tmp,
"\t<xc:Context id=\"%u\" url=\"%s:%u\">", context.id_, context.address_.c_str(), context.port_);
732 out << tmp <<
"\n\n";
734 for (XDAQApplication &app : context.applications_)
741 sprintf(tmp,
"\t\t<!-- Application GroupID = '%s' UID='%s' sourceConfig='%s' -->",
742 app.applicationGroupID_.c_str(), app.applicationUID_.c_str(), app.sourceConfig_.c_str());
749 sprintf(tmp,
"\t\t<xc:Application class=\"%s\" id=\"%u\" instance=\"%u\" network=\"%s\" group=\"%s\">\n",
750 app.class_.c_str(), app.id_, app.instance_, app.network_.c_str(), app.group_.c_str());
754 int foundColon = app.class_.rfind(
':');
755 if (foundColon >= 0) ++foundColon;
758 __SS__ <<
"Illegal XDAQApplication class name value of '" << app.class_
759 <<
"' - please check the entry for app ID = " << app.id_ << __E__;
760 throw std::runtime_error(ss.str());
762 out <<
"\t\t\t<properties xmlns=\"urn:xdaq-application:" <<
763 app.class_.substr(foundColon) <<
764 "\" xsi:type=\"soapenc:Struct\">\n";
767 for (XDAQApplicationProperty &appProperty : app.properties_)
770 if (appProperty.type_ ==
"ots::SupervisorProperty")
continue;
772 if (!appProperty.status_)
773 out <<
"\t\t\t\t<!--\n";
775 sprintf(tmp,
"\t\t\t\t<%s xsi:type=\"%s\">%s</%s>\n",
776 appProperty.name_.c_str(),
777 appProperty.type_.c_str(),
778 appProperty.value_.c_str(),
779 appProperty.name_.c_str());
782 if (!appProperty.status_)
783 out <<
"\t\t\t\t-->\n";
785 out <<
"\t\t\t</properties>\n";
788 out <<
"\t\t</xc:Application>\n";
791 sprintf(tmp,
"\t\t<xc:Module>%s</xc:Module>\n", app.module_.c_str());
794 if (context.status_ && !app.status_)
801 out <<
"\t</xc:Context>\n";
802 if (!context.status_)
808 out <<
"</xc:Partition>\n\n\n";
813 std::string XDAQContextConfiguration::getContextUID(
const std::string &url)
const
815 for (
auto context : contexts_)
817 if (!context.status_)
continue;
819 if (url == context.address_ +
":" + std::to_string(context.port_))
820 return context.contextUID_;
826 std::string XDAQContextConfiguration::getApplicationUID(
const std::string &url,
unsigned int id)
const
829 for (
auto context : contexts_)
835 if (!context.status_)
continue;
838 if (url == context.address_ +
":" + std::to_string(context.port_))
839 for (
auto application : context.applications_)
842 if (!application.status_)
continue;
844 if (application.id_ ==
id)
846 return application.applicationUID_;