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