otsdaq  3.11.00
CoreSupervisorBase.cc
1 #include "otsdaq/CoreSupervisors/CoreSupervisorBase.h"
2 
3 #include <iostream>
4 
5 using namespace ots;
6 
7 // XDAQ_INSTANTIATOR_IMPL(CoreSupervisorBase)
8 
9 const std::string CoreSupervisorBase::WORK_LOOP_DONE = "Done";
10 const std::string CoreSupervisorBase::WORK_LOOP_WORKING = "Working";
11 
12 //==============================================================================
13 CoreSupervisorBase::CoreSupervisorBase(xdaq::ApplicationStub* stub)
14  : xdaq::Application(stub)
15  , SOAPMessenger(this)
18  CorePropertySupervisorBase::allSupervisorInfo_.isWizardMode()
19  ? // set state machine name
20  CorePropertySupervisorBase::supervisorClassNoNamespace_
21  : CorePropertySupervisorBase::supervisorClassNoNamespace_ + ":" +
22  CorePropertySupervisorBase::getSupervisorUID())
23  , stateMachineWorkLoopManager_(toolbox::task::bind(
24  this, &CoreSupervisorBase::stateMachineThread, "StateMachine"))
25  , stateMachineSemaphore_(toolbox::BSem::FULL)
26  , theRemoteWebUsers_(this,
27  CorePropertySupervisorBase::getGatewaySupervisorDescriptor())
28 {
29  __SUP_COUT__ << "Constructor." << __E__;
30 
31  INIT_MF("." /*directory used is USER_DATA/LOG/.*/);
32 
33  xgi::bind(this, &CoreSupervisorBase::defaultPageWrapper, "Default");
34  xgi::bind(this, &CoreSupervisorBase::requestWrapper, "Request");
35 
36  xgi::bind(
37  this, &CoreSupervisorBase::stateMachineXgiHandler, "StateMachineXgiHandler");
38 
39  xoap::bind(this,
40  &CoreSupervisorBase::stateMachineStateRequest,
41  "StateMachineStateRequest",
42  XDAQ_NS_URI);
43  xoap::bind(this,
44  &CoreSupervisorBase::stateMachineErrorMessageRequest,
45  "StateMachineErrorMessageRequest",
46  XDAQ_NS_URI);
47  xoap::bind(this,
48  &CoreSupervisorBase::workLoopStatusRequestWrapper,
49  "WorkLoopStatusRequest",
50  XDAQ_NS_URI);
51  xoap::bind(this,
52  &CoreSupervisorBase::applicationStatusRequest,
53  "ApplicationStatusRequest",
54  XDAQ_NS_URI);
55  xoap::bind(this,
56  &CoreSupervisorBase::TRACESupervisorRequest,
57  "TRACESupervisorRequest",
58  XDAQ_NS_URI);
59  xoap::bind(this,
60  &CoreSupervisorBase::minReadyForEventGenerationStartIterationRequest,
61  "MinReadyForEventGenerationStartIterationRequest",
62  XDAQ_NS_URI);
63  xoap::bind(this,
64  &CoreSupervisorBase::minReadyForEventGenerationStartIterationRequest,
65  "MinReadyForEventGenerationStartIterationRequest",
66  XDAQ_NS_URI);
67 
68  __SUP_COUT__ << "Constructed. getpid()=" << getpid() << " gettid()=" << gettid()
69  << __E__;
70 } // end constructor
71 
72 //==============================================================================
73 CoreSupervisorBase::~CoreSupervisorBase(void)
74 {
75  __SUP_COUT__ << "Destructor." << __E__;
76  destroy();
77  __SUP_COUT__ << "Destructed." << __E__;
78 } // end destructor()
79 
80 //==============================================================================
81 void CoreSupervisorBase::destroy(void)
82 {
83  __SUP_COUT__ << "Destroying..." << __E__;
84  for(auto& it : theStateMachineImplementation_)
85  delete it;
86 
87  theStateMachineImplementation_.clear();
88 } // end destroy()
89 
90 //==============================================================================
92 void CoreSupervisorBase::defaultPageWrapper(xgi::Input* in, xgi::Output* out)
93 {
94  return defaultPage(in, out);
95 }
96 
97 //==============================================================================
98 void CoreSupervisorBase::defaultPage(xgi::Input* /*in*/, xgi::Output* out)
99 {
100  __SUP_COUT__ << "Supervisor class " << supervisorClass_ << __E__;
101 
102  std::stringstream pagess;
103  pagess << "/WebPath/html/" << supervisorClassNoNamespace_
104  << ".html?urn=" << this->getApplicationDescriptor()->getLocalId();
105 
106  __SUP_COUT__ << "Default page = " << pagess.str() << __E__;
107 
108  *out << "<!DOCTYPE HTML><html lang='en'><frameset col='100%' row='100%'><frame src='"
109  << pagess.str() << "'></frameset></html>";
110 } // end defaultPage()
111 
112 //==============================================================================
115 void CoreSupervisorBase::requestWrapper(xgi::Input* in, xgi::Output* out)
116 try
117 {
118  out->getHTTPResponseHeader().addHeader(
119  "Access-Control-Allow-Origin",
120  "*"); // to avoid block by blocked by CORS policy of browser
121  out->getHTTPResponseHeader().addHeader("Pragma", "no-cache");
122 
123  cgicc::Cgicc cgiIn(in);
124  std::string requestType = CgiDataUtilities::getData(cgiIn, "RequestType");
125 
126  __SUP_COUTT__ << "requestType " << requestType
127  << " files: " << cgiIn.getFiles().size() << __E__;
128 
129  HttpXmlDocument xmlOut;
130  WebUsers::RequestUserInfo userInfo(
131  requestType, CgiDataUtilities::getOrPostData(cgiIn, "CookieCode"));
132 
134 
135  if(!theRemoteWebUsers_.xmlRequestToGateway(
136  cgiIn, out, &xmlOut, CorePropertySupervisorBase::allSupervisorInfo_, userInfo))
137  return; // access failed
138 
139  if(requestType == "GetUserDisplayName")
140  {
141  __COUTV__(userInfo.displayName_);
142  xmlOut.addTextElementToData("DisplayName", userInfo.displayName_);
143  xmlOut.outputXmlDocument((std::ostringstream*)out,
144  false /*print to cout*/,
145  !userInfo.NoXmlWhiteSpace_ /*allow whitespace*/);
146  return;
147  }
148 
149  // done checking cookieCode, sequence, userWithLock, and permissions access all in one
150  // shot!
151  //**** end LOGIN GATEWAY CODE ***//
152 
153  if(!userInfo.automatedCommand_)
154  __SUP_COUTT__ << "DIAG ms=" << StringMacros::nowEpochMs()
155  << " requestType: " << requestType << __E__;
156 
157  if(userInfo.NonXMLRequestType_)
158  {
159  try
160  {
161  nonXmlRequest(requestType, cgiIn, *out, userInfo);
162  }
163  catch(const std::runtime_error& e)
164  {
165  __SUP_SS__ << "An error was encountered handling requestType '" << requestType
166  << "':" << e.what() << __E__;
167  __SUP_COUT_ERR__ << "\n" << ss.str();
168  }
169  catch(...)
170  {
171  __SUP_SS__ << "An unknown error was encountered handling requestType '"
172  << requestType << ".' "
173  << "Please check the printouts to debug." << __E__;
174  try
175  {
176  throw;
177  } //one more try to printout extra info
178  catch(const std::exception& e)
179  {
180  ss << "Exception message: " << e.what();
181  }
182  catch(...)
183  {
184  }
185  __SUP_COUT_ERR__ << "\n" << ss.str();
186  }
187  return;
188  }
189  // else xml request type
190 
191  std::chrono::steady_clock::time_point requestStart = std::chrono::steady_clock::now();
192  time_t requestStartTime = time(0);
193 
194  try
195  {
196  // call derived class' request()
197  request(requestType, cgiIn, xmlOut, userInfo);
198  }
199  catch(const std::runtime_error& e)
200  {
201  __SUP_SS__ << "An error was encountered handling requestType '" << requestType
202  << "':" << e.what() << __E__;
203  __SUP_COUT_ERR__ << "\n" << ss.str();
204  xmlOut.addTextElementToData("Error", ss.str());
205  }
206  catch(...)
207  {
208  __SUP_SS__ << "An unknown error was encountered handling requestType '"
209  << requestType << ".' "
210  << "Please check the printouts to debug." << __E__;
211  try
212  {
213  throw;
214  } //one more try to printout extra info
215  catch(const std::exception& e)
216  {
217  ss << "Exception message: " << e.what();
218  }
219  catch(...)
220  {
221  }
222  __SUP_COUT_ERR__ << "\n" << ss.str();
223  xmlOut.addTextElementToData("Error", ss.str());
224  }
225  __SUP_COUTT__ << "Request '" << requestType
226  << "' time: " << artdaq::TimeUtils::GetElapsedTime(requestStart)
227  << __E__;
228 
229  // used to print xml errors only if there are a reasonable number of children
230  if(TTEST(1)) //now just check child size if debugging
231  {
232  size_t numberOfChildren =
233  xmlOut.getRootDataElement()->getChildNodes()->getLength();
234  if(numberOfChildren &&
235  xmlOut.getRootDataElement()->getChildNodes()->item(0)->getNodeType() !=
236  xercesc::DOMNode::TEXT_NODE)
237  numberOfChildren += xmlOut.getRootDataElement()
238  ->getChildNodes()
239  ->item(0)
240  ->getChildNodes()
241  ->getLength();
242 
243  __SUP_COUTT__ << "Number of '" << requestType
244  << "' xml data element children: " << numberOfChildren << __E__;
245 
246  __SUP_COUTT__ << "Request '" << requestType
247  << "' time: " << artdaq::TimeUtils::GetElapsedTime(requestStart)
248  << __E__;
249  }
250  //Note: the above XML-children-count only looks at depth 1, if there are too many nodes (including deeper nodes) then outputing the xml will be slow (4K nodes takes ~2 seconds)
251 
252  // return xml doc holding server response to request
253  xmlOut.outputXmlDocument((std::ostringstream*)out,
254  false /*print to cout*/,
255  !userInfo.NoXmlWhiteSpace_ /*allow whitespace*/,
256  true /* printErrors */); // report any errors encountered
257 
258  if(!userInfo.automatedCommand_)
259  __SUP_COUTT__ << "DIAG ms=" << StringMacros::nowEpochMs()
260  << " requestType: " << requestType << " response written, elapsed="
261  << artdaq::TimeUtils::GetElapsedTime(requestStart) << "s" << __E__;
262 
263  // __SUP_COUTT__ << "Request '" << requestType
264  // << "' time: " << artdaq::TimeUtils::GetElapsedTime(requestStart)
265  // << __E__;
266  // std::stringstream oss;
267  // xmlOut.outputXmlDocument((std::ostringstream*)&oss,
268  // false /*print to cout*/,
269  // !userInfo.NoXmlWhiteSpace_ /*allow whitespace*/,
270  // true /* printErrors */);
271  // __SUP_COUTT__ << "Request '" << requestType
272  // << "' time: " << artdaq::TimeUtils::GetElapsedTime(requestStart)
273  // << __E__;
274  // __SUP_COUTV__(oss.str());
275 
276  __SUP_COUTT__ << "Total '" << requestType << "' xml request time: "
277  << artdaq::TimeUtils::GetElapsedTime(requestStart) << " = "
278  << time(0) - requestStartTime << __E__;
279 } // end requestWrapper()
280 catch(const std::runtime_error& e)
281 {
282  __SUP_SS__ << "An error was encountered handling HTTP request:" << e.what() << __E__;
283  __SUP_COUT_ERR__ << "\n" << ss.str();
284  throw;
285 }
286 catch(...)
287 {
288  __SUP_SS__ << "An unknown error was encountered HTTP request. "
289  << "Please check the printouts to debug." << __E__;
290  try
291  {
292  throw;
293  } //one more try to printout extra info
294  catch(const std::exception& e)
295  {
296  ss << "Exception message: " << e.what();
297  }
298  catch(...)
299  {
300  }
301  __SUP_COUT_ERR__ << "\n" << ss.str();
302  throw;
303 } // end requestWrapper() error handling
304 
305 //==============================================================================
311 void CoreSupervisorBase::request(const std::string& /*requestType*/,
312  cgicc::Cgicc& /*cgiIn*/,
313  HttpXmlDocument& xmlOut,
314  const WebUsers::RequestUserInfo& /*userInfo*/)
315 {
316  __SUP_SS__ << "This is the empty Core Supervisor request. Supervisors should "
317  "override this function."
318  << __E__;
319  __SUP_COUT__ << ss.str();
320  xmlOut.addTextElementToData("Error", ss.str());
321  return;
322 
323  // KEEP:
324  // here are some possibly interesting example lines of code for overriding
325  // supervisors
326  //
327  // try
328  //{
329  //
330  // if(requestType == "savePlanCommandSequence")
331  // {
332  // std::string planName = CgiDataUtilities::getData(cgiIn,"planName");
334  // CgiDataUtilities::postData(cgiIn,"commands");
336  //
337  // cgiIn.getFiles()
338  // __SUP_COUT__ << "planName: " << planName << __E__;
339  // __SUP_COUTV__(commands);
340  //
341  //
342  // }
343  // else
344  // {
345  // __SUP_SS__ << "requestType '" << requestType << "' request not recognized." <<
346  // __E__;
347  // __SUP_SS_THROW__;
348  // }
349  // xmlOut.addTextElementToData("Error",
350  // "request encountered an error!");
351  //}
352  // catch(const std::runtime_error& e)
353  // {
354  // __SUP_SS__ << "An error was encountered handling requestType '" << requestType
355  //<< "':" << e.what() << __E__;
356  // __SUP_COUT_ERR__ << "\n" << ss.str();
357  // xmlOut.addTextElementToData("Error", ss.str());
358  // }
359  // catch(...)
360  // {
361  // __SUP_SS__ << "An unknown error was encountered handling requestType '" <<
362  // requestType << ".' " << "Please check the printouts to debug." <<
363  //__E__;
364  // __SUP_COUT_ERR__ << "\n" << ss.str();
365  // xmlOut.addTextElementToData("Error", ss.str());
366  // }
367  // END KEEP.
368 
369 } // end request()
370 
371 //==============================================================================
377 void CoreSupervisorBase::nonXmlRequest(const std::string& /*requestType*/,
378  cgicc::Cgicc& /*cgiIn*/,
379  std::ostream& out,
380  const WebUsers::RequestUserInfo& /*userInfo*/)
381 {
382  __SUP_COUT__ << "This is the empty Core Supervisor non-xml request. Supervisors "
383  "should override this function."
384  << __E__;
385  out << "This is the empty Core Supervisor non-xml request. Supervisors should "
386  "override this function."
387  << __E__;
388 } // end nonXmlRequest()
389 
390 //==============================================================================
391 void CoreSupervisorBase::stateMachineXgiHandler(xgi::Input* /*in*/, xgi::Output* /*out*/)
392 {
393 }
394 
395 //==============================================================================
396 xoap::MessageReference CoreSupervisorBase::stateMachineXoapHandler(
397  xoap::MessageReference message)
398 {
399  __SUP_COUT__ << "Soap Handler!" << __E__;
400  stateMachineWorkLoopManager_.removeProcessedRequests();
401  stateMachineWorkLoopManager_.processRequest(message);
402  __SUP_COUT__ << "Done - Soap Handler!" << __E__;
403  return message;
404 } // end stateMachineXoapHandler()
405 
406 //==============================================================================
408 xoap::MessageReference CoreSupervisorBase::workLoopStatusRequestWrapper(
409  xoap::MessageReference message)
410 {
411  // this should have an override for monitoring work loops being done
412  return workLoopStatusRequest(message);
413 } // end workLoopStatusRequest()
414 
415 //==============================================================================
416 xoap::MessageReference CoreSupervisorBase::workLoopStatusRequest(
417  xoap::MessageReference /*message*/)
418 {
419  // this should have an override for monitoring work loops being done
420  return SOAPUtilities::makeSOAPMessageReference(CoreSupervisorBase::WORK_LOOP_DONE);
421 } // end workLoopStatusRequest()
422 
423 //==============================================================================
424 xoap::MessageReference CoreSupervisorBase::applicationStatusRequest(
425  xoap::MessageReference /*message*/)
426 {
427  // send back status and progress parameters
428 
429  __SUP_COUTVS__(20,
430  std::to_string(getpid()) + ":" + std::to_string(gettid()) + ":" +
431  theStateMachine_.getCurrentStateName());
432 
433  const std::string& err = theStateMachine_.getErrorMessage();
434  // std::string status = err == "" ? (theStateMachine_.isInTransition() ? theStateMachine_.getProvenanceStateName() : theStateMachine_.getCurrentStateName())
435  // : (theStateMachine_.getCurrentStateName() == "Paused" ? "Soft-Error:::" : "Error:::") + err;
436 
437  // __SUP_COUTV__(theStateMachine_.isInTransition());
438  // __SUP_COUTV__(theStateMachine_.getProvenanceStateName());
439  // __SUP_COUTV__(theStateMachine_.getCurrentStateName());
440  // __SUP_COUTV__(RunControlStateMachine::theProgressBar_.readPercentageString());
441 
442  SOAPParameters retParameters;
443  if(err == "")
444  {
445  if(theStateMachine_.isInTransition() ||
446  RunControlStateMachine::theProgressBar_.read() < 100)
447  {
448  // attempt to get transition name, otherwise give provenance state
449  try
450  {
451  retParameters.addParameter("Status",
452  theStateMachine_.getCurrentTransitionName());
453  }
454  catch(...)
455  {
456  retParameters.addParameter("Status",
457  theStateMachine_.getProvenanceStateName());
458  }
459  }
460  else
461  retParameters.addParameter("Status", theStateMachine_.getCurrentStateName());
462  }
463  else
464  retParameters.addParameter(
465  "Status",
466  (theStateMachine_.getCurrentStateName() == "Paused" ? "Soft-Error:::"
467  : "Error:::") +
468  err);
469 
470  retParameters.addParameter(
471  "Progress", RunControlStateMachine::theProgressBar_.readPercentageString());
472  retParameters.addParameter(
473  "Detail",
474  getStatusProgressDetail()); // call virtual progress detail string generation
475 
476  //return available disk space if first app in context
477  __SUP_COUTVS__(19, CorePropertySupervisorBase::isFirstAppInContext());
478  if(CorePropertySupervisorBase::isFirstAppInContext())
479  {
480  uint64_t availableLogSpaceKB =
481  CorePropertySupervisorBase::getAvailableLogSpaceKB();
482  uint64_t availableDataSpaceKB =
483  CorePropertySupervisorBase::getAvailableDataSpaceKB();
484 
485  retParameters.addParameter("AvailableLogSpaceKB",
486  std::to_string(availableLogSpaceKB));
487  retParameters.addParameter("AvailableDataSpaceKB",
488  std::to_string(availableDataSpaceKB));
489  }
490  else // just return 0 since not responsible for disk space
491  {
492  retParameters.addParameter("AvailableLogSpaceKB", "0");
493  retParameters.addParameter("AvailableDataSpaceKB", "0");
494  }
495 
496  auto subappInfo = getSubappInfo();
497  retParameters.addParameter("Subapps",
498  SupervisorInfo::serializeSubappInfos(subappInfo));
499 
500  return SOAPUtilities::makeSOAPMessageReference("applicationStatusRequestReply",
501  retParameters);
502 } // end applicationStatusRequest()
503 
504 //==============================================================================
505 xoap::MessageReference
506 CoreSupervisorBase::minReadyForEventGenerationStartIterationRequest(
507  xoap::MessageReference /*message*/)
508 {
509  unsigned int maxIteration = 0;
510  for(const auto& fsm : theStateMachineImplementation_)
511  {
512  unsigned int val = fsm->getMinReadyForEventGenerationStartIteration();
513  if(val > maxIteration)
514  maxIteration = val;
515  }
516 
517  __SUP_COUT__ << "MinReadyForEventGenerationStartIteration (aggregated max) = "
518  << maxIteration << __E__;
519 
520  SOAPParameters retParameters;
521  retParameters.addParameter("MinIteration", std::to_string(maxIteration));
522  return SOAPUtilities::makeSOAPMessageReference(
523  "MinReadyForEventGenerationStartIterationRequestReply", retParameters);
524 } // end minReadyForEventGenerationStartIterationRequest()
525 
526 //==============================================================================
532 {
533  std::string detail;
534  unsigned int cnt = 0;
535 
536  /*
537  //__SUP_COUT__ << "Checking..." << CoreSupervisorBase::theStateMachineImplementation_.size() << __E__;
538  for(const auto& fsm : CoreSupervisorBase::theStateMachineImplementation_)
539  {
540  //__SUP_COUT__ << "Checking..." << __E__;
541  try
542  {
543  VStateMachine* testFSM = dynamic_cast<VStateMachine*>(fsm);
544  }
545  catch(...)
546  {
547  __SUP_COUT__ << "getStatusProgressDetail() VStateMachine testFSM Failed..." << __E__;
548  throw;
549  }
550  }
551  */
552 
553  if(!theStateMachine_.isInTransition() &&
554  (theStateMachine_.getCurrentStateName() ==
555  RunControlStateMachine::HALTED_STATE_NAME ||
556  theStateMachine_.getCurrentStateName() ==
557  RunControlStateMachine::INITIAL_STATE_NAME))
558  {
559  detail = std::string("Uptime: ") +
560  StringMacros::encodeURIComponent(StringMacros::getTimeDurationString(
561  CorePropertySupervisorBase::getSupervisorUptime())) +
562  ", Time-in-state: " +
563  StringMacros::encodeURIComponent(StringMacros::getTimeDurationString(
564  theStateMachine_.getTimeInState()));
565  return detail;
566  }
567 
568  for(const auto& fsm : CoreSupervisorBase::theStateMachineImplementation_)
569  {
570  std::string fsmProgressDetail = fsm->getStatusProgressDetail();
571  if(fsmProgressDetail.size())
572  detail +=
573  ((cnt++) ? ":" : "") +
574  fsmProgressDetail; // StringMacros::encodeURIComponent(fsmProgressDetail);
575  }
576 
577  if(detail.size())
578  __SUP_COUTVS__(20, detail);
579 
580  // if empty detail, give last command
581  if(!detail.size() && RunControlStateMachine::getLastCommand() != "")
582  {
583  detail = "Last Command: " + RunControlStateMachine::getLastCommand();
584  if(RunControlStateMachine::getLastCommand() ==
585  RunControlStateMachine::CONFIGURE_TRANSITION_NAME)
586  detail += " w/" + RunControlStateMachine::getLastAttemptedConfigureGroup();
587  }
588 
589  return detail;
590 } // end getStatusProgressDetail()
591 
592 //==============================================================================
593 bool CoreSupervisorBase::stateMachineThread(toolbox::task::WorkLoop* workLoop)
594 {
595  stateMachineSemaphore_.take();
596  __SUP_COUT__ << "Re-sending message..."
597  << SOAPUtilities::translate(
598  stateMachineWorkLoopManager_.getMessage(workLoop))
599  .getCommand()
600  << __E__;
601  std::string reply = send(this->getApplicationDescriptor(),
602  stateMachineWorkLoopManager_.getMessage(workLoop));
603  stateMachineWorkLoopManager_.report(workLoop, reply, 100, true);
604  __SUP_COUT__ << "Done with message" << __E__;
605  stateMachineSemaphore_.give();
606  return false; // execute once and automatically remove the workloop so in
607  // WorkLoopManager the try workLoop->remove(job_) could be commented
608  // out return true;//go on and then you must do the
609  // workLoop->remove(job_) in WorkLoopManager
610 } // end stateMachineThread()
611 
612 //==============================================================================
613 xoap::MessageReference CoreSupervisorBase::stateMachineStateRequest(
614  xoap::MessageReference /*message*/)
615 {
616  __SUP_COUT__ << "theStateMachine_.getCurrentStateName() = "
617  << theStateMachine_.getCurrentStateName() << __E__;
618  return SOAPUtilities::makeSOAPMessageReference(
619  theStateMachine_.getCurrentStateName());
620 }
621 
622 //==============================================================================
623 xoap::MessageReference CoreSupervisorBase::stateMachineErrorMessageRequest(
624  xoap::MessageReference /*message*/)
625 
626 {
627  __SUP_COUT__ << "theStateMachine_.getErrorMessage() = "
628  << theStateMachine_.getErrorMessage() << __E__;
629 
630  SOAPParameters retParameters;
631  retParameters.addParameter("ErrorMessage", theStateMachine_.getErrorMessage());
632  return SOAPUtilities::makeSOAPMessageReference("stateMachineErrorMessageRequestReply",
633  retParameters);
634 } // end stateMachineErrorMessageRequest()
635 
636 //==============================================================================
637 void CoreSupervisorBase::stateInitial(toolbox::fsm::FiniteStateMachine& /*fsm*/)
638 {
639  __SUP_COUT__ << "CoreSupervisorBase::stateInitial" << __E__;
640 }
641 
642 //==============================================================================
643 void CoreSupervisorBase::stateHalted(toolbox::fsm::FiniteStateMachine& /*fsm*/)
644 {
645  __SUP_COUT__ << "CoreSupervisorBase::stateHalted" << __E__;
646 }
647 
648 //==============================================================================
649 void CoreSupervisorBase::stateRunning(toolbox::fsm::FiniteStateMachine& /*fsm*/)
650 {
651  __SUP_COUT__ << "CoreSupervisorBase::stateRunning" << __E__;
652 }
653 
654 //==============================================================================
655 void CoreSupervisorBase::stateConfigured(toolbox::fsm::FiniteStateMachine& /*fsm*/)
656 {
657  __SUP_COUT__ << "CoreSupervisorBase::stateConfigured" << __E__;
658 }
659 
660 //==============================================================================
661 void CoreSupervisorBase::statePaused(toolbox::fsm::FiniteStateMachine& /*fsm*/)
662 {
663  __SUP_COUT__ << "CoreSupervisorBase::statePaused" << __E__;
664 }
665 
666 //==============================================================================
667 void CoreSupervisorBase::inError(toolbox::fsm::FiniteStateMachine& /*fsm*/)
668 
669 {
670  __SUP_COUT__ << "Fsm current state: " << theStateMachine_.getCurrentStateName()
671  << __E__;
672  // rcmsStateNotifier_.stateChanged("Error", "");
673 }
674 
675 //==============================================================================
676 void CoreSupervisorBase::enteringError(toolbox::Event::Reference event)
677 
678 {
679  // __SUP_COUT__<< "Fsm current state: " << theStateMachine_.getCurrentStateName()
680  // << "\n\nError Message: " <<
681  // theStateMachine_.getErrorMessage() << __E__;
682  toolbox::fsm::FailedEvent& failedEvent =
683  dynamic_cast<toolbox::fsm::FailedEvent&>(*event);
684  std::ostringstream error;
685  error << "Failure performing transition from " << failedEvent.getFromState() << " to "
686  << failedEvent.getToState()
687  << " exception: " << failedEvent.getException().what();
688  __SUP_COUT_ERR__ << error.str() << __E__;
689  // diagService_->reportError(errstr.str(),DIAGERROR);
690 }
691 
692 //==============================================================================
693 void CoreSupervisorBase::preStateMachineExecutionLoop(void)
694 {
695  RunControlStateMachine::clearSubsystemIterationWork();
696  RunControlStateMachine::clearIterationWork();
697  RunControlStateMachine::clearSubIterationWork();
698 
699  stateMachinesIterationWorkCount_ = 0;
700 
702  {
703  // reset vector for iterations done on first iteration
704 
705  subIterationWorkStateMachineIndex_ = -1; // clear sub iteration work index
706 
707  stateMachinesIterationDone_.resize(theStateMachineImplementation_.size());
708  for(unsigned int i = 0; i < stateMachinesIterationDone_.size(); ++i)
709  stateMachinesIterationDone_[i] = false;
710 
712  lastSubsystemIterationIndexSeen_ =
713  RunControlStateMachine::getSubsystemIterationIndex();
714  }
715  else
716  {
717  __SUP_COUT__ << "SubsystemIteration "
718  << (RunControlStateMachine::isStandaloneSubsystem()
719  ? std::string("standalone")
720  : std::to_string(
721  RunControlStateMachine::getSubsystemIterationIndex()))
722  << " Iteration " << RunControlStateMachine::getIterationIndex()
723  << "." << RunControlStateMachine::getSubIterationIndex() << "("
724  << subIterationWorkStateMachineIndex_ << ")" << __E__;
725 
726  // a new subsystem-iteration re-arms the apps that asked for it
727  if(RunControlStateMachine::getSubsystemIterationIndex() !=
728  lastSubsystemIterationIndexSeen_)
729  {
730  lastSubsystemIterationIndexSeen_ =
731  RunControlStateMachine::getSubsystemIterationIndex();
732  for(unsigned int i : stateMachinesWaitingSubsystemIteration_)
733  stateMachinesIterationDone_[i] = false;
735  }
736  }
737 }
738 
739 //==============================================================================
740 void CoreSupervisorBase::preStateMachineExecution(unsigned int i)
741 {
742  if(i >= theStateMachineImplementation_.size())
743  {
744  __SUP_SS__ << "State Machine " << i << " not found!" << __E__;
745  __SUP_SS_THROW__;
746  }
747 
748  theStateMachineImplementation_[i]->VStateMachine::setSubsystemIterationIndex(
749  RunControlStateMachine::getSubsystemIterationIndex());
750  theStateMachineImplementation_[i]->VStateMachine::setIterationIndex(
751  RunControlStateMachine::getIterationIndex());
752  theStateMachineImplementation_[i]->VStateMachine::setSubIterationIndex(
753  RunControlStateMachine::getSubIterationIndex());
754  theStateMachineImplementation_[i]
755  ->VStateMachine::setSystemMinReadyForEventGenerationStartIteration(
756  RunControlStateMachine::getMinReadyForEventGenerationStartIteration());
757 
758  theStateMachineImplementation_[i]->VStateMachine::clearSubsystemIterationWork();
759  theStateMachineImplementation_[i]->VStateMachine::clearIterationWork();
760  theStateMachineImplementation_[i]->VStateMachine::clearSubIterationWork();
761 
762  __SUP_COUT__
763  << "theStateMachineImplementation Iteration "
764  << theStateMachineImplementation_[i]->VStateMachine::getIterationIndex() << "."
765  << theStateMachineImplementation_[i]->VStateMachine::getSubIterationIndex()
766  << __E__;
767 }
768 
769 //==============================================================================
770 void CoreSupervisorBase::postStateMachineExecution(unsigned int i)
771 {
772  if(i >= theStateMachineImplementation_.size())
773  {
774  __SUP_SS__ << "State Machine " << i << " not found!" << __E__;
775  __SUP_SS_THROW__;
776  }
777 
778  // sub-iteration has highest priority
779  if(theStateMachineImplementation_[i]->VStateMachine::getSubIterationWork())
780  {
781  subIterationWorkStateMachineIndex_ = i;
782  RunControlStateMachine::indicateSubIterationWork();
783 
784  __SUP_COUT__ << "State machine " << i
785  << " is flagged for another sub-iteration..." << __E__;
786  }
787  else if(theStateMachineImplementation_[i]->VStateMachine::getIterationWork())
788  {
789  // iteration — this app needs another iteration within this subsystem
790  stateMachinesIterationDone_[i] = false;
791  RunControlStateMachine::indicateIterationWork(); // mark not done at
792  // CoreSupervisorBase level
793  ++stateMachinesIterationWorkCount_; // increment still working count
794 
795  __SUP_COUT__ << "State machine " << i << " is flagged for another iteration..."
796  << __E__;
797  }
798  else if(theStateMachineImplementation_[i]->VStateMachine::getSubsystemIterationWork())
799  {
800  // subsystem-iteration — this app is done with inner iterations
801  // but needs another cross-subsystem sync barrier
802  stateMachinesIterationDone_[i] = true; // done with inner iterations
804  RunControlStateMachine::indicateSubsystemIterationWork();
805 
806  __SUP_COUT__ << "State machine " << i
807  << " is flagged for another subsystem-iteration..." << __E__;
808  }
809  else
810  {
811  // fully done
812  stateMachinesIterationDone_[i] = true;
813  }
814 } // end postStateMachineExecution()
815 
816 //==============================================================================
817 void CoreSupervisorBase::postStateMachineExecutionLoop(void)
818 {
819  if(RunControlStateMachine::subIterationWorkFlag_)
820  __SUP_COUT__ << "State machine implementation "
821  << subIterationWorkStateMachineIndex_
822  << " is flagged for another sub-iteration..." << __E__;
823  else if(RunControlStateMachine::iterationWorkFlag_)
824  __SUP_COUT__
825  << stateMachinesIterationWorkCount_
826  << " state machine implementation(s) flagged for another iteration..."
827  << __E__;
828  else if(RunControlStateMachine::subsystemIterationWorkFlag_)
829  __SUP_COUT__ << "State machine implementation(s) flagged for another "
830  "subsystem-iteration (cross-subsystem sync)..."
831  << __E__;
832  else
833  __SUP_COUT__ << "Done configuration all state machine implementations..."
834  << __E__;
835 } // end postStateMachineExecutionLoop()
836 
837 //==============================================================================
838 void CoreSupervisorBase::configureInit(bool attemptSkipIfGroupUnchanged /* = false */)
839 {
840  // activate the configuration tree (only the first iteration)
841 
843  return;
844 
845  __SUP_COUT__ << "configureInit()" << __E__;
846 
847  std::pair<std::string /*group name*/, TableGroupKey> theGroup(
848  SOAPUtilities::translate(theStateMachine_.getCurrentMessage())
849  .getParameters()
850  .getValue("ConfigurationTableGroupName"),
851  TableGroupKey(SOAPUtilities::translate(theStateMachine_.getCurrentMessage())
852  .getParameters()
853  .getValue("ConfigurationTableGroupKey")));
854 
855  __SUP_COUT__ << "Configuration table group name: " << theGroup.first
856  << " key: " << theGroup.second << __E__;
857 
858  //fill System Variables
859  StringMacros::systemVariables_["ActiveStateMachine"]["name"] =
860  SOAPUtilities::translate(theStateMachine_.getCurrentMessage())
861  .getParameters()
862  .getValue("ActiveStateMachineName");
863  StringMacros::systemVariables_["ActiveStateMachine"]["windowName"] =
864  SOAPUtilities::translate(theStateMachine_.getCurrentMessage())
865  .getParameters()
866  .getValue("ActiveStateMachineWindowName");
867  StringMacros::systemVariables_["ActiveStateMachine"]["runAlias"] =
868  SOAPUtilities::translate(theStateMachine_.getCurrentMessage())
869  .getParameters()
870  .getValue("ActiveStateMachineRunAlias");
871  __SUP_COUTV__(StringMacros::mapToString(StringMacros::systemVariables_));
872 
873  // Assemble Subsystem Common Table List ----------------
874  std::map<std::string /* tableName */, TableVersion> mergeInTables, overrideTables;
875  {
876  { //handle common merge-in list
877  std::string subsystemCommonList;
878  try
879  {
880  subsystemCommonList =
881  SOAPUtilities::translate(theStateMachine_.getCurrentMessage())
882  .getParameters()
883  .getValue("SubsystemCommonList");
884  }
885  catch(...)
886  {
887  __COUT__ << "Ignoring missing 'SubsystemCommonList' parameter." << __E__;
888  }
889 
890  if(!subsystemCommonList.empty())
891  {
892  subsystemCommonList =
893  StringMacros::decodeURIComponent(subsystemCommonList);
894  __COUT__ << "Transition parameter SubsystemCommonList: "
895  << subsystemCommonList << __E__;
896  StringMacros::getMapFromString(subsystemCommonList, mergeInTables);
897  __COUTV__(StringMacros::mapToString(mergeInTables));
898  }
899  } //end handle common merge-in list
900 
901  { //handle common override list
902  std::string subsystemCommonOverrideList;
903  try
904  {
905  subsystemCommonOverrideList =
906  SOAPUtilities::translate(theStateMachine_.getCurrentMessage())
907  .getParameters()
908  .getValue("SubsystemCommonOverrideList");
909  }
910  catch(...)
911  {
912  __COUT__ << "Ignoring missing 'SubsystemCommonOverrideList' parameter."
913  << __E__;
914  }
915 
916  if(!subsystemCommonOverrideList.empty())
917  {
918  subsystemCommonOverrideList =
919  StringMacros::decodeURIComponent(subsystemCommonOverrideList);
920  __COUT__ << "Transition parameter SubsystemCommonOverrideList: "
921  << subsystemCommonOverrideList << __E__;
922  StringMacros::getMapFromString(subsystemCommonOverrideList,
923  overrideTables);
924  __COUTV__(StringMacros::mapToString(overrideTables));
925  }
926  } //end handle common override list
927  } // end Assemble Subsystem Common Table List ----------------
928 
929  // If requested, skip the (expensive) table group reload + re-activation when
930  // it can be proven redundant: same group name+key already active, no
931  // merge-in/override lists in play now or at the previous activation (those
932  // mutate active tables after load), and no scratch/temporary member versions
933  // (whose content can change without a key change). Group keys are otherwise
934  // immutable, so same key => same content.
935  if(attemptSkipIfGroupUnchanged && mergeInTables.empty() && overrideTables.empty() &&
937  theConfigurationManager_->getActiveGroupName(
938  ConfigurationManager::GroupType::CONFIGURATION_TYPE) == theGroup.first &&
939  theConfigurationManager_->getActiveGroupKey(
940  ConfigurationManager::GroupType::CONFIGURATION_TYPE) == theGroup.second)
941  {
942  bool haveScratchOrTemporaryMembers = false;
943  for(const auto& activeVersionPair : theConfigurationManager_->getActiveVersions())
944  if(activeVersionPair.second.isScratchVersion() ||
945  activeVersionPair.second.isTemporaryVersion())
946  {
947  haveScratchOrTemporaryMembers = true;
948  __SUP_COUT__ << "Not skipping activation: active member '"
949  << activeVersionPair.first
950  << "' has scratch/temporary version "
951  << activeVersionPair.second << __E__;
952  break;
953  }
954 
955  if(!haveScratchOrTemporaryMembers)
956  {
957  __SUP_COUT_INFO__ << "Skipping table group activation: group '"
958  << theGroup.first << "(" << theGroup.second
959  << ")' is already active with no scratch/temporary "
960  "member versions and no merge-in/override lists."
961  << __E__;
962  return;
963  }
964  }
965 
966  try
967  {
969  theConfigurationManager_);
970  //disable version tracking to accept untracked versions to be selected by the FSM transition source
971  theConfigurationManager_->loadTableGroup(
972  theGroup.first,
973  theGroup.second,
974  true /*doActivate*/,
975  0 /*groupMembers */,
976  0 /*progressBar */,
977  0 /*accumulateWarnings*/,
978  0 /*groupComment */,
979  0 /*groupAuthor */,
980  0 /*groupCreateTime */,
981  false /*doNotLoadMember */,
982  0 /*groupTypeString */,
983  0 /*groupAliases */,
984  ConfigurationManager::LoadGroupType::ALL_TYPES,
985  true /*ignoreVersionTracking*/,
986  mergeInTables /* mergeInTables */,
987  overrideTables /* overrideTables */
988  );
989  }
990  catch(const std::runtime_error& e)
991  {
992  __SS__ << "Error loading table group '" << theGroup.first << "("
993  << theGroup.second << ")! \n"
994  << e.what() << __E__;
995  __SUP_COUT_ERR__ << ss.str();
996  // ExceptionHandler(ExceptionHandlerRethrow::no, ss.str());
997 
998  //__SS_THROW_ONLY__;
999  theStateMachine_.setErrorMessage(ss.str());
1000  throw toolbox::fsm::exception::Exception(
1001  "Transition Error" /*name*/,
1002  ss.str() /* message*/,
1003  "CoreSupervisorBase::configureInit" /*module*/,
1004  __LINE__ /*line*/,
1005  __FUNCTION__ /*function*/
1006  );
1007  }
1008  catch(...)
1009  {
1010  __SS__ << "Unknown error loading table group '" << theGroup.first << "("
1011  << theGroup.second << ")!" << __E__;
1012  try
1013  {
1014  throw;
1015  } //one more try to printout extra info
1016  catch(const std::exception& e)
1017  {
1018  ss << "Exception message: " << e.what();
1019  }
1020  catch(...)
1021  {
1022  }
1023  __SUP_COUT_ERR__ << ss.str();
1024  // ExceptionHandler(ExceptionHandlerRethrow::no, ss.str());
1025 
1026  //__SS_THROW_ONLY__;
1027  theStateMachine_.setErrorMessage(ss.str());
1028  throw toolbox::fsm::exception::Exception(
1029  "Transition Error" /*name*/,
1030  ss.str() /* message*/,
1031  "CoreSupervisorBase::configureInit" /*module*/,
1032  __LINE__ /*line*/,
1033  __FUNCTION__ /*function*/
1034  );
1035  }
1036 
1037  lastActivationHadMergeOrOverride_ = !mergeInTables.empty() || !overrideTables.empty();
1038 } //end configureInit()
1039 
1040 //==============================================================================
1041 void CoreSupervisorBase::transitionConfiguring(toolbox::Event::Reference /*event*/)
1042 {
1043  __SUP_COUT__ << "transitionConfiguring()" << __E__;
1044 
1045  CoreSupervisorBase::configureInit(true /*attemptSkipIfGroupUnchanged*/);
1046 
1047  CoreSupervisorBase::transitionConfiguringFSMs();
1048 
1049  __SUP_COUT__ << "Configured." << __E__;
1050 } // end transitionConfiguring()
1051 
1052 //==============================================================================
1053 void CoreSupervisorBase::transitionConfiguringFSMs()
1054 {
1055  // Now that the configuration manager has all the necessary configurations,
1056  // create all objects that depend on the configuration (the first iteration)
1057 
1058  try
1059  {
1060  __SUP_COUT__ << "Configuring all state machine implementations..." << __E__;
1061  preStateMachineExecutionLoop();
1062  for(unsigned int i = 0; i < theStateMachineImplementation_.size(); ++i)
1063  {
1064  // if one state machine is doing a sub-iteration, then target that one
1065  if(subIterationWorkStateMachineIndex_ != (unsigned int)-1 &&
1066  i != subIterationWorkStateMachineIndex_)
1067  continue; // skip those not in the sub-iteration
1068 
1070  continue; // skip state machines already done
1071 
1072  preStateMachineExecution(i);
1073  theStateMachineImplementation_[i]->parentSupervisor_ =
1074  this; // for backwards compatibility, kept out of configure parameters
1075  theStateMachineImplementation_[i]->configure(); // e.g. for FESupervisor,
1076  // this is configure of
1077  // FEVInterfacesManager
1078  postStateMachineExecution(i);
1079  }
1080  postStateMachineExecutionLoop();
1081  }
1082  catch(const std::runtime_error& e)
1083  {
1084  __SUP_SS__ << "Error was caught while configuring: " << e.what() << __E__;
1085  __SUP_COUT_ERR__ << "\n" << ss.str();
1086  theStateMachine_.setErrorMessage(ss.str());
1087  throw toolbox::fsm::exception::Exception(
1088  "Transition Error" /*name*/,
1089  ss.str() /* message*/,
1090  "CoreSupervisorBase::transitionConfiguringFSMs" /*module*/,
1091  __LINE__ /*line*/,
1092  __FUNCTION__ /*function*/
1093  );
1094  }
1095  catch(...)
1096  {
1097  __SUP_SS__
1098  << "Unknown error was caught while configuring. Please checked the logs."
1099  << __E__;
1100  try
1101  {
1102  throw;
1103  } //one more try to printout extra info
1104  catch(const std::exception& e)
1105  {
1106  ss << "Exception message: " << e.what();
1107  }
1108  catch(...)
1109  {
1110  }
1111  __SUP_COUT_ERR__ << "\n" << ss.str();
1112  theStateMachine_.setErrorMessage(ss.str());
1113  throw toolbox::fsm::exception::Exception(
1114  "Transition Error" /*name*/,
1115  ss.str() /* message*/,
1116  "CoreSupervisorBase::transitionConfiguringFSMs" /*module*/,
1117  __LINE__ /*line*/,
1118  __FUNCTION__ /*function*/
1119  );
1120  }
1121 } // end transitionConfiguringFSMs()
1122 
1123 //==============================================================================
1126 void CoreSupervisorBase::transitionHalting(toolbox::Event::Reference /*event*/)
1127 {
1128  const std::string transitionName = "Halting";
1129  try
1130  {
1131  __SUP_COUT__ << transitionName << " all state machine implementations..."
1132  << __E__;
1133  preStateMachineExecutionLoop();
1134  for(unsigned int i = 0; i < theStateMachineImplementation_.size(); ++i)
1135  {
1136  // if one state machine is doing a sub-iteration, then target that one
1137  if(subIterationWorkStateMachineIndex_ != (unsigned int)-1 &&
1138  i != subIterationWorkStateMachineIndex_)
1139  continue; // skip those not in the sub-iteration
1140 
1142  continue; // skip state machines already done
1143 
1144  preStateMachineExecution(i);
1145  theStateMachineImplementation_[i]->halt(); // e.g. for FESupervisor, this is
1146  // transition of
1147  // FEVInterfacesManager
1148  postStateMachineExecution(i);
1149  }
1150  postStateMachineExecutionLoop();
1151  }
1152  catch(const std::runtime_error& e)
1153  {
1154  // if halting from Failed or Halted state, then ignore errors
1155  if(theStateMachine_.getProvenanceStateName() ==
1156  RunControlStateMachine::FAILED_STATE_NAME ||
1157  theStateMachine_.getProvenanceStateName() ==
1158  RunControlStateMachine::HALTED_STATE_NAME)
1159  {
1160  __SUP_COUT_INFO__ << "Error was caught while halting (but ignoring because "
1161  "previous state was '"
1162  << theStateMachine_.getProvenanceStateName()
1163  << "'): " << e.what() << __E__;
1164  }
1165  else // if not previously in Failed state, then fail
1166  {
1167  __SUP_SS__ << "Error was caught while " << transitionName << ": " << e.what()
1168  << __E__;
1169  __SUP_COUT_ERR__ << "\n" << ss.str();
1170  theStateMachine_.setErrorMessage(ss.str());
1171  throw toolbox::fsm::exception::Exception(
1172  "Transition Error" /*name*/,
1173  ss.str() /* message*/,
1174  "CoreSupervisorBase::transition" + transitionName /*module*/,
1175  __LINE__ /*line*/,
1176  __FUNCTION__ /*function*/
1177  );
1178  }
1179  }
1180  catch(...)
1181  {
1182  // if halting from Failed or Halted state, then ignore errors
1183  if(theStateMachine_.getProvenanceStateName() ==
1184  RunControlStateMachine::FAILED_STATE_NAME ||
1185  theStateMachine_.getProvenanceStateName() ==
1186  RunControlStateMachine::HALTED_STATE_NAME)
1187  {
1188  __SUP_COUT_INFO__ << "Unknown error was caught while halting (but ignoring "
1189  "because previous state was '"
1190  << theStateMachine_.getProvenanceStateName() << "')."
1191  << __E__;
1192  }
1193  else // if not previously in Failed state, then fail
1194  {
1195  __SUP_SS__ << "Unknown error was caught while " << transitionName
1196  << ". Please checked the logs." << __E__;
1197  try
1198  {
1199  throw;
1200  } //one more try to printout extra info
1201  catch(const std::exception& e)
1202  {
1203  ss << "Exception message: " << e.what();
1204  }
1205  catch(...)
1206  {
1207  }
1208  __SUP_COUT_ERR__ << "\n" << ss.str();
1209  theStateMachine_.setErrorMessage(ss.str());
1210  throw toolbox::fsm::exception::Exception(
1211  "Transition Error" /*name*/,
1212  ss.str() /* message*/,
1213  "CoreSupervisorBase::transition" + transitionName /*module*/,
1214  __LINE__ /*line*/,
1215  __FUNCTION__ /*function*/
1216  );
1217  }
1218  }
1219 } // end transitionHalting()
1220 
1221 //==============================================================================
1224 void CoreSupervisorBase::transitionInitializing(toolbox::Event::Reference /*event*/)
1225 {
1226  __SUP_COUT__ << "transitionInitializing" << __E__;
1227 
1228  CorePropertySupervisorBase::resetPropertiesAreSetup(); // indicate need to re-load
1229  // user properties
1230 
1231  // Note: Do not initialize the state machine implementations...
1232  // do any initializing in configure
1233  // This allows re-instantiation at each configure time.
1234  // for(auto& it: theStateMachineImplementation_)
1235  // it->initialize();
1236 } // end transitionInitializing()
1237 
1238 //==============================================================================
1239 void CoreSupervisorBase::transitionPausing(toolbox::Event::Reference /*event*/)
1240 {
1241  const std::string transitionName = "Pausing";
1242  try
1243  {
1244  __SUP_COUT__ << "Configuring all state machine implementations..." << __E__;
1245  preStateMachineExecutionLoop();
1246  for(unsigned int i = 0; i < theStateMachineImplementation_.size(); ++i)
1247  {
1248  // if one state machine is doing a sub-iteration, then target that one
1249  if(subIterationWorkStateMachineIndex_ != (unsigned int)-1 &&
1250  i != subIterationWorkStateMachineIndex_)
1251  continue; // skip those not in the sub-iteration
1252 
1254  continue; // skip state machines already done
1255 
1256  preStateMachineExecution(i);
1257  theStateMachineImplementation_[i]->pause(); // e.g. for FESupervisor, this is
1258  // transition of
1259  // FEVInterfacesManager
1260  postStateMachineExecution(i);
1261  }
1262  postStateMachineExecutionLoop();
1263  }
1264  catch(const std::runtime_error& e)
1265  {
1266  __SUP_SS__ << "Error was caught while " << transitionName << ": " << e.what()
1267  << __E__;
1268  __SUP_COUT_ERR__ << "\n" << ss.str();
1269  theStateMachine_.setErrorMessage(ss.str());
1270  throw toolbox::fsm::exception::Exception(
1271  "Transition Error" /*name*/,
1272  ss.str() /* message*/,
1273  "CoreSupervisorBase::transition" + transitionName /*module*/,
1274  __LINE__ /*line*/,
1275  __FUNCTION__ /*function*/
1276  );
1277  }
1278  catch(...)
1279  {
1280  __SUP_SS__ << "Unknown error was caught while " << transitionName
1281  << ". Please checked the logs." << __E__;
1282  try
1283  {
1284  throw;
1285  } //one more try to printout extra info
1286  catch(const std::exception& e)
1287  {
1288  ss << "Exception message: " << e.what();
1289  }
1290  catch(...)
1291  {
1292  }
1293  __SUP_COUT_ERR__ << "\n" << ss.str();
1294  theStateMachine_.setErrorMessage(ss.str());
1295  throw toolbox::fsm::exception::Exception(
1296  "Transition Error" /*name*/,
1297  ss.str() /* message*/,
1298  "CoreSupervisorBase::transition" + transitionName /*module*/,
1299  __LINE__ /*line*/,
1300  __FUNCTION__ /*function*/
1301  );
1302  }
1303 } // end transitionPausing()
1304 
1305 //==============================================================================
1306 void CoreSupervisorBase::transitionResuming(toolbox::Event::Reference /*event*/)
1307 {
1308  const std::string transitionName = "Resuming";
1309  try
1310  {
1311  __SUP_COUT__ << "Configuring all state machine implementations..." << __E__;
1312  preStateMachineExecutionLoop();
1313  for(unsigned int i = 0; i < theStateMachineImplementation_.size(); ++i)
1314  {
1315  // if one state machine is doing a sub-iteration, then target that one
1316  if(subIterationWorkStateMachineIndex_ != (unsigned int)-1 &&
1317  i != subIterationWorkStateMachineIndex_)
1318  continue; // skip those not in the sub-iteration
1319 
1321  continue; // skip state machines already done
1322 
1323  preStateMachineExecution(i);
1324  theStateMachineImplementation_[i]->resume(); // e.g. for FESupervisor, this
1325  // is transition of
1326  // FEVInterfacesManager
1327  postStateMachineExecution(i);
1328  }
1329  postStateMachineExecutionLoop();
1330  }
1331  catch(const std::runtime_error& e)
1332  {
1333  __SUP_SS__ << "Error was caught while " << transitionName << ": " << e.what()
1334  << __E__;
1335  __SUP_COUT_ERR__ << "\n" << ss.str();
1336  theStateMachine_.setErrorMessage(ss.str());
1337  throw toolbox::fsm::exception::Exception(
1338  "Transition Error" /*name*/,
1339  ss.str() /* message*/,
1340  "CoreSupervisorBase::transition" + transitionName /*module*/,
1341  __LINE__ /*line*/,
1342  __FUNCTION__ /*function*/
1343  );
1344  }
1345  catch(...)
1346  {
1347  __SUP_SS__ << "Unknown error was caught while " << transitionName
1348  << ". Please checked the logs." << __E__;
1349  try
1350  {
1351  throw;
1352  } //one more try to printout extra info
1353  catch(const std::exception& e)
1354  {
1355  ss << "Exception message: " << e.what();
1356  }
1357  catch(...)
1358  {
1359  }
1360  __SUP_COUT_ERR__ << "\n" << ss.str();
1361  theStateMachine_.setErrorMessage(ss.str());
1362  throw toolbox::fsm::exception::Exception(
1363  "Transition Error" /*name*/,
1364  ss.str() /* message*/,
1365  "CoreSupervisorBase::transition" + transitionName /*module*/,
1366  __LINE__ /*line*/,
1367  __FUNCTION__ /*function*/
1368  );
1369  }
1370 } // end transitionResuming()
1371 
1372 //==============================================================================
1373 void CoreSupervisorBase::transitionStarting(toolbox::Event::Reference /*event*/)
1374 {
1375  const std::string transitionName = "Starting";
1376  const std::string runNumber =
1377  SOAPUtilities::translate(theStateMachine_.getCurrentMessage())
1378  .getParameters()
1379  .getValue("RunNumber");
1380  try
1381  {
1382  __SUP_COUT__ << "Configuring all state machine implementations..." << __E__;
1383  preStateMachineExecutionLoop();
1384  for(unsigned int i = 0; i < theStateMachineImplementation_.size(); ++i)
1385  {
1386  // if one state machine is doing a sub-iteration, then target that one
1387  if(subIterationWorkStateMachineIndex_ != (unsigned int)-1 &&
1388  i != subIterationWorkStateMachineIndex_)
1389  continue; // skip those not in the sub-iteration
1390 
1392  continue; // skip state machines already done
1393 
1394  preStateMachineExecution(i);
1395  theStateMachineImplementation_[i]->start(runNumber); // e.g. for
1396  // FESupervisor, this is
1397  // transition of
1398  // FEVInterfacesManager
1399  postStateMachineExecution(i);
1400  }
1401  postStateMachineExecutionLoop();
1402  }
1403  catch(const std::runtime_error& e)
1404  {
1405  __SUP_SS__ << "Error was caught while " << transitionName << ": " << e.what()
1406  << __E__;
1407  __SUP_COUT_ERR__ << "\n" << ss.str();
1408  theStateMachine_.setErrorMessage(ss.str());
1409  throw toolbox::fsm::exception::Exception(
1410  "Transition Error" /*name*/,
1411  ss.str() /* message*/,
1412  "CoreSupervisorBase::transition" + transitionName /*module*/,
1413  __LINE__ /*line*/,
1414  __FUNCTION__ /*function*/
1415  );
1416  }
1417  catch(...)
1418  {
1419  __SUP_SS__ << "Unknown error was caught while " << transitionName
1420  << ". Please checked the logs." << __E__;
1421  try
1422  {
1423  throw;
1424  } //one more try to printout extra info
1425  catch(const std::exception& e)
1426  {
1427  ss << "Exception message: " << e.what();
1428  }
1429  catch(...)
1430  {
1431  }
1432  __SUP_COUT_ERR__ << "\n" << ss.str();
1433  theStateMachine_.setErrorMessage(ss.str());
1434  throw toolbox::fsm::exception::Exception(
1435  "Transition Error" /*name*/,
1436  ss.str() /* message*/,
1437  "CoreSupervisorBase::transition" + transitionName /*module*/,
1438  __LINE__ /*line*/,
1439  __FUNCTION__ /*function*/
1440  );
1441  }
1442 } // end transitionStarting()
1443 
1444 //==============================================================================
1445 void CoreSupervisorBase::transitionStopping(toolbox::Event::Reference /*event*/)
1446 {
1447  const std::string transitionName = "Stopping";
1448  try
1449  {
1450  __SUP_COUT__ << "Configuring all state machine implementations..." << __E__;
1451  preStateMachineExecutionLoop();
1452  for(unsigned int i = 0; i < theStateMachineImplementation_.size(); ++i)
1453  {
1454  // if one state machine is doing a sub-iteration, then target that one
1455  if(subIterationWorkStateMachineIndex_ != (unsigned int)-1 &&
1456  i != subIterationWorkStateMachineIndex_)
1457  continue; // skip those not in the sub-iteration
1458 
1460  continue; // skip state machines already done
1461 
1462  preStateMachineExecution(i);
1463  theStateMachineImplementation_[i]->stop(); // e.g. for FESupervisor, this is
1464  // transition of
1465  // FEVInterfacesManager
1466  postStateMachineExecution(i);
1467  }
1468  postStateMachineExecutionLoop();
1469  }
1470  catch(const std::runtime_error& e)
1471  {
1472  __SUP_SS__ << "Error was caught while " << transitionName << ": " << e.what()
1473  << __E__;
1474  __SUP_COUT_ERR__ << "\n" << ss.str();
1475  theStateMachine_.setErrorMessage(ss.str());
1476  throw toolbox::fsm::exception::Exception(
1477  "Transition Error" /*name*/,
1478  ss.str() /* message*/,
1479  "CoreSupervisorBase::transition" + transitionName /*module*/,
1480  __LINE__ /*line*/,
1481  __FUNCTION__ /*function*/
1482  );
1483  }
1484  catch(...)
1485  {
1486  __SUP_SS__ << "Unknown error was caught while " << transitionName
1487  << ". Please checked the logs." << __E__;
1488  try
1489  {
1490  throw;
1491  } //one more try to printout extra info
1492  catch(const std::exception& e)
1493  {
1494  ss << "Exception message: " << e.what();
1495  }
1496  catch(...)
1497  {
1498  }
1499  __SUP_COUT_ERR__ << "\n" << ss.str();
1500  theStateMachine_.setErrorMessage(ss.str());
1501  throw toolbox::fsm::exception::Exception(
1502  "Transition Error" /*name*/,
1503  ss.str() /* message*/,
1504  "CoreSupervisorBase::transition" + transitionName /*module*/,
1505  __LINE__ /*line*/,
1506  __FUNCTION__ /*function*/
1507  );
1508  }
1509 } // end transitionStopping()
1510 
1511 //==============================================================================
1516 void CoreSupervisorBase::sendAsyncExceptionToGateway(const std::string& errorMessage,
1517  bool isPauseException,
1518  bool isStopException)
1519 try
1520 {
1521  if(isStopException)
1522  __SUP_COUT_ERR__ << "Sending Supervisor Async STOP Running Exception... \n"
1523  << errorMessage << __E__;
1524  else if(isPauseException)
1525  __SUP_COUT_ERR__ << "Sending Supervisor Async SOFT Running Error... \n"
1526  << errorMessage << __E__;
1527  else
1528  __SUP_COUT_ERR__ << "Sending Supervisor Async Running Error... \n"
1529  << errorMessage << __E__;
1530 
1531  theStateMachine_.setErrorMessage(errorMessage);
1532 
1533  XDAQ_CONST_CALL xdaq::ApplicationDescriptor* gatewaySupervisor =
1534  allSupervisorInfo_.getGatewayInfo().getDescriptor();
1535 
1536  SOAPParameters parameters;
1537  parameters.addParameter("ErrorMessage", errorMessage);
1538 
1539  xoap::MessageReference replyMessage = SOAPMessenger::sendWithSOAPReply(
1540  gatewaySupervisor,
1541  isStopException ? "AsyncStopException"
1542  : (isPauseException ? "AsyncPauseException" : "AsyncError"),
1543  parameters);
1544 
1545  std::stringstream replyMessageSStream;
1546  replyMessageSStream << SOAPUtilities::translate(replyMessage);
1547  __SUP_COUT__ << "Received... " << replyMessageSStream.str() << std::endl;
1548 
1549  if(replyMessageSStream.str().find("Fault") != std::string::npos)
1550  {
1551  __SUP_COUT_ERR__ << "Failure to indicate fault to Gateway..." << __E__;
1552  throw;
1553  }
1554 }
1555 catch(const xdaq::exception::Exception& e)
1556 {
1557  if(isStopException)
1558  __SUP_COUT__
1559  << "SOAP message failure indicating Supervisor asynchronous running STOP "
1560  "exception back to Gateway: "
1561  << e.what() << __E__;
1562  else if(isPauseException)
1563  __SUP_COUT__
1564  << "SOAP message failure indicating Supervisor asynchronous running SOFT "
1565  "exception back to Gateway: "
1566  << e.what() << __E__;
1567  else
1568  __SUP_COUT__ << "SOAP message failure indicating Supervisor asynchronous running "
1569  "error back to Gateway: "
1570  << e.what() << __E__;
1571  throw; // rethrow and hope error is noticed
1572 }
1573 catch(...)
1574 {
1575  if(isStopException)
1576  __SUP_COUT__
1577  << "Unknown error encounter indicating Supervisor asynchronous running "
1578  "STOP exception back to Gateway."
1579  << __E__;
1580  else if(isPauseException)
1581  __SUP_COUT__
1582  << "Unknown error encounter indicating Supervisor asynchronous running "
1583  "SOFT error back to Gateway."
1584  << __E__;
1585  else
1586  __SUP_COUT__
1587  << "Unknown error encounter indicating Supervisor asynchronous running "
1588  "error back to Gateway."
1589  << __E__;
1590  throw; // rethrow and hope error is noticed
1591 } // end SendAsyncErrorToGateway()
1592 
1593 //==============================================================================
1594 xoap::MessageReference CoreSupervisorBase::TRACESupervisorRequest(
1595  xoap::MessageReference message)
1596 {
1597  return CorePropertySupervisorBase::TRACESupervisorRequest(message);
1598 } // end TRACESupervisorRequest()
static std::string getOrPostData(cgicc::Cgicc &cgi, const std::string &needle)
static std::string getData(cgicc::Cgicc &cgi, const std::string &needle)
std::map< std::string, TableVersion > getActiveVersions(void) const
getActiveVersions
void loadTableGroup(const std::string &tableGroupName, const TableGroupKey &tableGroupKey, bool doActivate=false, std::map< std::string, TableVersion > *groupMembers=0, ProgressBar *progressBar=0, std::string *accumulateWarnings=0, std::string *groupComment=0, std::string *groupAuthor=0, std::string *groupCreateTime=0, bool doNotLoadMember=false, std::string *groupTypeString=0, std::map< std::string, std::string > *groupAliases=0, ConfigurationManager::LoadGroupType groupTypeToLoad=ConfigurationManager::LoadGroupType::ALL_TYPES, bool ignoreVersionTracking=false, std::map< std::string, TableVersion > mergeInTables={}, std::map< std::string, TableVersion > overrideTables={})
void getRequestUserInfo(WebUsers::RequestUserInfo &requestUserInfo)
virtual void transitionHalting(toolbox::Event::Reference event)
virtual void stateInitial(toolbox::fsm::FiniteStateMachine &fsm)
void stateMachineXgiHandler(xgi::Input *in, xgi::Output *out)
State Machine request handlers.
virtual void request(const std::string &requestType, cgicc::Cgicc &cgiIn, HttpXmlDocument &xmlOut, const WebUsers::RequestUserInfo &userInfo)
virtual void stateConfigured(toolbox::fsm::FiniteStateMachine &fsm)
virtual std::string getStatusProgressDetail(void)
virtual void statePaused(toolbox::fsm::FiniteStateMachine &fsm)
virtual void stateRunning(toolbox::fsm::FiniteStateMachine &fsm)
virtual void transitionInitializing(toolbox::Event::Reference event)
std::set< unsigned int > stateMachinesWaitingSubsystemIteration_
re-armed when the subsystem-iteration index changes
virtual void defaultPage(xgi::Input *in, xgi::Output *out)
virtual void nonXmlRequest(const std::string &requestType, cgicc::Cgicc &cgiIn, std::ostream &out, const WebUsers::RequestUserInfo &userInfo)
std::vector< bool > stateMachinesIterationDone_
for managing transition iterations
void sendAsyncExceptionToGateway(const std::string &errMsg, bool isPauseException, bool isStopException)
virtual void stateHalted(toolbox::fsm::FiniteStateMachine &fsm)
time_t getTimeInState(void) const
void outputXmlDocument(std::ostringstream *out, bool dispStdOut=false, bool allowWhiteSpace=false, bool printErrors=false)
bool xmlRequestToGateway(cgicc::Cgicc &cgi, std::ostringstream *out, HttpXmlDocument *xmldoc, const AllSupervisorInfo &allSupervisorInfo, WebUsers::RequestUserInfo &userInfo)
bool isFirstIteration(void) const
true on the very first call of a transition (all indices at their starting value)
std::string send(XDAQ_CONST_CALL xdaq::ApplicationDescriptor *d, xoap::MessageReference message)
XDAQ_CONST_CALL xdaq::ApplicationDescriptor * getDescriptor(void) const
Getters ----------------—.
HttpXmlDocument processRequest(cgicc::Cgicc &cgi)
defines used also by OtsConfigurationWizardSupervisor
void INIT_MF(const char *name)
static std::string mapToString(const std::map< std::string, T > &mapToReturn, const std::string &primaryDelimeter=", ", const std::string &secondaryDelimeter=": ")
static void getMapFromString(const std::string &inputString, std::map< S, T > &mapToReturn, const std::set< char > &pairPairDelimiter={',', '|', '&'}, const std::set< char > &nameValueDelimiter={'=', ':'}, const std::set< char > &whitespace={' ', '\t', '\n', '\r'})
getMapFromString ~
static std::string getTimeDurationString(const time_t durationInSeconds=time(0))
static std::string decodeURIComponent(const std::string &data)