1 #include "otsdaq-core/ConfigurationInterface/ConfigurationManager.h"
2 #include "otsdaq-core/Macros/TablePluginMacros.h"
3 #include "otsdaq-core/TablePluginDataFormats/XDAQContextTable.h"
11 #define XDAQ_RUN_FILE \
12 std::string(getenv("XDAQ_CONFIGURATION_DATA_PATH")) + "/" + \
13 std::string(getenv("XDAQ_CONFIGURATION_XML")) + ".xml"
14 #define APP_PRIORITY_FILE \
15 std::string(getenv("XDAQ_CONFIGURATION_DATA_PATH")) + "/" + \
16 "xdaqAppStateMachinePriority"
22 const std::string XDAQContextTable::DEPRECATED_SUPERVISOR_CLASS =
24 const std::string XDAQContextTable::GATEWAY_SUPERVISOR_CLASS =
"ots::GatewaySupervisor";
25 const std::string XDAQContextTable::WIZARD_SUPERVISOR_CLASS =
"ots::WizardSupervisor";
26 const std::set<std::string> XDAQContextTable::FETypeClassNames_ = {
28 "ots::FEDataManagerSupervisor",
29 "ots::ARTDAQFEDataManagerSupervisor"};
30 const std::set<std::string> XDAQContextTable::DMTypeClassNames_ = {
31 "ots::DataManagerSupervisor",
32 "ots::FEDataManagerSupervisor",
33 "ots::ARTDAQFEDataManagerSupervisor"};
34 const std::set<std::string> XDAQContextTable::LogbookTypeClassNames_ = {
35 "ots::LogbookSupervisor"};
36 const std::set<std::string> XDAQContextTable::MacroMakerTypeClassNames_ = {
37 "ots::MacroMakerSupervisor"};
38 const std::set<std::string> XDAQContextTable::ChatTypeClassNames_ = {
39 "ots::ChatSupervisor"};
40 const std::set<std::string> XDAQContextTable::ConsoleTypeClassNames_ = {
41 "ots::ConsoleSupervisor"};
42 const std::set<std::string> XDAQContextTable::ConfigurationGUITypeClassNames_ = {
43 "ots::TableGUISupervisor"};
45 const std::string XDAQContextTable::ARTDAQ_OFFSET_PORT =
"OffsetPort";
47 const uint8_t XDAQContextTable::XDAQApplication::DEFAULT_PRIORITY = 100;
50 XDAQContextTable::XDAQContextTable(
void) :
TableBase(
"XDAQContextTable")
90 XDAQContextTable::~XDAQContextTable(
void) {}
96 extractContexts(configManager);
102 fs.open(XDAQ_RUN_FILE, std::fstream::out | std::fstream::trunc);
105 __SS__ <<
"Failed to open XDAQ run file: " << XDAQ_RUN_FILE << __E__;
115 bool XDAQContextTable::isARTDAQContext(
const std::string& contextUID)
117 return (contextUID.find(
"ART") == 0 || contextUID.find(
"ARTDAQ") == 0);
121 std::map<std::string ,
122 std::pair<std::string ,
unsigned int >>
123 XDAQContextTable::getARTDAQAppRankMap()
const
125 std::map<std::string ,
126 std::pair<std::string ,
unsigned int >>
129 if(artdaqBoardReaders_.size() == 0 && artdaqEventBuilders_.size() == 0 &&
130 artdaqAggregators_.size() == 0)
132 __COUT_WARN__ <<
"Assuming since there are 0 active ARTDAQ context UID(s), we "
133 "can ignore empty rank map."
138 for(
auto& i : artdaqBoardReaders_)
140 std::make_pair(contexts_[i].contextUID_,
141 std::make_pair(contexts_[i].address_,
142 getARTDAQAppRank(contexts_[i].contextUID_))));
144 for(
auto& i : artdaqEventBuilders_)
146 std::make_pair(contexts_[i].contextUID_,
147 std::make_pair(contexts_[i].address_,
148 getARTDAQAppRank(contexts_[i].contextUID_))));
150 for(
auto& i : artdaqAggregators_)
152 std::make_pair(contexts_[i].contextUID_,
153 std::make_pair(contexts_[i].address_,
154 getARTDAQAppRank(contexts_[i].contextUID_))));
166 unsigned int XDAQContextTable::getARTDAQAppRank(
const std::string& contextUID)
const
168 if(artdaqBoardReaders_.size() == 0 && artdaqEventBuilders_.size() == 0 &&
169 artdaqAggregators_.size() == 0)
171 __COUT_WARN__ <<
"Assuming since there are 0 active ARTDAQ context UID(s), we "
172 "can ignore rank failure."
178 auto localGetRank = [](
const XDAQContext& context) ->
unsigned int {
179 if(context.applications_.size() != 1)
181 __SS__ <<
"Invalid number of ARTDAQ applications in context '"
182 << context.contextUID_ <<
".' Must be 1. Currently is "
183 << context.applications_.size() <<
"." << __E__;
187 return context.applications_[0].id_;
190 for(
auto& i : artdaqBoardReaders_)
191 if(contexts_[i].contextUID_ == contextUID)
192 return localGetRank(contexts_[i]);
194 for(
auto& i : artdaqEventBuilders_)
195 if(contexts_[i].contextUID_ == contextUID)
196 return localGetRank(contexts_[i]);
198 for(
auto& i : artdaqAggregators_)
199 if(contexts_[i].contextUID_ == contextUID)
200 return localGetRank(contexts_[i]);
205 __SS__ <<
"ARTDAQ rank could not be found for context UID '" << contextUID <<
".'"
211 std::string XDAQContextTable::getContextAddress(
const std::string& contextUID,
214 if(contextUID ==
"X")
216 for(
auto& context : contexts_)
218 if(context.contextUID_ == contextUID)
221 return context.address_;
222 auto address = context.address_;
223 if(address.find(
"http://") == 0)
225 address = address.replace(0, 7,
"");
227 if(address.find(
"https://") == 0)
229 address = address.replace(0, 8,
"");
237 unsigned int XDAQContextTable::getARTDAQDataPort(
240 if(contextUID ==
"X")
242 for(
auto& context : contexts_)
244 if(context.contextUID_ == contextUID)
246 if(context.applications_.size() != 1)
248 __SS__ <<
"Invalid number of ARTDAQ applications in context '"
249 << contextUID <<
".' Must be 1. Currently is "
250 << context.applications_.size() <<
"." << __E__;
255 if(context.applications_[0].class_ ==
"ots::ARTDAQDataManagerSupervisor" ||
256 context.applications_[0].class_ ==
"ots::ARTDAQFEDataManagerSupervisor")
259 getSupervisorConfigNode(configManager,
261 context.applications_[0].applicationUID_)
262 .getNode(
"LinkToDataBufferTable")
264 .second.getNode(
"LinkToDataProcessorTable")
267 std::string processorType;
270 for(
auto& processor : processors)
272 processorType = processor.second.getNode(
"ProcessorPluginName")
273 .getValue<std::string>();
274 __COUTV__(processorType);
276 if(processorType ==
"ARTDAQConsumer" ||
277 processorType ==
"ARTDAQProducer")
278 return processor.second.getNode(
"LinkToProcessorTable")
279 .getNode(XDAQContextTable::ARTDAQ_OFFSET_PORT)
280 .getValue<
unsigned int>();
283 __SS__ <<
"No ARTDAQ processor was found while looking for data port."
288 return getSupervisorConfigNode(configManager,
290 context.applications_[0].applicationUID_)
291 .getNode(XDAQContextTable::ARTDAQ_OFFSET_PORT)
292 .getValue<
unsigned int>();
299 std::vector<const XDAQContextTable::XDAQContext*>
300 XDAQContextTable::getBoardReaderContexts()
const
302 std::vector<const XDAQContext*> retVec;
303 for(
auto& i : artdaqBoardReaders_)
304 retVec.push_back(&contexts_[i]);
308 std::vector<const XDAQContextTable::XDAQContext*>
309 XDAQContextTable::getEventBuilderContexts()
const
311 std::vector<const XDAQContext*> retVec;
312 for(
auto& i : artdaqEventBuilders_)
313 retVec.push_back(&contexts_[i]);
317 std::vector<const XDAQContextTable::XDAQContext*>
318 XDAQContextTable::getAggregatorContexts()
const
320 std::vector<const XDAQContext*> retVec;
321 for(
auto& i : artdaqAggregators_)
322 retVec.push_back(&contexts_[i]);
330 return configManager->__SELF_NODE__.getNode(contextUID);
336 const std::string& contextUID,
337 const std::string& appUID)
const
339 return configManager->__SELF_NODE__.getNode(
340 contextUID +
"/" + colContext_.colLinkToApplicationTable_ +
"/" + appUID);
346 const std::string& contextUID,
347 const std::string& appUID)
const
349 return configManager->__SELF_NODE__.getNode(
350 contextUID +
"/" + colContext_.colLinkToApplicationTable_ +
"/" + appUID +
"/" +
351 colApplication_.colLinkToSupervisorTable_);
366 auto children = configManager->__SELF_NODE__.getChildren();
371 artdaqBoardReaders_.clear();
372 artdaqEventBuilders_.clear();
373 artdaqAggregators_.clear();
378 std::set<
unsigned int > appIdSet;
380 for(
auto& child : children)
382 contexts_.push_back(XDAQContext());
386 contexts_.back().contextUID_ = child.first;
388 contexts_.back().sourceConfig_ =
389 child.second.getTableName() +
"_v" +
390 child.second.getTableVersion().toString() +
" @ " +
391 std::to_string(child.second.getTableCreationTime());
392 child.second.getNode(colContext_.colContextUID_)
393 .getValue(contexts_.back().contextUID_);
394 child.second.getNode(colContext_.colStatus_).getValue(contexts_.back().status_);
395 child.second.getNode(colContext_.colId_).getValue(contexts_.back().id_);
396 child.second.getNode(colContext_.colAddress_).getValue(contexts_.back().address_);
397 child.second.getNode(colContext_.colPort_).getValue(contexts_.back().port_);
401 auto appLink = child.second.getNode(colContext_.colLinkToApplicationTable_);
402 if(appLink.isDisconnected())
404 __SS__ <<
"Application link is disconnected!" << __E__;
409 auto appChildren = appLink.getChildren();
410 for(
auto appChild : appChildren)
414 contexts_.back().applications_.push_back(XDAQApplication());
416 contexts_.back().applications_.back().applicationGroupID_ = child.first;
417 contexts_.back().applications_.back().sourceConfig_ =
418 appChild.second.getTableName() +
"_v" +
419 appChild.second.getTableVersion().toString() +
" @ " +
420 std::to_string(appChild.second.getTableCreationTime());
422 appChild.second.getNode(colApplication_.colApplicationUID_)
423 .getValue(contexts_.back().applications_.back().applicationUID_);
424 appChild.second.getNode(colApplication_.colStatus_)
425 .getValue(contexts_.back().applications_.back().status_);
426 appChild.second.getNode(colApplication_.colClass_)
427 .getValue(contexts_.back().applications_.back().class_);
428 appChild.second.getNode(colApplication_.colId_)
429 .getValue(contexts_.back().applications_.back().id_);
432 if((contexts_.back().applications_.back().id_ == 200 &&
433 contexts_.back().applications_.back().class_ !=
434 XDAQContextTable::GATEWAY_SUPERVISOR_CLASS &&
435 contexts_.back().applications_.back().class_ !=
436 XDAQContextTable::DEPRECATED_SUPERVISOR_CLASS) ||
437 (contexts_.back().applications_.back().id_ != 200 &&
438 (contexts_.back().applications_.back().class_ ==
439 XDAQContextTable::GATEWAY_SUPERVISOR_CLASS ||
440 contexts_.back().applications_.back().class_ ==
441 XDAQContextTable::DEPRECATED_SUPERVISOR_CLASS)))
443 __SS__ <<
"XDAQ Application ID of 200 is reserved for the Gateway "
445 << XDAQContextTable::GATEWAY_SUPERVISOR_CLASS
446 <<
". Conflict specifically at id="
447 << contexts_.back().applications_.back().id_ <<
" appName="
448 << contexts_.back().applications_.back().applicationUID_ << __E__;
453 if(contexts_.back().status_ && contexts_.back().applications_.back().status_)
456 if(appIdSet.find(contexts_.back().applications_.back().id_) !=
459 __SS__ <<
"XDAQ Application IDs are not unique. Specifically at id="
460 << contexts_.back().applications_.back().id_ <<
" appName="
461 << contexts_.back().applications_.back().applicationUID_
463 __COUT_ERR__ <<
"\n" << ss.str();
466 appIdSet.insert(contexts_.back().applications_.back().id_);
470 if(appChild.second.getNode(colApplication_.colInstance_).isDefaultValue())
471 contexts_.back().applications_.back().instance_ = 1;
473 appChild.second.getNode(colApplication_.colInstance_)
474 .getValue(contexts_.back().applications_.back().instance_);
476 if(appChild.second.getNode(colApplication_.colNetwork_).isDefaultValue())
477 contexts_.back().applications_.back().network_ =
"local";
479 appChild.second.getNode(colApplication_.colNetwork_)
480 .getValue(contexts_.back().applications_.back().network_);
482 if(appChild.second.getNode(colApplication_.colGroup_).isDefaultValue())
483 contexts_.back().applications_.back().group_ =
"daq";
485 appChild.second.getNode(colApplication_.colGroup_)
486 .getValue(contexts_.back().applications_.back().group_);
488 appChild.second.getNode(colApplication_.colModule_)
489 .getValue(contexts_.back().applications_.back().module_);
492 if(contexts_.back().applications_.back().class_ ==
493 XDAQContextTable::DEPRECATED_SUPERVISOR_CLASS)
495 contexts_.back().applications_.back().class_ =
496 XDAQContextTable::GATEWAY_SUPERVISOR_CLASS;
497 __COUT__ <<
"Fixing deprecated Supervisor class from "
498 << XDAQContextTable::DEPRECATED_SUPERVISOR_CLASS <<
" to "
499 << (contexts_.back().applications_.back().class_);
501 if(contexts_.back().applications_.back().module_.find(
"libSupervisor.so") !=
504 __COUT__ <<
"Fixing deprecated Supervisor class from "
505 << contexts_.back().applications_.back().module_ <<
" to ";
506 contexts_.back().applications_.back().module_ =
507 contexts_.back().applications_.back().module_.substr(
509 contexts_.back().applications_.back().module_.size() -
510 std::string(
"Supervisor.so").size()) +
511 "GatewaySupervisor.so";
512 std::cout << contexts_.back().applications_.back().module_ << __E__;
517 appChild.second.getNode(colApplication_.colConfigurePriority_)
518 .getValue(contexts_.back()
519 .applications_.back()
520 .stateMachineCommandPriority_[
"Configure"]);
521 appChild.second.getNode(colApplication_.colStartPriority_)
522 .getValue(contexts_.back()
523 .applications_.back()
524 .stateMachineCommandPriority_[
"Start"]);
525 appChild.second.getNode(colApplication_.colStopPriority_)
526 .getValue(contexts_.back()
527 .applications_.back()
528 .stateMachineCommandPriority_[
"Stop"]);
532 __COUT__ <<
"Ignoring missing state machine priorities..." << __E__;
535 auto appPropertyLink =
536 appChild.second.getNode(colApplication_.colLinkToPropertyTable_);
537 if(!appPropertyLink.isDisconnected())
541 auto appPropertyChildren = appPropertyLink.getChildren();
546 for(
auto appPropertyChild : appPropertyChildren)
548 contexts_.back().applications_.back().properties_.push_back(
549 XDAQApplicationProperty());
550 contexts_.back().applications_.back().properties_.back().status_ =
551 appPropertyChild.second.getNode(colAppProperty_.colStatus_)
553 contexts_.back().applications_.back().properties_.back().name_ =
554 appPropertyChild.second.getNode(colAppProperty_.colPropertyName_)
555 .getValue<std::string>();
556 contexts_.back().applications_.back().properties_.back().type_ =
557 appPropertyChild.second.getNode(colAppProperty_.colPropertyType_)
558 .getValue<std::string>();
559 contexts_.back().applications_.back().properties_.back().value_ =
560 appPropertyChild.second.getNode(colAppProperty_.colPropertyValue_)
561 .getValue<std::string>();
573 if(isARTDAQContext(contexts_.back().contextUID_))
577 if(contexts_.back().applications_.size() != 1)
579 __SS__ <<
"ARTDAQ Context '" << contexts_.back().contextUID_
580 <<
"' must have one Application! "
581 << contexts_.back().applications_.size() <<
" were found. "
586 if(!contexts_.back().status_)
589 if(contexts_.back().applications_[0].class_ ==
590 "ots::ARTDAQDataManagerSupervisor" ||
591 contexts_.back().applications_[0].class_ ==
592 "ots::ARTDAQFEDataManagerSupervisor")
593 artdaqBoardReaders_.push_back(contexts_.size() - 1);
594 else if(contexts_.back().applications_[0].class_ ==
595 "ots::EventBuilderApp")
596 artdaqEventBuilders_.push_back(contexts_.size() - 1);
597 else if(contexts_.back().applications_[0].class_ ==
598 "ots::DataLoggerApp" ||
599 contexts_.back().applications_[0].class_ ==
600 "ots::DispatcherApp")
601 artdaqAggregators_.push_back(contexts_.size() - 1);
604 __SS__ <<
"ARTDAQ Context must be have Application of an allowed class "
606 <<
"\tots::ARTDAQDataManagerSupervisor (Board Reader)\n"
607 <<
"\tots::ARTDAQFEDataManagerSupervisor (Board Reader)\n"
608 <<
"\tots::EventBuilderApp (Event Builder)\n"
609 <<
"\tots::DataLoggerApp (Aggregator)\n"
610 <<
"\tots::DispatcherApp (Aggregator)\n"
611 <<
"\nClass found was " << contexts_.back().applications_[0].class_
855 out <<
"<?xml version='1.0'?>\n"
856 <<
"<xc:Partition \txmlns:xsi\t= \"http://www.w3.org/2001/XMLSchema-instance\"\n"
857 <<
"\t\txmlns:soapenc\t= \"http://schemas.xmlsoap.org/soap/encoding/\"\n"
858 <<
"\t\txmlns:xc\t= "
859 "\"http://xdaq.web.cern.ch/xdaq/xsd/2004/XMLConfiguration-30\">\n\n";
876 "\t<!-- ContextUID='%s' sourceConfig='%s' -->",
877 context.contextUID_.c_str(),
878 context.sourceConfig_.c_str());
885 "\t<xc:Context id=\"%u\" url=\"%s:%u\">",
887 context.address_.c_str(),
889 out << tmp <<
"\n\n";
899 "\t\t<!-- Application GroupID = '%s' UID='%s' sourceConfig='%s' -->",
900 app.applicationGroupID_.c_str(),
901 app.applicationUID_.c_str(),
902 app.sourceConfig_.c_str());
910 "\t\t<xc:Application class=\"%s\" id=\"%u\" instance=\"%u\" "
911 "network=\"%s\" group=\"%s\">\n",
915 app.network_.c_str(),
920 int foundColon = app.class_.rfind(
':');
925 __SS__ <<
"Illegal XDAQApplication class name value of '" << app.class_
926 <<
"' - please check the entry for app ID = " << app.id_ << __E__;
929 out <<
"\t\t\t<properties xmlns=\"urn:xdaq-application:"
930 << app.class_.substr(foundColon) <<
"\" xsi:type=\"soapenc:Struct\">\n";
935 if(appProperty.type_ ==
"ots::SupervisorProperty")
938 if(!appProperty.status_)
939 out <<
"\t\t\t\t<!--\n";
942 "\t\t\t\t<%s xsi:type=\"%s\">%s</%s>\n",
943 appProperty.name_.c_str(),
944 appProperty.type_.c_str(),
945 appProperty.value_.c_str(),
946 appProperty.name_.c_str());
949 if(!appProperty.status_)
950 out <<
"\t\t\t\t-->\n";
952 out <<
"\t\t\t</properties>\n";
955 out <<
"\t\t</xc:Application>\n";
957 sprintf(tmp,
"\t\t<xc:Module>%s</xc:Module>\n", app.module_.c_str());
960 if(context.status_ && !app.status_)
967 out <<
"\t</xc:Context>\n";
974 out <<
"</xc:Partition>\n\n\n";
978 std::string XDAQContextTable::getContextUID(
const std::string& url)
const
980 for(
auto context : contexts_)
985 if(url == context.address_ +
":" + std::to_string(context.port_))
986 return context.contextUID_;
992 std::string XDAQContextTable::getApplicationUID(
const std::string& url,
993 unsigned int id)
const
996 for(
auto context : contexts_)
1002 if(!context.status_)
1007 if(url == context.address_ +
":" + std::to_string(context.port_))
1008 for(
auto application : context.applications_)
1011 if(!application.status_)
1014 if(application.id_ ==
id)
1016 return application.applicationUID_;
void outputXDAQXML(std::ostream &out)