1 #include "otsdaq-core/ConfigurationInterface/ConfigurationManager.h"
2 #include "otsdaq-core/Macros/TablePluginMacros.h"
3 #include "otsdaq-core/TablePlugins/XDAQContextTable.h"
11 #define XDAQ_RUN_FILE \
12 std::string(__ENV__("XDAQ_CONFIGURATION_DATA_PATH")) + "/" + \
13 std::string(__ENV__("XDAQ_CONFIGURATION_XML")) + ".xml"
14 #define APP_PRIORITY_FILE \
15 std::string(__ENV__("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")
58 XDAQContextTable::~XDAQContextTable(
void) {}
64 extractContexts(configManager);
70 fs.open(XDAQ_RUN_FILE, std::fstream::out | std::fstream::trunc);
73 __SS__ <<
"Failed to open XDAQ run file: " << XDAQ_RUN_FILE << __E__;
83 bool XDAQContextTable::isARTDAQContext(
const std::string& contextUID)
85 return (contextUID.find(
"ART") == 0 || contextUID.find(
"ARTDAQ") == 0);
89 std::map<std::string ,
90 std::pair<std::string ,
unsigned int >>
91 XDAQContextTable::getARTDAQAppRankMap()
const
93 std::map<std::string ,
94 std::pair<std::string ,
unsigned int >>
97 if(artdaqBoardReaders_.size() == 0 && artdaqEventBuilders_.size() == 0 &&
98 artdaqAggregators_.size() == 0)
100 __COUT_WARN__ <<
"Assuming since there are 0 active ARTDAQ context UID(s), we "
101 "can ignore empty rank map."
106 for(
auto& i : artdaqBoardReaders_)
108 std::make_pair(contexts_[i].contextUID_,
109 std::make_pair(contexts_[i].address_,
110 getARTDAQAppRank(contexts_[i].contextUID_))));
112 for(
auto& i : artdaqEventBuilders_)
114 std::make_pair(contexts_[i].contextUID_,
115 std::make_pair(contexts_[i].address_,
116 getARTDAQAppRank(contexts_[i].contextUID_))));
118 for(
auto& i : artdaqAggregators_)
120 std::make_pair(contexts_[i].contextUID_,
121 std::make_pair(contexts_[i].address_,
122 getARTDAQAppRank(contexts_[i].contextUID_))));
134 unsigned int XDAQContextTable::getARTDAQAppRank(
const std::string& contextUID)
const
136 if(artdaqBoardReaders_.size() == 0 && artdaqEventBuilders_.size() == 0 &&
137 artdaqAggregators_.size() == 0)
139 __COUT_WARN__ <<
"Assuming since there are 0 active ARTDAQ context UID(s), we "
140 "can ignore rank failure."
146 auto localGetRank = [](
const XDAQContext& context) ->
unsigned int {
147 if(context.applications_.size() != 1)
149 __SS__ <<
"Invalid number of ARTDAQ applications in context '"
150 << context.contextUID_ <<
".' Must be 1. Currently is "
151 << context.applications_.size() <<
"." << __E__;
155 return context.applications_[0].id_;
158 for(
auto& i : artdaqBoardReaders_)
159 if(contexts_[i].contextUID_ == contextUID)
160 return localGetRank(contexts_[i]);
162 for(
auto& i : artdaqEventBuilders_)
163 if(contexts_[i].contextUID_ == contextUID)
164 return localGetRank(contexts_[i]);
166 for(
auto& i : artdaqAggregators_)
167 if(contexts_[i].contextUID_ == contextUID)
168 return localGetRank(contexts_[i]);
173 __SS__ <<
"ARTDAQ rank could not be found for context UID '" << contextUID <<
".'"
179 std::string XDAQContextTable::getContextAddress(
const std::string& contextUID,
182 if(contextUID ==
"X")
184 for(
auto& context : contexts_)
186 if(context.contextUID_ == contextUID)
189 return context.address_;
190 auto address = context.address_;
191 if(address.find(
"http://") == 0)
193 address = address.replace(0, 7,
"");
195 if(address.find(
"https://") == 0)
197 address = address.replace(0, 8,
"");
205 unsigned int XDAQContextTable::getARTDAQDataPort(
208 if(contextUID ==
"X")
210 for(
auto& context : contexts_)
212 if(context.contextUID_ == contextUID)
214 if(context.applications_.size() != 1)
216 __SS__ <<
"Invalid number of ARTDAQ applications in context '"
217 << contextUID <<
".' Must be 1. Currently is "
218 << context.applications_.size() <<
"." << __E__;
223 if(context.applications_[0].class_ ==
"ots::ARTDAQDataManagerSupervisor" ||
224 context.applications_[0].class_ ==
"ots::ARTDAQFEDataManagerSupervisor")
227 getSupervisorConfigNode(configManager,
229 context.applications_[0].applicationUID_)
230 .getNode(
"LinkToDataBufferTable")
232 .second.getNode(
"LinkToDataProcessorTable")
235 std::string processorType;
238 for(
auto& processor : processors)
240 processorType = processor.second.getNode(
"ProcessorPluginName")
241 .getValue<std::string>();
242 __COUTV__(processorType);
244 if(processorType ==
"ARTDAQConsumer" ||
245 processorType ==
"ARTDAQProducer")
246 return processor.second.getNode(
"LinkToProcessorTable")
247 .getNode(XDAQContextTable::ARTDAQ_OFFSET_PORT)
248 .getValue<
unsigned int>();
251 __SS__ <<
"No ARTDAQ processor was found while looking for data port."
256 return getSupervisorConfigNode(configManager,
258 context.applications_[0].applicationUID_)
259 .getNode(XDAQContextTable::ARTDAQ_OFFSET_PORT)
260 .getValue<
unsigned int>();
267 std::vector<const XDAQContextTable::XDAQContext*>
268 XDAQContextTable::getBoardReaderContexts()
const
270 std::vector<const XDAQContext*> retVec;
271 for(
auto& i : artdaqBoardReaders_)
272 retVec.push_back(&contexts_[i]);
276 std::vector<const XDAQContextTable::XDAQContext*>
277 XDAQContextTable::getEventBuilderContexts()
const
279 std::vector<const XDAQContext*> retVec;
280 for(
auto& i : artdaqEventBuilders_)
281 retVec.push_back(&contexts_[i]);
285 std::vector<const XDAQContextTable::XDAQContext*>
286 XDAQContextTable::getAggregatorContexts()
const
288 std::vector<const XDAQContext*> retVec;
289 for(
auto& i : artdaqAggregators_)
290 retVec.push_back(&contexts_[i]);
298 return configManager->__SELF_NODE__.getNode(contextUID);
304 const std::string& contextUID,
305 const std::string& appUID)
const
307 return configManager->__SELF_NODE__.getNode(
308 contextUID +
"/" + colContext_.colLinkToApplicationTable_ +
"/" + appUID);
314 const std::string& contextUID,
315 const std::string& appUID)
const
317 return configManager->__SELF_NODE__.getNode(
318 contextUID +
"/" + colContext_.colLinkToApplicationTable_ +
"/" + appUID +
"/" +
319 colApplication_.colLinkToSupervisorTable_);
334 auto children = configManager->__SELF_NODE__.getChildren();
339 artdaqBoardReaders_.clear();
340 artdaqEventBuilders_.clear();
341 artdaqAggregators_.clear();
346 std::set<
unsigned int > appIdSet;
348 for(
auto& child : children)
350 contexts_.push_back(XDAQContext());
354 contexts_.back().contextUID_ = child.first;
356 contexts_.back().sourceConfig_ =
357 child.second.getTableName() +
"_v" +
358 child.second.getTableVersion().toString() +
" @ " +
359 std::to_string(child.second.getTableCreationTime());
360 child.second.getNode(colContext_.colContextUID_)
361 .getValue(contexts_.back().contextUID_);
362 child.second.getNode(colContext_.colStatus_).getValue(contexts_.back().status_);
363 child.second.getNode(colContext_.colId_).getValue(contexts_.back().id_);
364 child.second.getNode(colContext_.colAddress_).getValue(contexts_.back().address_);
365 child.second.getNode(colContext_.colPort_).getValue(contexts_.back().port_);
369 auto appLink = child.second.getNode(colContext_.colLinkToApplicationTable_);
370 if(appLink.isDisconnected())
372 __SS__ <<
"Application link is disconnected!" << __E__;
377 auto appChildren = appLink.getChildren();
378 for(
auto appChild : appChildren)
382 contexts_.back().applications_.push_back(XDAQApplication());
384 contexts_.back().applications_.back().applicationGroupID_ = child.first;
385 contexts_.back().applications_.back().sourceConfig_ =
386 appChild.second.getTableName() +
"_v" +
387 appChild.second.getTableVersion().toString() +
" @ " +
388 std::to_string(appChild.second.getTableCreationTime());
390 appChild.second.getNode(colApplication_.colApplicationUID_)
391 .getValue(contexts_.back().applications_.back().applicationUID_);
392 appChild.second.getNode(colApplication_.colStatus_)
393 .getValue(contexts_.back().applications_.back().status_);
394 appChild.second.getNode(colApplication_.colClass_)
395 .getValue(contexts_.back().applications_.back().class_);
396 appChild.second.getNode(colApplication_.colId_)
397 .getValue(contexts_.back().applications_.back().id_);
400 if((contexts_.back().applications_.back().id_ == 200 &&
401 contexts_.back().applications_.back().class_ !=
402 XDAQContextTable::GATEWAY_SUPERVISOR_CLASS &&
403 contexts_.back().applications_.back().class_ !=
404 XDAQContextTable::DEPRECATED_SUPERVISOR_CLASS) ||
405 (contexts_.back().applications_.back().id_ != 200 &&
406 (contexts_.back().applications_.back().class_ ==
407 XDAQContextTable::GATEWAY_SUPERVISOR_CLASS ||
408 contexts_.back().applications_.back().class_ ==
409 XDAQContextTable::DEPRECATED_SUPERVISOR_CLASS)))
411 __SS__ <<
"XDAQ Application ID of 200 is reserved for the Gateway "
413 << XDAQContextTable::GATEWAY_SUPERVISOR_CLASS
414 <<
". Conflict specifically at id="
415 << contexts_.back().applications_.back().id_ <<
" appName="
416 << contexts_.back().applications_.back().applicationUID_ << __E__;
421 if(contexts_.back().status_ && contexts_.back().applications_.back().status_)
424 if(appIdSet.find(contexts_.back().applications_.back().id_) !=
427 __SS__ <<
"XDAQ Application IDs are not unique. Specifically at id="
428 << contexts_.back().applications_.back().id_ <<
" appName="
429 << contexts_.back().applications_.back().applicationUID_
431 __COUT_ERR__ <<
"\n" << ss.str();
434 appIdSet.insert(contexts_.back().applications_.back().id_);
438 if(appChild.second.getNode(colApplication_.colInstance_).isDefaultValue())
439 contexts_.back().applications_.back().instance_ = 1;
441 appChild.second.getNode(colApplication_.colInstance_)
442 .getValue(contexts_.back().applications_.back().instance_);
444 if(appChild.second.getNode(colApplication_.colNetwork_).isDefaultValue())
445 contexts_.back().applications_.back().network_ =
"local";
447 appChild.second.getNode(colApplication_.colNetwork_)
448 .getValue(contexts_.back().applications_.back().network_);
450 if(appChild.second.getNode(colApplication_.colGroup_).isDefaultValue())
451 contexts_.back().applications_.back().group_ =
"daq";
453 appChild.second.getNode(colApplication_.colGroup_)
454 .getValue(contexts_.back().applications_.back().group_);
456 appChild.second.getNode(colApplication_.colModule_)
457 .getValue(contexts_.back().applications_.back().module_);
460 if(contexts_.back().applications_.back().class_ ==
461 XDAQContextTable::DEPRECATED_SUPERVISOR_CLASS)
463 contexts_.back().applications_.back().class_ =
464 XDAQContextTable::GATEWAY_SUPERVISOR_CLASS;
465 __COUT__ <<
"Fixing deprecated Supervisor class from "
466 << XDAQContextTable::DEPRECATED_SUPERVISOR_CLASS <<
" to "
467 << (contexts_.back().applications_.back().class_);
469 if(contexts_.back().applications_.back().module_.find(
"libSupervisor.so") !=
472 __COUT__ <<
"Fixing deprecated Supervisor class from "
473 << contexts_.back().applications_.back().module_ <<
" to ";
474 contexts_.back().applications_.back().module_ =
475 contexts_.back().applications_.back().module_.substr(
477 contexts_.back().applications_.back().module_.size() -
478 std::string(
"Supervisor.so").size()) +
479 "GatewaySupervisor.so";
480 std::cout << contexts_.back().applications_.back().module_ << __E__;
485 appChild.second.getNode(colApplication_.colConfigurePriority_)
486 .getValue(contexts_.back()
487 .applications_.back()
488 .stateMachineCommandPriority_[
"Configure"]);
489 appChild.second.getNode(colApplication_.colStartPriority_)
490 .getValue(contexts_.back()
491 .applications_.back()
492 .stateMachineCommandPriority_[
"Start"]);
493 appChild.second.getNode(colApplication_.colStopPriority_)
494 .getValue(contexts_.back()
495 .applications_.back()
496 .stateMachineCommandPriority_[
"Stop"]);
500 __COUT__ <<
"Ignoring missing state machine priorities..." << __E__;
503 auto appPropertyLink =
504 appChild.second.getNode(colApplication_.colLinkToPropertyTable_);
505 if(!appPropertyLink.isDisconnected())
509 auto appPropertyChildren = appPropertyLink.getChildren();
514 for(
auto appPropertyChild : appPropertyChildren)
516 contexts_.back().applications_.back().properties_.push_back(
517 XDAQApplicationProperty());
518 contexts_.back().applications_.back().properties_.back().status_ =
519 appPropertyChild.second.getNode(colAppProperty_.colStatus_)
521 contexts_.back().applications_.back().properties_.back().name_ =
522 appPropertyChild.second.getNode(colAppProperty_.colPropertyName_)
523 .getValue<std::string>();
524 contexts_.back().applications_.back().properties_.back().type_ =
525 appPropertyChild.second.getNode(colAppProperty_.colPropertyType_)
526 .getValue<std::string>();
527 contexts_.back().applications_.back().properties_.back().value_ =
528 appPropertyChild.second.getNode(colAppProperty_.colPropertyValue_)
529 .getValue<std::string>();
541 if(isARTDAQContext(contexts_.back().contextUID_))
545 if(contexts_.back().applications_.size() != 1)
547 __SS__ <<
"ARTDAQ Context '" << contexts_.back().contextUID_
548 <<
"' must have one Application! "
549 << contexts_.back().applications_.size() <<
" were found. "
554 if(!contexts_.back().status_)
557 if(contexts_.back().applications_[0].class_ ==
558 "ots::ARTDAQDataManagerSupervisor" ||
559 contexts_.back().applications_[0].class_ ==
560 "ots::ARTDAQFEDataManagerSupervisor")
561 artdaqBoardReaders_.push_back(contexts_.size() - 1);
562 else if(contexts_.back().applications_[0].class_ ==
563 "ots::EventBuilderApp")
564 artdaqEventBuilders_.push_back(contexts_.size() - 1);
565 else if(contexts_.back().applications_[0].class_ ==
566 "ots::DataLoggerApp" ||
567 contexts_.back().applications_[0].class_ ==
568 "ots::DispatcherApp")
569 artdaqAggregators_.push_back(contexts_.size() - 1);
572 __SS__ <<
"ARTDAQ Context must be have Application of an allowed class "
574 <<
"\tots::ARTDAQDataManagerSupervisor (Board Reader)\n"
575 <<
"\tots::ARTDAQFEDataManagerSupervisor (Board Reader)\n"
576 <<
"\tots::EventBuilderApp (Event Builder)\n"
577 <<
"\tots::DataLoggerApp (Aggregator)\n"
578 <<
"\tots::DispatcherApp (Aggregator)\n"
579 <<
"\nClass found was " << contexts_.back().applications_[0].class_
823 out <<
"<?xml version='1.0'?>\n"
824 <<
"<xc:Partition \txmlns:xsi\t= \"http://www.w3.org/2001/XMLSchema-instance\"\n"
825 <<
"\t\txmlns:soapenc\t= \"http://schemas.xmlsoap.org/soap/encoding/\"\n"
826 <<
"\t\txmlns:xc\t= "
827 "\"http://xdaq.web.cern.ch/xdaq/xsd/2004/XMLConfiguration-30\">\n\n";
844 "\t<!-- ContextUID='%s' sourceConfig='%s' -->",
845 context.contextUID_.c_str(),
846 context.sourceConfig_.c_str());
853 "\t<xc:Context id=\"%u\" url=\"%s:%u\">",
855 context.address_.c_str(),
857 out << tmp <<
"\n\n";
867 "\t\t<!-- Application GroupID = '%s' UID='%s' sourceConfig='%s' -->",
868 app.applicationGroupID_.c_str(),
869 app.applicationUID_.c_str(),
870 app.sourceConfig_.c_str());
878 "\t\t<xc:Application class=\"%s\" id=\"%u\" instance=\"%u\" "
879 "network=\"%s\" group=\"%s\">\n",
883 app.network_.c_str(),
888 int foundColon = app.class_.rfind(
':');
893 __SS__ <<
"Illegal XDAQApplication class name value of '" << app.class_
894 <<
"' - please check the entry for app ID = " << app.id_ << __E__;
897 out <<
"\t\t\t<properties xmlns=\"urn:xdaq-application:"
898 << app.class_.substr(foundColon) <<
"\" xsi:type=\"soapenc:Struct\">\n";
903 if(appProperty.type_ ==
"ots::SupervisorProperty")
906 if(!appProperty.status_)
907 out <<
"\t\t\t\t<!--\n";
910 "\t\t\t\t<%s xsi:type=\"%s\">%s</%s>\n",
911 appProperty.name_.c_str(),
912 appProperty.type_.c_str(),
913 appProperty.value_.c_str(),
914 appProperty.name_.c_str());
917 if(!appProperty.status_)
918 out <<
"\t\t\t\t-->\n";
920 out <<
"\t\t\t</properties>\n";
923 out <<
"\t\t</xc:Application>\n";
925 sprintf(tmp,
"\t\t<xc:Module>%s</xc:Module>\n", app.module_.c_str());
928 if(context.status_ && !app.status_)
935 out <<
"\t</xc:Context>\n";
942 out <<
"</xc:Partition>\n\n\n";
946 std::string XDAQContextTable::getContextUID(
const std::string& url)
const
948 for(
auto context : contexts_)
953 if(url == context.address_ +
":" + std::to_string(context.port_))
954 return context.contextUID_;
960 std::string XDAQContextTable::getApplicationUID(
const std::string& url,
961 unsigned int id)
const
964 for(
auto context : contexts_)
975 if(url == context.address_ +
":" + std::to_string(context.port_))
976 for(
auto application : context.applications_)
979 if(!application.status_)
982 if(application.id_ ==
id)
984 return application.applicationUID_;
void outputXDAQXML(std::ostream &out)