tdaq-develop-2025-02-12
XDAQContextTable.cc
1 #include "otsdaq/TablePlugins/XDAQContextTable/XDAQContextTable.h"
2 #include "otsdaq/ConfigurationInterface/ConfigurationManager.h"
3 
4 #include <stdio.h>
5 #include <fstream> // std::fstream
6 #include <iostream>
7 
8 using namespace ots;
9 
10 // clang-format off
11 
12 #define XDAQ_RUN_FILE std::string(__ENV__("XDAQ_CONFIGURATION_DATA_PATH")) + "/" + std::string(__ENV__("XDAQ_CONFIGURATION_XML")) + ".xml"
13 #define APP_PRIORITY_FILE std::string(__ENV__("XDAQ_CONFIGURATION_DATA_PATH")) + "/" + "xdaqAppStateMachinePriority"
14 
15 const std::string XDAQContextTable::DEPRECATED_SUPERVISOR_CLASS = "ots::Supervisor"; // still allowed for now, in StartOTS
16 const std::string XDAQContextTable::GATEWAY_SUPERVISOR_CLASS = "ots::GatewaySupervisor";
17 const std::string XDAQContextTable::WIZARD_SUPERVISOR_CLASS = "ots::WizardSupervisor";
18 const std::string XDAQContextTable::ARTDAQ_SUPERVISOR_CLASS = "ots::ARTDAQSupervisor";
19 const std::set<std::string> XDAQContextTable::FETypeClassNames_ = { "ots::FESupervisor", "ots::FEDataManagerSupervisor", "ots::ARTDAQFEDataManagerSupervisor"};
20 const std::set<std::string> XDAQContextTable::DMTypeClassNames_ = { "ots::DataManagerSupervisor", "ots::FEDataManagerSupervisor", "ots::ARTDAQFEDataManagerSupervisor"};
21 const std::set<std::string> XDAQContextTable::LogbookTypeClassNames_ = { "ots::LogbookSupervisor", "ots::ECLSupervisor"};
22 const std::set<std::string> XDAQContextTable::MacroMakerTypeClassNames_ = { "ots::MacroMakerSupervisor"};
23 const std::set<std::string> XDAQContextTable::ChatTypeClassNames_ = { "ots::ChatSupervisor"};
24 const std::set<std::string> XDAQContextTable::ConsoleTypeClassNames_ = { "ots::ConsoleSupervisor"};
25 const std::set<std::string> XDAQContextTable::ConfigurationGUITypeClassNames_ = { "ots::ConfigurationGUISupervisor"};
26 const std::set<std::string> XDAQContextTable::CodeEditorTypeClassNames_ = { "ots::CodeEditorSupervisor"};
27 const std::set<std::string> XDAQContextTable::VisualizerTypeClassNames_ = { "ots::VisualSupervisor"};
28 const std::set<std::string> XDAQContextTable::SlowControlsTypeClassNames_ = { "ots::SlowControlsDashboardSupervisor"};
29 
31 const std::map<std::string /*class*/, std::string /*module*/> XDAQContextTable::AppClassModuleLookup_ = {
32  std::make_pair(XDAQContextTable::GATEWAY_SUPERVISOR_CLASS, "${OTSDAQ_LIB}/libGatewaySupervisor.so"),
33  std::make_pair(XDAQContextTable::ARTDAQ_SUPERVISOR_CLASS, "${OTSDAQ_LIB}/libARTDAQSupervisor.so"),
34  std::make_pair(*(std::next(XDAQContextTable::FETypeClassNames_.begin(),2)), "${OTSDAQ_LIB}/libCoreSupervisors.so"),
35  std::make_pair(*(std::next(XDAQContextTable::FETypeClassNames_.begin(),1)), "${OTSDAQ_LIB}/libCoreSupervisors.so"),
36  std::make_pair(*(XDAQContextTable::FETypeClassNames_.begin()), "${OTSDAQ_LIB}/libCoreSupervisors.so"),
37  std::make_pair(*(std::next(XDAQContextTable::DMTypeClassNames_.begin(),2)), "${OTSDAQ_LIB}/libCoreSupervisors.so"),
38  std::make_pair(*(std::next(XDAQContextTable::DMTypeClassNames_.begin(),1)), "${OTSDAQ_LIB}/libCoreSupervisors.so"),
39  std::make_pair(*(XDAQContextTable::DMTypeClassNames_.begin()), "${OTSDAQ_LIB}/libCoreSupervisors.so"),
40  std::make_pair(*(std::next(XDAQContextTable::LogbookTypeClassNames_.begin(),1)), "${OTSDAQ_UTILITIES_LIB}/libLogbook.so"),
41  std::make_pair(*(XDAQContextTable::LogbookTypeClassNames_.begin()), "${OTSDAQ_UTILITIES_LIB}/libECLWriter.so"),
42  std::make_pair(*(XDAQContextTable::MacroMakerTypeClassNames_.begin()), "${OTSDAQ_UTILITIES_LIB}/libMacroMaker.so"),
43  std::make_pair(*(XDAQContextTable::ChatTypeClassNames_.begin()), "${OTSDAQ_UTILITIES_LIB}/libChat.so"),
44  std::make_pair(*(XDAQContextTable::ConsoleTypeClassNames_.begin()), "${OTSDAQ_UTILITIES_LIB}/libConsole.so"),
45  std::make_pair(*(XDAQContextTable::ConfigurationGUITypeClassNames_.begin()), "${OTSDAQ_UTILITIES_LIB}/libConfigurationGUI.so"),
46  std::make_pair(*(XDAQContextTable::CodeEditorTypeClassNames_.begin()), "${OTSDAQ_LIB}/libCodeEditor.so"),
47  std::make_pair(*(XDAQContextTable::VisualizerTypeClassNames_.begin()), "${OTSDAQ_UTILITIES_LIB}/libVisualization.so"),
48  std::make_pair(*(XDAQContextTable::SlowControlsTypeClassNames_.begin()), "${OTSDAQ_UTILITIES_LIB}/libSlowControlsDashboard.so")
49 };
90 const unsigned int XDAQContextTable::XDAQApplication::GATEWAY_APP_ID = 200;
91 
92 XDAQContextTable::ColContext XDAQContextTable::colContext_ = XDAQContextTable::ColContext(); // initialize static member
93 XDAQContextTable::ColApplication XDAQContextTable::colApplication_ = XDAQContextTable::ColApplication(); // initialize static member
94 XDAQContextTable::ColApplicationProperty XDAQContextTable::colAppProperty_ = XDAQContextTable::ColApplicationProperty(); // initialize static member
95 
96 // clang-format on
97 
98 //==============================================================================
99 XDAQContextTable::XDAQContextTable(void)
100  : TableBase(ConfigurationManager::XDAQ_CONTEXT_TABLE_NAME)
101  , artdaqSupervisorContext_((unsigned int)-1)
102 {
104  // WARNING: the names used in C++ MUST match the Table INFO //
106 
107  // KEEP FOR DEBUGGING next traversal order through set
108  // for(auto &lu:AppClassModuleLookup_)
109  // __COUT__ << lu.first << " " << lu.second << __E__;
110 
111  // __COUTV__(*(XDAQContextTable::FETypeClassNames_.begin()));
112  // __COUTV__(*(std::next(XDAQContextTable::FETypeClassNames_.begin(),1)));
113  // __COUTV__(*(std::next(XDAQContextTable::FETypeClassNames_.begin(),2)));
114 } // end constructor
115 
116 //==============================================================================
117 XDAQContextTable::~XDAQContextTable(void) {}
118 
119 //==============================================================================
121 {
122  //__COUT__ << "init" << __E__;
123  extractContexts(configManager);
124 
125  bool isFirstAppInContext = configManager->isOwnerFirstAppInContext();
126 
127  //__COUTV__(isFirstAppInContext);
128  if(!isFirstAppInContext)
129  return;
130 
131  {
133  // generate xdaq run parameter file
134  std::fstream fs;
135  fs.open(XDAQ_RUN_FILE, std::fstream::out | std::fstream::trunc);
136  if(fs.fail())
137  {
138  __SS__ << "Failed to open XDAQ run file: " << XDAQ_RUN_FILE << __E__;
139  __SS_THROW__;
140  }
141  outputXDAQXML((std::ostream&)fs);
142  fs.close();
143  }
144 } // end init()
145 
146 //==============================================================================
147 std::string XDAQContextTable::getContextAddress(const std::string& contextUID,
148  bool wantHttp) const
149 {
150  if(contextUID == "X")
151  return "";
152  for(auto& context : contexts_)
153  {
154  if(context.contextUID_ == contextUID)
155  {
156  if(wantHttp)
157  return context.address_;
158  size_t i = context.address_.find("://");
159  if(i == std::string::npos)
160  i = 0;
161  else
162  i += 3;
163  return context.address_.substr(i);
164  }
165  }
166  return "";
167 } // end getContextAddress()
168 
169 //==============================================================================
171  const
172 {
173  if(artdaqSupervisorContext_ >= contexts_.size())
174  return nullptr;
175  return &contexts_[artdaqSupervisorContext_];
176 } // end getTheARTDAQSupervisorContext()
177 
178 //==============================================================================
179 ConfigurationTree XDAQContextTable::getContextNode(
180  const ConfigurationManager* configManager, const std::string& contextUID)
181 {
182  return configManager->getNode(ConfigurationManager::XDAQ_CONTEXT_TABLE_NAME)
183  .getNode(contextUID);
184 } // end getContextNode()
185 
186 //==============================================================================
187 ConfigurationTree XDAQContextTable::getApplicationNode(
188  const ConfigurationManager* configManager,
189  const std::string& contextUID,
190  const std::string& appUID)
191 {
192  return configManager->getNode(ConfigurationManager::XDAQ_CONTEXT_TABLE_NAME)
193  .getNode(contextUID + "/" + colContext_.colLinkToApplicationTable_ + "/" +
194  appUID);
195 } // end getApplicationNode()
196 
197 //==============================================================================
198 ConfigurationTree XDAQContextTable::getSupervisorConfigNode(
199  const ConfigurationManager* configManager,
200  const std::string& contextUID,
201  const std::string& appUID)
202 {
203  return configManager->getNode(ConfigurationManager::XDAQ_CONTEXT_TABLE_NAME)
204  .getNode(contextUID + "/" +
205  XDAQContextTable::colContext_.colLinkToApplicationTable_ + "/" + appUID +
206  "/" + XDAQContextTable::colApplication_.colLinkToSupervisorTable_);
207 } // end getSupervisorConfigNode()
208 
209 //==============================================================================
214 {
215  //__COUT__ << "*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*" << __E__;
216  //__COUT__ << configManager->__SELF_NODE__ << __E__;
217 
218  // __COUT__ << configManager->getNode(this->getTableName()).getValueAsString()
219  // << __E__;
220 
221  auto children = configManager->__SELF_NODE__.getChildren();
222 
223  contexts_.clear(); // reset
224  artdaqSupervisorContext_ = (unsigned int)-1; // reset
225 
226  // Enforce that app IDs do not repeat!
227  // Note: this is important because there are maps in MacroMaker and
228  // SupervisorDescriptorInfoBase that rely on localId() as key
229  std::set<unsigned int /*appId*/> appIdSet;
230 
231  for(auto& child : children)
232  {
233  contexts_.push_back(XDAQContext());
234  //__COUT__ << child.first << __E__;
235  // __COUT__ << child.second.getNode(colContextUID_) << __E__;
236 
237  contexts_.back().contextUID_ = child.first;
238 
239  contexts_.back().sourceConfig_ =
240  child.second.getTableName() + "_v" +
241  child.second.getTableVersion().toString() + " @ " +
242  std::to_string(child.second.getTableCreationTime());
243  child.second.getNode(colContext_.colContextUID_)
244  .getValue(contexts_.back().contextUID_);
245  child.second.getNode(colContext_.colStatus_).getValue(contexts_.back().status_);
246  child.second.getNode(colContext_.colId_).getValue(contexts_.back().id_);
247  child.second.getNode(colContext_.colAddress_).getValue(contexts_.back().address_);
248  child.second.getNode(colContext_.colPort_).getValue(contexts_.back().port_);
249 
250  // help the user out if the config has old defaults for port/address
251  // Same as CorePropertySupervisorBase.cc:indicateOtsAlive:L156
252  if(contexts_.back().port_ == 0) // convert 0 to ${OTS_MAIN_PORT}
253  contexts_.back().port_ = atoi(__ENV__("OTS_MAIN_PORT"));
254  if(contexts_.back().address_ ==
255  "DEFAULT") // convert DEFAULT to http://${HOSTNAME}
256  contexts_.back().address_ = "http://" + std::string(__ENV__("HOSTNAME"));
257  if(contexts_.back().port_ < 1024 || contexts_.back().port_ > 49151)
258  {
259  __SS__ << "Illegal xdaq Context port: " << contexts_.back().port_
260  << ". Port must be between 1024 and 49151." << __E__;
261  }
262  // child.second.getNode(colContext_.colARTDAQDataPort_).getValue(contexts_.back().artdaqDataPort_);
263 
264  //__COUT__ << contexts_.back().address_ << __E__;
265  auto appLink = child.second.getNode(colContext_.colLinkToApplicationTable_);
266  if(appLink.isDisconnected())
267  {
268  __SS__ << "Application link is disconnected!" << __E__;
269  __SS_THROW__;
270  }
271 
272  // add xdaq applications to this context
273  auto appChildren = appLink.getChildren();
274  for(auto appChild : appChildren)
275  {
276  //__COUT__ << "Loop: " << child.first << "/" << appChild.first << __E__;
277 
278  contexts_.back().applications_.push_back(XDAQApplication());
279 
280  contexts_.back().applications_.back().applicationGroupID_ = child.first;
281  contexts_.back().applications_.back().sourceConfig_ =
282  appChild.second.getTableName() + "_v" +
283  appChild.second.getTableVersion().toString() + " @ " +
284  std::to_string(appChild.second.getTableCreationTime());
285 
286  appChild.second.getNode(colApplication_.colApplicationUID_)
287  .getValue(contexts_.back().applications_.back().applicationUID_);
288  appChild.second.getNode(colApplication_.colStatus_)
289  .getValue(contexts_.back().applications_.back().status_);
290  appChild.second.getNode(colApplication_.colClass_)
291  .getValue(contexts_.back().applications_.back().class_);
292  appChild.second.getNode(colApplication_.colId_)
293  .getValue(contexts_.back().applications_.back().id_);
294 
295  // infer Gateway is XDAQContextTable::XDAQApplication::GATEWAY_APP_ID from default
296  if(appChild.second.getNode(colApplication_.colId_).isDefaultValue() &&
297  (contexts_.back().applications_.back().class_ ==
298  XDAQContextTable::GATEWAY_SUPERVISOR_CLASS ||
299  contexts_.back().applications_.back().class_ ==
300  XDAQContextTable::DEPRECATED_SUPERVISOR_CLASS))
301  {
302  contexts_.back().applications_.back().id_ =
303  XDAQContextTable::XDAQApplication::GATEWAY_APP_ID;
304  }
305 
306  // assert Gateway is XDAQContextTable::XDAQApplication::GATEWAY_APP_ID
307  if((contexts_.back().applications_.back().id_ ==
308  XDAQContextTable::XDAQApplication::GATEWAY_APP_ID &&
309  contexts_.back().applications_.back().class_ !=
310  XDAQContextTable::GATEWAY_SUPERVISOR_CLASS &&
311  contexts_.back().applications_.back().class_ !=
312  XDAQContextTable::DEPRECATED_SUPERVISOR_CLASS) ||
313  (contexts_.back().applications_.back().id_ !=
314  XDAQContextTable::XDAQApplication::GATEWAY_APP_ID &&
315  (contexts_.back().applications_.back().class_ ==
316  XDAQContextTable::GATEWAY_SUPERVISOR_CLASS ||
317  contexts_.back().applications_.back().class_ ==
318  XDAQContextTable::DEPRECATED_SUPERVISOR_CLASS)))
319  {
320  __SS__ << "XDAQ Application ID of "
321  << XDAQContextTable::XDAQApplication::GATEWAY_APP_ID
322  << " is reserved for the Gateway Supervisor's class '"
323  << XDAQContextTable::GATEWAY_SUPERVISOR_CLASS
324  << ".' There must be one and only one XDAQ supervisor application "
325  "specified with ID '"
326  << XDAQContextTable::XDAQApplication::GATEWAY_APP_ID
327  << "' and class '" << XDAQContextTable::GATEWAY_SUPERVISOR_CLASS
328  << ".' A conflict was found specifically at appName="
329  << contexts_.back().applications_.back().applicationUID_
330  << " with id=" << contexts_.back().applications_.back().id_
331  << " and class=" << contexts_.back().applications_.back().class_
332  << __E__;
333  __SS_THROW__;
334  }
335 
336  // assert NO app id repeats if context/app enabled
337  if(contexts_.back().status_ && contexts_.back().applications_.back().status_)
338  {
339  // assert NO app id repeats
340  if(appIdSet.find(contexts_.back().applications_.back().id_) !=
341  appIdSet.end())
342  {
343  __SS__ << "XDAQ Application IDs are not unique; this could be due to "
344  "multiple instances of the same XDAQ application linked to "
345  "from two "
346  "seperate XDAQ Contexts (check all enabled XDAQ Contexts "
347  "for replicated application IDs). Specifically, there is a "
348  "duplicate at id="
349  << contexts_.back().applications_.back().id_ << " appName="
350  << contexts_.back().applications_.back().applicationUID_
351  << __E__;
352  __COUT_ERR__ << "\n" << ss.str();
353  __SS_THROW__;
354  }
355  appIdSet.insert(contexts_.back().applications_.back().id_);
356  }
357 
358  // convert defaults to values
359  if(appChild.second.getNode(colApplication_.colInstance_).isDefaultValue())
360  contexts_.back().applications_.back().instance_ = 1;
361  else
362  appChild.second.getNode(colApplication_.colInstance_)
363  .getValue(contexts_.back().applications_.back().instance_);
364 
365  if(appChild.second.getNode(colApplication_.colNetwork_).isDefaultValue())
366  contexts_.back().applications_.back().network_ = "local";
367  else
368  appChild.second.getNode(colApplication_.colNetwork_)
369  .getValue(contexts_.back().applications_.back().network_);
370 
371  if(appChild.second.getNode(colApplication_.colGroup_).isDefaultValue())
372  contexts_.back().applications_.back().group_ = "daq";
373  else
374  appChild.second.getNode(colApplication_.colGroup_)
375  .getValue(contexts_.back().applications_.back().group_);
376 
377  // force deprecated Supervisor to GatewaySupervisor class
378  if(contexts_.back().applications_.back().class_ ==
379  XDAQContextTable::DEPRECATED_SUPERVISOR_CLASS)
380  {
381  contexts_.back().applications_.back().class_ =
382  XDAQContextTable::GATEWAY_SUPERVISOR_CLASS;
383  __COUT__ << "Fixing deprecated Supervisor class from "
384  << XDAQContextTable::DEPRECATED_SUPERVISOR_CLASS << " to "
385  << (contexts_.back().applications_.back().class_);
386  }
387 
388  if(contexts_.back().applications_.back().class_ ==
389  XDAQContextTable::GATEWAY_SUPERVISOR_CLASS &&
390  contexts_.back().applications_.back().module_.find("libSupervisor.so") !=
391  std::string::npos)
392  {
393  __COUT__ << "Fixing deprecated Supervisor class from "
394  << contexts_.back().applications_.back().module_ << " to ";
395  contexts_.back().applications_.back().module_ =
396  contexts_.back().applications_.back().module_.substr(
397  0,
398  contexts_.back().applications_.back().module_.size() -
399  std::string("Supervisor.so").size()) +
400  "GatewaySupervisor.so";
401  std::cout << contexts_.back().applications_.back().module_ << __E__;
402  }
403 
404  // __COUT__ << "CHECK Inferred module of '" << contexts_.back().applications_.back().applicationUID_ << "' as '" <<
405  // contexts_.back().applications_.back().module_ << "' " << (appChild.second.getNode(colApplication_.colModule_).isDefaultValue()?"YES":"NO") <<
406  // __E__;
407 
408  // if module is default, attempt to resolve from class
409  if(contexts_.back().applications_.back().id_ ==
410  XDAQContextTable::XDAQApplication::
411  GATEWAY_APP_ID) // force correct Gateway Supervisor module
412  contexts_.back().applications_.back().module_ =
414  XDAQContextTable::GATEWAY_SUPERVISOR_CLASS);
415  else if(appChild.second.getNode(colApplication_.colModule_)
416  .isDefaultValue() &&
418  contexts_.back().applications_.back().class_) !=
420  {
421  contexts_.back().applications_.back().module_ =
423  contexts_.back().applications_.back().class_);
424  __COUT__ << "Inferred module of '"
425  << contexts_.back().applications_.back().applicationUID_
426  << "' as '" << contexts_.back().applications_.back().module_
427  << "' based on class '"
428  << contexts_.back().applications_.back().class_ << "'" << __E__;
429  }
430  else // keep module env variable!! so do getValueAsString()
431  contexts_.back().applications_.back().module_ =
432  appChild.second.getNode(colApplication_.colModule_)
433  .getValueAsString();
434 
435  try
436  {
437  appChild.second.getNode(colApplication_.colConfigurePriority_)
438  .getValue(contexts_.back()
439  .applications_.back()
440  .stateMachineCommandPriority_["Configure"]);
441  appChild.second.getNode(colApplication_.colStartPriority_)
442  .getValue(contexts_.back()
443  .applications_.back()
444  .stateMachineCommandPriority_["Start"]);
445  appChild.second.getNode(colApplication_.colStopPriority_)
446  .getValue(contexts_.back()
447  .applications_.back()
448  .stateMachineCommandPriority_["Stop"]);
449  }
450  catch(...)
451  {
452  __COUT__ << "Ignoring missing state machine priorities..." << __E__;
453  }
454 
455  auto appPropertyLink =
456  appChild.second.getNode(colApplication_.colLinkToPropertyTable_);
457  if(!appPropertyLink.isDisconnected())
458  {
459  // add xdaq application properties to this context
460 
461  auto appPropertyChildren = appPropertyLink.getChildren();
462 
463  //__COUT__ << "appPropertyChildren.size() " << appPropertyChildren.size()
464  //<< __E__;
465 
466  for(auto appPropertyChild : appPropertyChildren)
467  {
468  contexts_.back().applications_.back().properties_.push_back(
470  contexts_.back().applications_.back().properties_.back().status_ =
471  appPropertyChild.second.getNode(colAppProperty_.colStatus_)
472  .getValue<bool>();
473  contexts_.back().applications_.back().properties_.back().name_ =
474  appPropertyChild.second.getNode(colAppProperty_.colPropertyName_)
475  .getValue<std::string>();
476  contexts_.back().applications_.back().properties_.back().type_ =
477  appPropertyChild.second.getNode(colAppProperty_.colPropertyType_)
478  .getValue<std::string>();
479  contexts_.back().applications_.back().properties_.back().value_ =
480  appPropertyChild.second.getNode(colAppProperty_.colPropertyValue_)
481  .getValue<std::string>();
482 
483  //__COUT__ <<
484  // contexts_.back().applications_.back().properties_.back().name_ <<
485  // __E__;
486  }
487  }
488  // else
489  // __COUT__ << "Disconnected." << __E__;
490  }
491 
492  // check for artdaq Supervisor in context
493  {
494  if(!contexts_.back().status_)
495  continue; // skip if disabled
496 
497  for(auto& app : contexts_.back().applications_)
498  {
499  if(app.class_ == // if artdaq interface supervisor
500  "ots::ARTDAQSupervisor" &&
501  app.status_)
502  {
503  __COUT__ << "Found " << app.class_ << " in context '"
504  << contexts_.back().contextUID_ << "'" << __E__;
505 
506  if(artdaqSupervisorContext_ < contexts_.size())
507  {
508  __SS__ << "Error! Only one artdaq Supervisor is allowed to be "
509  "active - "
510  << "two encountered in context '"
511  << contexts_[artdaqSupervisorContext_].contextUID_
512  << "' and '" << contexts_.back().contextUID_ << "'..."
513  << __E__;
514 
515  artdaqSupervisorContext_ = (unsigned int)-1; // reset
516 
517  __SS_THROW__;
518  }
519 
520  artdaqSupervisorContext_ = contexts_.size() - 1;
521  // break; //continue to look for invalid configuration
522  }
523  } // end artdaq app loop
524 
525  } // end artdaq context handling
526 
527  } // end primary context loop
528 
529 } // end extractContexts()
530 
531 //==============================================================================
532 void XDAQContextTable::outputXDAQXML(std::ostream& out)
533 {
534  // each generated context will look something like this:
535  //<xc:Context id="0" url="http://${SUPERVISOR_SERVER}:${PORT}">
539  //</xc:Context>
540 
541  // print xml header information and declare xc partition
542  out << "<?xml version='1.0'?>\n"
543  << "<xc:Partition \txmlns:xsi\t= \"http://www.w3.org/2001/XMLSchema-instance\"\n"
544  << "\t\txmlns:soapenc\t= \"http://schemas.xmlsoap.org/soap/encoding/\"\n"
545  << "\t\txmlns:xc\t= "
546  "\"http://xdaq.web.cern.ch/xdaq/xsd/2004/XMLConfiguration-30\">\n\n";
547 
548  // print partition open
549  // for each context
550  // open context
551  // for each app in context
552  // print application
553  // print module
554  // close context
555  // close partition
556 
557  char tmp[200];
558  for(XDAQContext& context : contexts_)
559  {
560  //__COUT__ << context.contextUID_ << __E__;
561 
562  sprintf(tmp,
563  "\t<!-- ContextUID='%s' sourceConfig='%s' -->",
564  context.contextUID_.c_str(),
565  context.sourceConfig_.c_str());
566  out << tmp << "\n";
567 
568  if(!context.status_) // comment out if disabled
569  out << "\t<!--\n";
570 
571  sprintf(tmp,
572  "\t<xc:Context id=\"%u\" url=\"%s:%u\">",
573  context.id_,
574  context.address_.c_str(),
575  context.port_);
576  out << tmp << "\n\n";
577 
578  for(XDAQApplication& app : context.applications_)
579  {
580  //__COUT__ << app.id_ << __E__;
581 
582  if(context.status_)
583  {
584  sprintf(
585  tmp,
586  "\t\t<!-- Application GroupID = '%s' UID='%s' sourceConfig='%s' -->",
587  app.applicationGroupID_.c_str(),
588  app.applicationUID_.c_str(),
589  app.sourceConfig_.c_str());
590  out << tmp << "\n";
591 
592  if(!app.status_) // comment out if disabled
593  out << "\t\t<!--\n";
594  }
595 
596  if(app.class_ == "ots::GatewaySupervisor") // add otsdaq icons
597  sprintf(
598  tmp,
599  "\t\t<xc:Application class=\"%s\" id=\"%u\" instance=\"%u\" "
600  "network=\"%s\" icon=\"/WebPath/images/otsdaqIcons/logo_square.png\" "
601  "icon16x16=\"/WebPath/images/otsdaqIcons/favicon-16x16.png\" "
602  "group=\"%s\">\n",
603  app.class_.c_str(),
604  app.id_,
605  app.instance_,
606  app.network_.c_str(),
607  app.group_.c_str());
608  else
609  sprintf(tmp,
610  "\t\t<xc:Application class=\"%s\" id=\"%u\" instance=\"%u\" "
611  "network=\"%s\" group=\"%s\">\n",
612  app.class_.c_str(),
613  app.id_,
614  app.instance_,
615  app.network_.c_str(),
616  app.group_.c_str());
617  out << tmp;
618 
620  int foundColon = app.class_.rfind(':');
621  if(foundColon >= 0)
622  ++foundColon;
623  else
624  {
625  __SS__ << "Illegal XDAQApplication class name value of '" << app.class_
626  << "' - please check the entry for app ID = " << app.id_ << __E__;
627  __SS_THROW__;
628  }
629  out << "\t\t\t<properties xmlns=\"urn:xdaq-application:"
630  << app.class_.substr(foundColon) << "\" xsi:type=\"soapenc:Struct\">\n";
631 
632  //__COUT__ << "app.properties_ " << app.properties_.size() << __E__;
633  for(XDAQApplicationProperty& appProperty : app.properties_)
634  {
635  if(appProperty.type_ == "ots::SupervisorProperty")
636  continue; // skip ots Property values
637 
638  if(!appProperty.status_)
639  out << "\t\t\t\t<!--\n";
640 
641  sprintf(tmp,
642  "\t\t\t\t<%s xsi:type=\"%s\">%s</%s>\n",
643  appProperty.name_.c_str(),
644  appProperty.type_.c_str(),
645  appProperty.value_.c_str(),
646  appProperty.name_.c_str());
647  out << tmp;
648 
649  if(!appProperty.status_)
650  out << "\t\t\t\t-->\n";
651  }
652  out << "\t\t\t</properties>\n";
654 
655  out << "\t\t</xc:Application>\n";
656 
657  sprintf(tmp, "\t\t<xc:Module>%s</xc:Module>\n", app.module_.c_str());
658  out << tmp;
659 
660  if(context.status_ && !app.status_)
661  out << "\t\t-->\n";
662  out << "\n";
663 
664  // __COUT__ << "DONE" << __E__;
665  }
666 
667  out << "\t</xc:Context>\n";
668  if(!context.status_)
669  out << "\t-->\n";
670  out << "\n";
671  }
672 
673  //__COUT__ << "DONE" << __E__;
674  out << "</xc:Partition>\n\n\n";
675 }
676 
677 //==============================================================================
678 std::string XDAQContextTable::getContextUID(const std::string& url) const
679 {
680  for(auto context : contexts_)
681  {
682  if(!context.status_)
683  continue;
684 
685  if(url == context.address_ + ":" + std::to_string(context.port_))
686  return context.contextUID_;
687  }
688  return "";
689 }
690 
691 //==============================================================================
692 std::string XDAQContextTable::getApplicationUID(const std::string& url,
693  unsigned int id) const
694 {
695  //__COUTV__(url); __COUTV__(id);
696  for(auto context : contexts_)
697  {
698  //__COUT__ << "Checking " << (context.address_ + ":" +
699  // std::to_string(context.port_)) << __E__;
700  //__COUTV__(context.status_);
701 
702  if(!context.status_)
703  continue;
704 
705  //__COUT__ << "Checking " << (context.address_ + ":" +
706  // std::to_string(context.port_)) << __E__;
707  if(url == context.address_ + ":" + std::to_string(context.port_))
708  for(auto application : context.applications_)
709  {
710  //__COUTV__(application.status_); __COUTV__(application.id_);
711  if(!application.status_)
712  continue;
713 
714  if(application.id_ == id)
715  {
716  return application.applicationUID_;
717  }
718  }
719  }
720  return "";
721 } // end getApplicationUID()
722 
723 //==============================================================================
726  const std::string& appUID) const
727 {
728  // look through all contexts until first appUID found
729 
730  auto childrenMap = configManager->__SELF_NODE__.getChildren();
731 
732  for(auto& context : childrenMap)
733  {
734  if(!context.second.getNode(XDAQContextTable::colContext_.colStatus_)
735  .getValue<bool>())
736  continue;
737 
738  ConfigurationTree appLink = context.second.getNode(
739  XDAQContextTable::colContext_.colLinkToApplicationTable_);
740  if(appLink.isDisconnected())
741  continue;
742 
743  auto appMap = appLink.getChildren();
744  for(auto& app : appMap)
745  {
746  if(!app.second.getNode(XDAQContextTable::colApplication_.colStatus_)
747  .getValue<bool>())
748  continue;
749 
750  if(app.first == appUID)
751  return context.first; // return context UID
752  } // end app search loop
753  } // end context search loop
754 
755  __SS__ << "Application '" << appUID << "' search found no parent context!" << __E__;
756  // ss << StringMacros::stackTrace() << __E__;
757  __SS_THROW__;
758 } // end getContextOfApplication()
759 
760 //==============================================================================
763  ConfigurationManager* configManager) const
764 {
765  // look through all contexts until first gateway found
766 
767  auto childrenMap = configManager->__SELF_NODE__.getChildren();
768 
769  for(auto& context : childrenMap)
770  {
771  if(!context.second.getNode(XDAQContextTable::colContext_.colStatus_)
772  .getValue<bool>())
773  continue;
774 
775  ConfigurationTree appLink = context.second.getNode(
776  XDAQContextTable::colContext_.colLinkToApplicationTable_);
777  if(appLink.isDisconnected())
778  continue;
779 
780  auto appMap = appLink.getChildren();
781  for(auto& app : appMap)
782  {
783  if(!app.second.getNode(XDAQContextTable::colApplication_.colStatus_)
784  .getValue<bool>())
785  continue;
786 
787  std::string className =
788  app.second.getNode(XDAQContextTable::colApplication_.colClass_)
789  .getValue<std::string>();
790  if(className == XDAQContextTable::GATEWAY_SUPERVISOR_CLASS ||
791  className == XDAQContextTable::DEPRECATED_SUPERVISOR_CLASS)
792  return context.first; // return context UID
793  } // end app search loop
794  } // end context search loop
795 
796  __SS__ << "Gateway Application search found no parent context!" << __E__;
797  __SS_THROW__;
798 } // end getContextOfGateway()
ConfigurationTree getNode(const std::string &nodeString, bool doNotThrowOnBrokenUIDLinks=false) const
"root/parent/parent/"
std::vector< std::pair< std::string, ConfigurationTree > > getChildren(std::map< std::string, TableVersion > *memberMap=0, std::string *accumulatedTreeErrors=0) const
bool isDisconnected(void) const
ConfigurationTree getNode(const std::string &nodeName, bool doNotThrowOnBrokenUIDLinks=false) const
navigating between nodes
std::vector< std::pair< std::string, ConfigurationTree > > getChildren(std::map< std::string, std::string > filterMap=std::map< std::string, std::string >(), bool byPriority=false, bool onlyStatusTrue=false) const
void outputXDAQXML(std::ostream &out)
void init(ConfigurationManager *configManager)
Methods.
static const std::map< std::string, std::string > AppClassModuleLookup_
NOTE!!! std::next + offset reads std::set from right-to-left above (end to beginning)
std::string getContextUID(const std::string &url) const
void extractContexts(ConfigurationManager *configManager)
std::string getContextOfGateway(ConfigurationManager *configManager) const
only considers ON contexts and applications
const XDAQContext * getTheARTDAQSupervisorContext(void) const
artdaq specific get methods
std::string getContextOfApplication(ConfigurationManager *configManager, const std::string &appUID) const
only considers ON contexts and applications
XDAQ Context Column names.