otsdaq  v2_05_02_indev
AllSupervisorInfo.cc
1 #include "otsdaq/SupervisorInfo/AllSupervisorInfo.h"
2 
3 #include "otsdaq/Macros/CoutMacros.h"
4 #include "otsdaq/MessageFacility/MessageFacility.h"
5 
6 #include "otsdaq/ConfigurationInterface/ConfigurationManager.h"
7 #include "otsdaq/TablePlugins/XDAQContextTable.h"
8 
9 #include <iostream>
10 
11 using namespace ots;
12 
13 const bool AllSupervisorInfo::MACROMAKER_MODE = ((getenv("MACROMAKER_MODE") == NULL) // check Macro Maker mode environment variable in a safe way
14  ? (false)
15  : ((std::string(__ENV__("MACROMAKER_MODE")) == "1") ? true : false));
16 
17 //==============================================================================
18 AllSupervisorInfo::AllSupervisorInfo(void) : theSupervisorInfo_(0), theWizardInfo_(0) {}
19 
20 //==============================================================================
21 AllSupervisorInfo::AllSupervisorInfo(xdaq::ApplicationContext* applicationContext) : AllSupervisorInfo() { init(applicationContext); }
22 
23 //==============================================================================
24 AllSupervisorInfo::~AllSupervisorInfo(void) { destroy(); }
25 
26 //==============================================================================
27 void AllSupervisorInfo::destroy(void)
28 {
29  allSupervisorInfo_.clear();
30  allFETypeSupervisorInfo_.clear();
31  allDMTypeSupervisorInfo_.clear();
32 
33  theSupervisorInfo_ = 0;
34  theWizardInfo_ = 0;
35 
36  SupervisorDescriptorInfoBase::destroy();
37 } // end destroy()
38 
39 //==============================================================================
40 void AllSupervisorInfo::init(xdaq::ApplicationContext* applicationContext)
41 {
42  __COUT__ << "Initializing info based on XDAQ context..." << __E__;
43 
44  AllSupervisorInfo::destroy();
45  SupervisorDescriptorInfoBase::init(applicationContext);
46 
47  auto allDescriptors = SupervisorDescriptorInfoBase::getAllDescriptors();
48  // ready.. loop through all descriptors, and organize
49 
50  // for(const auto& descriptor:allDescriptors)
51  // {
52  // SupervisorInfo tempSupervisorInfo(
53  // descriptor.second /* descriptor */,
54  // "" /* config app name */,"" /* config parent context name */
56  // );
57  //
58  // __COUT__ << "id " << descriptor.second->getLocalId() << " url " <<
59  // descriptor.second->getContextDescriptor()->getURL() << __E__;
60  //
61  // }
62  // __COUTV__(XDAQContextTable::GATEWAY_SUPERVISOR_CLASS);
63 
64  // Steps:
65  // 1. first pass, identify Wiz mode or not
66  // 2. second pass, organize supervisors
67 
68  bool isWizardMode = false;
69 
70  // first pass, identify Wiz mode or not
71  // accept first encountered (wizard or gateway) as the mode
72  for(const auto& descriptor : allDescriptors)
73  {
74  SupervisorInfo tempSupervisorInfo(
75  descriptor.second /* descriptor */, "" /* config app name */, "" /* config parent context name */ // skip configuration info
76  );
77 
78  // check for gateway supervisor
79  if(tempSupervisorInfo.isGatewaySupervisor())
80  {
81  // found normal mode, done with first pass
82  isWizardMode = false;
83  break;
84  }
85  else if(tempSupervisorInfo.isWizardSupervisor())
86  {
87  // found wiz mode, done with first pass
88  isWizardMode = true;
89  break;
90  }
91  }
92 
93  if(AllSupervisorInfo::MACROMAKER_MODE)
94  __COUT__ << "Initializing info for Macro Maker mode XDAQ context..." << __E__;
95  else if(isWizardMode)
96  __COUT__ << "Initializing info for Wiz mode XDAQ context..." << __E__;
97  else
98  __COUT__ << "Initializing info for Normal mode XDAQ context..." << __E__;
99  std::unique_ptr<ConfigurationManager> cfgMgr((isWizardMode || AllSupervisorInfo::MACROMAKER_MODE) ? 0 : new ConfigurationManager());
100  const XDAQContextTable* contextConfig = (isWizardMode || AllSupervisorInfo::MACROMAKER_MODE) ? 0 : cfgMgr->__GET_CONFIG__(XDAQContextTable);
101 
102  // do not involve the Configuration Manager
103  // as it adds no valid information to the supervisors
104  // present in wiz mode
105  for(const auto& descriptor : allDescriptors)
106  {
107  auto /*<iterator,bool>*/ emplacePair = allSupervisorInfo_.emplace(std::pair<unsigned int, SupervisorInfo>(
108  descriptor.second->getLocalId(), // descriptor.first,
110  descriptor.second /* descriptor */,
111  contextConfig ? contextConfig->getApplicationUID(descriptor.second->getContextDescriptor()->getURL(), descriptor.second->getLocalId())
112  : "" /* config app name */,
113  contextConfig ? contextConfig->getContextUID(descriptor.second->getContextDescriptor()->getURL()) : "" /* config parent context name */
114  )));
115  if(!emplacePair.second)
116  {
117  __SS__ << "Error! Duplicate Application IDs are not allowed. ID =" << descriptor.second->getLocalId() << __E__;
118  __SS_THROW__;
119  }
120 
122  // now organize new descriptor by class...
123 
124  // check for gateway supervisor
125  // note: necessarily exclusive to other Supervisor types
126  if(emplacePair.first->second.isGatewaySupervisor())
127  {
128  if(theSupervisorInfo_)
129  {
130  __SS__ << "Error! Multiple Gateway Supervisors of class " << XDAQContextTable::GATEWAY_SUPERVISOR_CLASS
131  << " found. There can only be one. ID =" << descriptor.second->getLocalId() << __E__;
132  __SS_THROW__;
133  }
134  // copy and erase from map
135  theSupervisorInfo_ = &(emplacePair.first->second);
136  continue;
137  }
138 
139  // check for wizard supervisor
140  // note: necessarily exclusive to other Supervisor types
141  if(emplacePair.first->second.isWizardSupervisor())
142  {
143  if(theWizardInfo_)
144  {
145  __SS__ << "Error! Multiple Wizard Supervisors of class " << XDAQContextTable::WIZARD_SUPERVISOR_CLASS
146  << " found. There can only be one. ID =" << descriptor.second->getLocalId() << __E__;
147  __SS_THROW__;
148  }
149  // copy and erase from map
150  theWizardInfo_ = &(emplacePair.first->second);
151  continue;
152  }
153 
154  // check for FE type, then add to FE group
155  // note: not necessarily exclusive to other Supervisor types
156  if(emplacePair.first->second.isTypeFESupervisor())
157  {
158  allFETypeSupervisorInfo_.emplace(std::pair<unsigned int, const SupervisorInfo&>(emplacePair.first->second.getId(), emplacePair.first->second));
159  }
160 
161  // check for DM type, then add to DM group
162  // note: not necessarily exclusive to other Supervisor types
163  if(emplacePair.first->second.isTypeDMSupervisor())
164  {
165  allDMTypeSupervisorInfo_.emplace(std::pair<unsigned int, const SupervisorInfo&>(emplacePair.first->second.getId(), emplacePair.first->second));
166  }
167 
168  // check for Logbook type, then add to Logbook group
169  // note: not necessarily exclusive to other Supervisor types
170  if(emplacePair.first->second.isTypeLogbookSupervisor())
171  {
172  allLogbookTypeSupervisorInfo_.emplace(std::pair<unsigned int, const SupervisorInfo&>(emplacePair.first->second.getId(), emplacePair.first->second));
173  }
174 
175  // check for MacroMaker type, then add to MacroMaker group
176  // note: not necessarily exclusive to other Supervisor types
177  if(emplacePair.first->second.isTypeMacroMakerSupervisor())
178  {
179  allMacroMakerTypeSupervisorInfo_.emplace(
180  std::pair<unsigned int, const SupervisorInfo&>(emplacePair.first->second.getId(), emplacePair.first->second));
181  }
182 
183  } // end main extraction loop
184 
185  if(AllSupervisorInfo::MACROMAKER_MODE)
186  {
187  if(theWizardInfo_ || theSupervisorInfo_)
188  {
189  __SS__ << "Error! For MacroMaker mode, must not have one " << XDAQContextTable::GATEWAY_SUPERVISOR_CLASS << " OR one "
190  << XDAQContextTable::WIZARD_SUPERVISOR_CLASS << " as part of the context configuration! "
191  << "One was found." << __E__;
192  __SS_THROW__;
193  }
194  }
195  else if((!theWizardInfo_ && !theSupervisorInfo_) || (theWizardInfo_ && theSupervisorInfo_))
196  {
197  __SS__ << "Error! Must have one " << XDAQContextTable::GATEWAY_SUPERVISOR_CLASS << " OR one " << XDAQContextTable::WIZARD_SUPERVISOR_CLASS
198  << " as part of the context configuration! "
199  << "Neither (or both) were found." << __E__;
200  __SS_THROW__;
201  }
202 
203  SupervisorDescriptorInfoBase::destroy();
204 
205  __COUT__ << "Supervisor Info initialization complete!" << __E__;
206 
207  // for debugging
208  // getOrderedSupervisorDescriptors("Configure");
209 } // end init()
210 
211 //==============================================================================
212 const SupervisorInfo& AllSupervisorInfo::getSupervisorInfo(xdaq::Application* app) const
213 {
214  auto it = allSupervisorInfo_.find(app->getApplicationDescriptor()->getLocalId());
215  if(it == allSupervisorInfo_.end())
216  {
217  __SS__ << "Could not find: " << app->getApplicationDescriptor()->getLocalId() << std::endl;
218  __SS_THROW__;
219  }
220  return it->second;
221 }
222 
223 //==============================================================================
224 void AllSupervisorInfo::setSupervisorStatus(xdaq::Application* app, const std::string& status, const unsigned int progress, const std::string& detail)
225 {
226  setSupervisorStatus(app->getApplicationDescriptor()->getLocalId(), status, progress, detail);
227 }
228 //==============================================================================
229 void AllSupervisorInfo::setSupervisorStatus(const SupervisorInfo& appInfo, const std::string& status, const unsigned int progress, const std::string& detail)
230 {
231  setSupervisorStatus(appInfo.getId(), status, progress, detail);
232 }
233 //==============================================================================
234 void AllSupervisorInfo::setSupervisorStatus(const unsigned int& id, const std::string& status, const unsigned int progress, const std::string& detail)
235 {
236  auto it = allSupervisorInfo_.find(id);
237  if(it == allSupervisorInfo_.end())
238  {
239  __SS__ << "Could not find: " << id << __E__;
240  __SS_THROW__;
241  }
242  it->second.setStatus(status, progress, detail);
243 } // end setSupervisorStatus()
244 
245 //==============================================================================
246 const SupervisorInfo& AllSupervisorInfo::getGatewayInfo(void) const
247 {
248  if(!theSupervisorInfo_)
249  {
250  __SS__ << "AllSupervisorInfo was not initialized or no Application of type " << XDAQContextTable::GATEWAY_SUPERVISOR_CLASS << " found!" << __E__;
251  __SS_THROW__;
252  }
253  return *theSupervisorInfo_;
254 }
255 //==============================================================================
256 XDAQ_CONST_CALL xdaq::ApplicationDescriptor* AllSupervisorInfo::getGatewayDescriptor(void) const { return getGatewayInfo().getDescriptor(); }
257 
258 //==============================================================================
259 const SupervisorInfo& AllSupervisorInfo::getWizardInfo(void) const
260 {
261  if(!theWizardInfo_)
262  {
263  __SS__ << "AllSupervisorInfo was not initialized or no Application of type " << XDAQContextTable::WIZARD_SUPERVISOR_CLASS << " found!" << __E__;
264  __SS_THROW__;
265  }
266  return *theWizardInfo_;
267 }
268 //==============================================================================
269 XDAQ_CONST_CALL xdaq::ApplicationDescriptor* AllSupervisorInfo::getWizardDescriptor(void) const { return getWizardInfo().getDescriptor(); }
270 
271 //==============================================================================
272 std::vector<std::vector<const SupervisorInfo*>> AllSupervisorInfo::getOrderedSupervisorDescriptors(const std::string& stateMachineCommand) const
273 {
274  __COUT__ << "getOrderedSupervisorDescriptors" << __E__;
275 
276  std::map<uint64_t /*priority*/, std::vector<unsigned int /*appId*/>> orderedByPriority;
277 
278  try
279  {
280  ConfigurationManager cfgMgr;
281  const std::vector<XDAQContextTable::XDAQContext>& contexts = cfgMgr.__GET_CONFIG__(XDAQContextTable)->getContexts();
282 
283  for(const auto& context : contexts)
284  if(context.status_)
285  for(const auto& app : context.applications_)
286  {
287  if(!app.status_)
288  continue; // skip disabled apps
289 
290  auto it = app.stateMachineCommandPriority_.find(stateMachineCommand);
291  if(it == app.stateMachineCommandPriority_.end())
292  orderedByPriority[XDAQContextTable::XDAQApplication::DEFAULT_PRIORITY].push_back(
293  app.id_); // if no priority, then default to
294  // XDAQContextTable::XDAQApplication::DEFAULT_PRIORITY
295  else // take value, and do not allow DEFAULT value of 0 -> force to
296  // XDAQContextTable::XDAQApplication::DEFAULT_PRIORITY
297  orderedByPriority[it->second ? it->second : XDAQContextTable::XDAQApplication::DEFAULT_PRIORITY].push_back(app.id_);
298 
299  //__COUT__ << "app.id_ " << app.id_ << __E__;
300  }
301  }
302  catch(...)
303  {
304  __COUT_ERR__ << "SupervisorDescriptorInfoBase could not access the XDAQ Context "
305  "and Application configuration through the Context Table "
306  "Group."
307  << __E__;
308  throw;
309  }
310 
311  __COUT__ << "Here is the order supervisors will be " << stateMachineCommand << "'d:" << __E__;
312 
313  // return ordered set of supervisor infos
314  // skip over Gateway Supervisor,
315  // and other supervisors that do not need state transitions.
316  std::vector<std::vector<const SupervisorInfo*>> retVec;
317  bool createContainer;
318  for(const auto& priorityAppVector : orderedByPriority)
319  {
320  createContainer = true;
321 
322  for(const auto& priorityApp : priorityAppVector.second)
323  {
324  auto it = allSupervisorInfo_.find(priorityApp);
325  if(it == allSupervisorInfo_.end())
326  {
327  __SS__ << "Error! Was AllSupervisorInfo properly initialized? The app.id_ " << priorityApp << " priority "
328  << (unsigned int)priorityAppVector.first << " could not be found in AllSupervisorInfo." << __E__;
329  __SS_THROW__;
330  }
331 
332  //__COUT__ << it->second.getName() << " [" << it->second.getId() << "]: " << "
333  // priority? " << (unsigned int)priorityAppVector.first <<
334  //__E__;
335 
336  if(it->second.isGatewaySupervisor())
337  continue; // skip gateway supervisor
338  if(it->second.isTypeLogbookSupervisor())
339  continue; // skip logbook supervisor(s)
340  if(it->second.isTypeMacroMakerSupervisor())
341  continue; // skip macromaker supervisor(s)
342  if(it->second.isTypeConfigurationGUISupervisor())
343  continue; // skip configurationGUI supervisor(s)
344  if(it->second.isTypeChatSupervisor())
345  continue; // skip chat supervisor(s)
346  if(it->second.isTypeConsoleSupervisor())
347  continue; // skip console supervisor(s)
348 
349  if(createContainer) // create container first time
350  {
351  retVec.push_back(std::vector<const SupervisorInfo*>());
352 
353  // if default priority, create a new vector container for each entry
354  // so they happen in sequence by default
355  // if(priorityAppVector.first !=
356  // XDAQContextTable::XDAQApplication::DEFAULT_PRIORITY)
357  // createContainer = false;
358 
359  createContainer = false;
360  }
361  retVec[retVec.size() - 1].push_back(&(it->second));
362 
363  __COUT__ << it->second.getName() << " [LID=" << it->second.getId() << "]: "
364  << " priority " << (unsigned int)priorityAppVector.first << " count " << retVec[retVec.size() - 1].size() << __E__;
365  }
366  } // end equal priority loop
367  return retVec;
368 }