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(appIdSet.find(contexts_.back().applications_.back().id_) != appIdSet.end())
345 __SS__ <<
"XDAQ Application IDs are not unique. Specifically at id=" <<
346 contexts_.back().applications_.back().id_ <<
" appName=" <<
347 contexts_.back().applications_.back().applicationUID_ << std::endl;
348 __COUT_ERR__ <<
"\n" << ss.str();
349 throw std::runtime_error(ss.str());
353 if((contexts_.back().applications_.back().id_ == 200 &&
354 contexts_.back().applications_.back().class_ != XDAQContextConfiguration::GATEWAY_SUPERVISOR_CLASS &&
355 contexts_.back().applications_.back().class_ != XDAQContextConfiguration::DEPRECATED_SUPERVISOR_CLASS) ||
356 (contexts_.back().applications_.back().id_ != 200 &&
357 (contexts_.back().applications_.back().class_ == XDAQContextConfiguration::GATEWAY_SUPERVISOR_CLASS ||
358 contexts_.back().applications_.back().class_ == XDAQContextConfiguration::DEPRECATED_SUPERVISOR_CLASS)))
360 __SS__ <<
"XDAQ Application ID of 200 is reserved for the Gateway Supervisor " <<
361 XDAQContextConfiguration::GATEWAY_SUPERVISOR_CLASS <<
". Conflict specifically at id=" <<
362 contexts_.back().applications_.back().id_ <<
" appName=" <<
363 contexts_.back().applications_.back().applicationUID_ << std::endl;
367 appIdSet.insert(contexts_.back().applications_.back().id_);
370 if (appChild.second.getNode(colApplication_.colInstance_).isDefaultValue())
371 contexts_.back().applications_.back().instance_ = 1;
373 appChild.second.getNode(colApplication_.colInstance_).getValue(contexts_.back().applications_.back().instance_);
375 if (appChild.second.getNode(colApplication_.colNetwork_).isDefaultValue())
376 contexts_.back().applications_.back().network_ =
"local";
378 appChild.second.getNode(colApplication_.colNetwork_).getValue(contexts_.back().applications_.back().network_);
380 if (appChild.second.getNode(colApplication_.colGroup_).isDefaultValue())
381 contexts_.back().applications_.back().group_ =
"daq";
383 appChild.second.getNode(colApplication_.colGroup_).getValue(contexts_.back().applications_.back().group_);
385 appChild.second.getNode(colApplication_.colModule_).getValue(contexts_.back().applications_.back().module_);
389 appChild.second.getNode(colApplication_.colConfigurePriority_).getValue(contexts_.back().applications_.back().stateMachineCommandPriority_[
"Configure"]);
390 appChild.second.getNode(colApplication_.colStartPriority_).getValue(contexts_.back().applications_.back().stateMachineCommandPriority_[
"Start"]);
391 appChild.second.getNode(colApplication_.colStopPriority_).getValue(contexts_.back().applications_.back().stateMachineCommandPriority_[
"Stop"]);
395 __COUT__ <<
"Ignoring missing state machine priorities..." << __E__;
399 auto appPropertyLink = appChild.second.getNode(colApplication_.colLinkToPropertyConfiguration_);
400 if (!appPropertyLink.isDisconnected())
404 auto appPropertyChildren = appPropertyLink.getChildren();
408 for (
auto appPropertyChild : appPropertyChildren)
410 contexts_.back().applications_.back().properties_.push_back(XDAQApplicationProperty());
411 contexts_.back().applications_.back().properties_.back().status_ =
412 appPropertyChild.second.getNode(colAppProperty_.colStatus_).getValue<
bool>();
413 contexts_.back().applications_.back().properties_.back().name_ =
414 appPropertyChild.second.getNode(colAppProperty_.colPropertyName_).getValue<std::string>();
415 contexts_.back().applications_.back().properties_.back().type_ =
416 appPropertyChild.second.getNode(colAppProperty_.colPropertyType_).getValue<std::string>();
417 contexts_.back().applications_.back().properties_.back().value_ =
418 appPropertyChild.second.getNode(colAppProperty_.colPropertyValue_).getValue<std::string>();
428 if (isARTDAQContext(contexts_.back().contextUID_))
432 if (contexts_.back().applications_.size() != 1)
434 __SS__ <<
"ARTDAQ Context '" << contexts_.back().contextUID_ <<
435 "' must have one Application! " <<
436 contexts_.back().applications_.size() <<
" were found. " << std::endl;
437 throw std::runtime_error(ss.str());
440 if (!contexts_.back().status_)
continue;
442 if (contexts_.back().applications_[0].class_ ==
443 "ots::ARTDAQDataManagerSupervisor")
444 artdaqBoardReaders_.push_back(contexts_.size() - 1);
445 else if (contexts_.back().applications_[0].class_ ==
446 "ots::EventBuilderApp")
447 artdaqEventBuilders_.push_back(contexts_.size() - 1);
448 else if (contexts_.back().applications_[0].class_ ==
449 "ots::DataLoggerApp" ||
450 contexts_.back().applications_[0].class_ ==
451 "ots::DispatcherApp")
452 artdaqAggregators_.push_back(contexts_.size() - 1);
455 __SS__ <<
"ARTDAQ Context must be have Application of an allowed class type:\n " <<
456 "\tots::ARTDAQDataManagerSupervisor\n" <<
457 "\tots::EventBuilderApp\n" <<
458 "\tots::DataLoggerApp\n" <<
459 "\tots::DispatcherApp\n" <<
460 "\nClass found was " <<
461 contexts_.back().applications_[0].class_ << std::endl;
462 throw std::runtime_error(ss.str());
692 void XDAQContextConfiguration::outputXDAQXML(std::ostream &out)
701 out <<
"<?xml version='1.0'?>\n" <<
702 "<xc:Partition \txmlns:xsi\t= \"http://www.w3.org/2001/XMLSchema-instance\"\n" <<
703 "\t\txmlns:soapenc\t= \"http://schemas.xmlsoap.org/soap/encoding/\"\n" <<
704 "\t\txmlns:xc\t= \"http://xdaq.web.cern.ch/xdaq/xsd/2004/XMLConfiguration-30\">\n\n";
716 for (XDAQContext &context : contexts_)
721 sprintf(tmp,
"\t<!-- ContextUID='%s' sourceConfig='%s' -->",
722 context.contextUID_.c_str(), context.sourceConfig_.c_str());
725 if (!context.status_)
728 sprintf(tmp,
"\t<xc:Context id=\"%u\" url=\"%s:%u\">", context.id_, context.address_.c_str(), context.port_);
729 out << tmp <<
"\n\n";
731 for (XDAQApplication &app : context.applications_)
738 sprintf(tmp,
"\t\t<!-- Application GroupID = '%s' UID='%s' sourceConfig='%s' -->",
739 app.applicationGroupID_.c_str(), app.applicationUID_.c_str(), app.sourceConfig_.c_str());
746 sprintf(tmp,
"\t\t<xc:Application class=\"%s\" id=\"%u\" instance=\"%u\" network=\"%s\" group=\"%s\">\n",
747 app.class_.c_str(), app.id_, app.instance_, app.network_.c_str(), app.group_.c_str());
751 int foundColon = app.class_.rfind(
':');
752 if (foundColon >= 0) ++foundColon;
755 __SS__ <<
"Illegal XDAQApplication class name value of '" << app.class_
756 <<
"' - please check the entry for app ID = " << app.id_ << __E__;
757 throw std::runtime_error(ss.str());
759 out <<
"\t\t\t<properties xmlns=\"urn:xdaq-application:" <<
760 app.class_.substr(foundColon) <<
761 "\" xsi:type=\"soapenc:Struct\">\n";
764 for (XDAQApplicationProperty &appProperty : app.properties_)
767 if (appProperty.type_ ==
"ots-only Property")
continue;
769 if (!appProperty.status_)
770 out <<
"\t\t\t\t<!--\n";
772 sprintf(tmp,
"\t\t\t\t<%s xsi:type=\"%s\">%s</%s>\n",
773 appProperty.name_.c_str(),
774 appProperty.type_.c_str(),
775 appProperty.value_.c_str(),
776 appProperty.name_.c_str());
779 if (!appProperty.status_)
780 out <<
"\t\t\t\t-->\n";
782 out <<
"\t\t\t</properties>\n";
785 out <<
"\t\t</xc:Application>\n";
788 sprintf(tmp,
"\t\t<xc:Module>%s</xc:Module>\n", app.module_.c_str());
791 if (context.status_ && !app.status_)
798 out <<
"\t</xc:Context>\n";
799 if (!context.status_)
805 out <<
"</xc:Partition>\n\n\n";
810 std::string XDAQContextConfiguration::getContextUID(
const std::string &url)
const
812 for (
auto context : contexts_)
814 if (!context.status_)
continue;
816 if (url == context.address_ +
":" + std::to_string(context.port_))
817 return context.contextUID_;
823 std::string XDAQContextConfiguration::getApplicationUID(
const std::string &url,
unsigned int id)
const
825 for (
auto context : contexts_)
827 if (!context.status_)
continue;
829 if (url == context.address_ +
":" + std::to_string(context.port_))
830 for (
auto application : context.applications_)
832 if (!application.status_)
continue;
834 if (application.id_ ==
id)
836 return application.applicationUID_;