otsdaq  3.10.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_COUT__ << "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_COUT__ << "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::clearIterationWork();
696  RunControlStateMachine::clearSubIterationWork();
697 
698  stateMachinesIterationWorkCount_ = 0;
699 
700  if(RunControlStateMachine::getIterationIndex() == 0 &&
701  RunControlStateMachine::getSubIterationIndex() == 0)
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  }
711  else
712  __SUP_COUT__ << "Iteration " << RunControlStateMachine::getIterationIndex() << "."
713  << RunControlStateMachine::getSubIterationIndex() << "("
714  << subIterationWorkStateMachineIndex_ << ")" << __E__;
715 }
716 
717 //==============================================================================
718 void CoreSupervisorBase::preStateMachineExecution(unsigned int i)
719 {
720  if(i >= theStateMachineImplementation_.size())
721  {
722  __SUP_SS__ << "State Machine " << i << " not found!" << __E__;
723  __SUP_SS_THROW__;
724  }
725 
726  theStateMachineImplementation_[i]->VStateMachine::setIterationIndex(
727  RunControlStateMachine::getIterationIndex());
728  theStateMachineImplementation_[i]->VStateMachine::setSubIterationIndex(
729  RunControlStateMachine::getSubIterationIndex());
730  theStateMachineImplementation_[i]
731  ->VStateMachine::setSystemMinReadyForEventGenerationStartIteration(
732  RunControlStateMachine::getMinReadyForEventGenerationStartIteration());
733 
734  theStateMachineImplementation_[i]->VStateMachine::clearIterationWork();
735  theStateMachineImplementation_[i]->VStateMachine::clearSubIterationWork();
736 
737  __SUP_COUT__
738  << "theStateMachineImplementation Iteration "
739  << theStateMachineImplementation_[i]->VStateMachine::getIterationIndex() << "."
740  << theStateMachineImplementation_[i]->VStateMachine::getSubIterationIndex()
741  << __E__;
742 }
743 
744 //==============================================================================
745 void CoreSupervisorBase::postStateMachineExecution(unsigned int i)
746 {
747  if(i >= theStateMachineImplementation_.size())
748  {
749  __SUP_SS__ << "State Machine " << i << " not found!" << __E__;
750  __SUP_SS_THROW__;
751  }
752 
753  // sub-iteration has priority
754  if(theStateMachineImplementation_[i]->VStateMachine::getSubIterationWork())
755  {
756  subIterationWorkStateMachineIndex_ = i;
757  RunControlStateMachine::indicateSubIterationWork();
758 
759  __SUP_COUT__ << "State machine " << i
760  << " is flagged for another sub-iteration..." << __E__;
761  }
762  else
763  {
765  !theStateMachineImplementation_[i]->VStateMachine::getIterationWork();
766 
768  {
769  __SUP_COUT__ << "State machine " << i
770  << " is flagged for another iteration..." << __E__;
771  RunControlStateMachine::indicateIterationWork(); // mark not done at
772  // CoreSupervisorBase level
773  ++stateMachinesIterationWorkCount_; // increment still working count
774  }
775  }
776 } // end postStateMachineExecution()
777 
778 //==============================================================================
779 void CoreSupervisorBase::postStateMachineExecutionLoop(void)
780 {
781  if(RunControlStateMachine::subIterationWorkFlag_)
782  __SUP_COUT__ << "State machine implementation "
783  << subIterationWorkStateMachineIndex_
784  << " is flagged for another sub-iteration..." << __E__;
785  else if(RunControlStateMachine::iterationWorkFlag_)
786  __SUP_COUT__
787  << stateMachinesIterationWorkCount_
788  << " state machine implementation(s) flagged for another iteration..."
789  << __E__;
790  else
791  __SUP_COUT__ << "Done configuration all state machine implementations..."
792  << __E__;
793 } // end postStateMachineExecutionLoop()
794 
795 //==============================================================================
796 void CoreSupervisorBase::configureInit(void)
797 {
798  // activate the configuration tree (only the first iteration)
799 
800  if(!(RunControlStateMachine::getIterationIndex() == 0 &&
801  RunControlStateMachine::getSubIterationIndex() == 0))
802  return;
803 
804  __SUP_COUT__ << "configureInit()" << __E__;
805 
806  std::pair<std::string /*group name*/, TableGroupKey> theGroup(
807  SOAPUtilities::translate(theStateMachine_.getCurrentMessage())
808  .getParameters()
809  .getValue("ConfigurationTableGroupName"),
810  TableGroupKey(SOAPUtilities::translate(theStateMachine_.getCurrentMessage())
811  .getParameters()
812  .getValue("ConfigurationTableGroupKey")));
813 
814  __SUP_COUT__ << "Configuration table group name: " << theGroup.first
815  << " key: " << theGroup.second << __E__;
816 
817  //fill System Variables
818  StringMacros::systemVariables_["ActiveStateMachine"]["name"] =
819  SOAPUtilities::translate(theStateMachine_.getCurrentMessage())
820  .getParameters()
821  .getValue("ActiveStateMachineName");
822  StringMacros::systemVariables_["ActiveStateMachine"]["windowName"] =
823  SOAPUtilities::translate(theStateMachine_.getCurrentMessage())
824  .getParameters()
825  .getValue("ActiveStateMachineWindowName");
826  StringMacros::systemVariables_["ActiveStateMachine"]["runAlias"] =
827  SOAPUtilities::translate(theStateMachine_.getCurrentMessage())
828  .getParameters()
829  .getValue("ActiveStateMachineRunAlias");
830  __SUP_COUTV__(StringMacros::mapToString(StringMacros::systemVariables_));
831 
832  // Assemble Subsystem Common Table List ----------------
833  std::map<std::string /* tableName */, TableVersion> mergeInTables, overrideTables;
834  {
835  { //handle common merge-in list
836  std::string subsystemCommonList;
837  try
838  {
839  subsystemCommonList =
840  SOAPUtilities::translate(theStateMachine_.getCurrentMessage())
841  .getParameters()
842  .getValue("SubsystemCommonList");
843  }
844  catch(...)
845  {
846  __COUT__ << "Ignoring missing 'SubsystemCommonList' parameter." << __E__;
847  }
848 
849  if(!subsystemCommonList.empty())
850  {
851  subsystemCommonList =
852  StringMacros::decodeURIComponent(subsystemCommonList);
853  __COUT__ << "Transition parameter SubsystemCommonList: "
854  << subsystemCommonList << __E__;
855  StringMacros::getMapFromString(subsystemCommonList, mergeInTables);
856  __COUTV__(StringMacros::mapToString(mergeInTables));
857  }
858  } //end handle common merge-in list
859 
860  { //handle common override list
861  std::string subsystemCommonOverrideList;
862  try
863  {
864  subsystemCommonOverrideList =
865  SOAPUtilities::translate(theStateMachine_.getCurrentMessage())
866  .getParameters()
867  .getValue("SubsystemCommonOverrideList");
868  }
869  catch(...)
870  {
871  __COUT__ << "Ignoring missing 'SubsystemCommonOverrideList' parameter."
872  << __E__;
873  }
874 
875  if(!subsystemCommonOverrideList.empty())
876  {
877  subsystemCommonOverrideList =
878  StringMacros::decodeURIComponent(subsystemCommonOverrideList);
879  __COUT__ << "Transition parameter SubsystemCommonOverrideList: "
880  << subsystemCommonOverrideList << __E__;
881  StringMacros::getMapFromString(subsystemCommonOverrideList,
882  overrideTables);
883  __COUTV__(StringMacros::mapToString(overrideTables));
884  }
885  } //end handle common override list
886  } // end Assemble Subsystem Common Table List ----------------
887 
888  try
889  {
891  theConfigurationManager_);
892  //disable version tracking to accept untracked versions to be selected by the FSM transition source
893  theConfigurationManager_->loadTableGroup(
894  theGroup.first,
895  theGroup.second,
896  true /*doActivate*/,
897  0 /*groupMembers */,
898  0 /*progressBar */,
899  0 /*accumulateWarnings*/,
900  0 /*groupComment */,
901  0 /*groupAuthor */,
902  0 /*groupCreateTime */,
903  false /*doNotLoadMember */,
904  0 /*groupTypeString */,
905  0 /*groupAliases */,
906  ConfigurationManager::LoadGroupType::ALL_TYPES,
907  true /*ignoreVersionTracking*/,
908  mergeInTables /* mergeInTables */,
909  overrideTables /* overrideTables */
910  );
911  }
912  catch(const std::runtime_error& e)
913  {
914  __SS__ << "Error loading table group '" << theGroup.first << "("
915  << theGroup.second << ")! \n"
916  << e.what() << __E__;
917  __SUP_COUT_ERR__ << ss.str();
918  // ExceptionHandler(ExceptionHandlerRethrow::no, ss.str());
919 
920  //__SS_THROW_ONLY__;
921  theStateMachine_.setErrorMessage(ss.str());
922  throw toolbox::fsm::exception::Exception(
923  "Transition Error" /*name*/,
924  ss.str() /* message*/,
925  "CoreSupervisorBase::configureInit" /*module*/,
926  __LINE__ /*line*/,
927  __FUNCTION__ /*function*/
928  );
929  }
930  catch(...)
931  {
932  __SS__ << "Unknown error loading table group '" << theGroup.first << "("
933  << theGroup.second << ")!" << __E__;
934  try
935  {
936  throw;
937  } //one more try to printout extra info
938  catch(const std::exception& e)
939  {
940  ss << "Exception message: " << e.what();
941  }
942  catch(...)
943  {
944  }
945  __SUP_COUT_ERR__ << ss.str();
946  // ExceptionHandler(ExceptionHandlerRethrow::no, ss.str());
947 
948  //__SS_THROW_ONLY__;
949  theStateMachine_.setErrorMessage(ss.str());
950  throw toolbox::fsm::exception::Exception(
951  "Transition Error" /*name*/,
952  ss.str() /* message*/,
953  "CoreSupervisorBase::configureInit" /*module*/,
954  __LINE__ /*line*/,
955  __FUNCTION__ /*function*/
956  );
957  }
958 } //end configureInit()
959 
960 //==============================================================================
961 void CoreSupervisorBase::transitionConfiguring(toolbox::Event::Reference /*event*/)
962 {
963  __SUP_COUT__ << "transitionConfiguring()" << __E__;
964 
965  CoreSupervisorBase::configureInit();
966 
967  CoreSupervisorBase::transitionConfiguringFSMs();
968 
969  __SUP_COUT__ << "Configured." << __E__;
970 } // end transitionConfiguring()
971 
972 //==============================================================================
973 void CoreSupervisorBase::transitionConfiguringFSMs()
974 {
975  // Now that the configuration manager has all the necessary configurations,
976  // create all objects that depend on the configuration (the first iteration)
977 
978  try
979  {
980  __SUP_COUT__ << "Configuring all state machine implementations..." << __E__;
981  preStateMachineExecutionLoop();
982  for(unsigned int i = 0; i < theStateMachineImplementation_.size(); ++i)
983  {
984  // if one state machine is doing a sub-iteration, then target that one
985  if(subIterationWorkStateMachineIndex_ != (unsigned int)-1 &&
986  i != subIterationWorkStateMachineIndex_)
987  continue; // skip those not in the sub-iteration
988 
990  continue; // skip state machines already done
991 
992  preStateMachineExecution(i);
993  theStateMachineImplementation_[i]->parentSupervisor_ =
994  this; // for backwards compatibility, kept out of configure parameters
995  theStateMachineImplementation_[i]->configure(); // e.g. for FESupervisor,
996  // this is configure of
997  // FEVInterfacesManager
998  postStateMachineExecution(i);
999  }
1000  postStateMachineExecutionLoop();
1001  }
1002  catch(const std::runtime_error& e)
1003  {
1004  __SUP_SS__ << "Error was caught while configuring: " << e.what() << __E__;
1005  __SUP_COUT_ERR__ << "\n" << ss.str();
1006  theStateMachine_.setErrorMessage(ss.str());
1007  throw toolbox::fsm::exception::Exception(
1008  "Transition Error" /*name*/,
1009  ss.str() /* message*/,
1010  "CoreSupervisorBase::transitionConfiguringFSMs" /*module*/,
1011  __LINE__ /*line*/,
1012  __FUNCTION__ /*function*/
1013  );
1014  }
1015  catch(...)
1016  {
1017  __SUP_SS__
1018  << "Unknown error was caught while configuring. Please checked the logs."
1019  << __E__;
1020  try
1021  {
1022  throw;
1023  } //one more try to printout extra info
1024  catch(const std::exception& e)
1025  {
1026  ss << "Exception message: " << e.what();
1027  }
1028  catch(...)
1029  {
1030  }
1031  __SUP_COUT_ERR__ << "\n" << ss.str();
1032  theStateMachine_.setErrorMessage(ss.str());
1033  throw toolbox::fsm::exception::Exception(
1034  "Transition Error" /*name*/,
1035  ss.str() /* message*/,
1036  "CoreSupervisorBase::transitionConfiguringFSMs" /*module*/,
1037  __LINE__ /*line*/,
1038  __FUNCTION__ /*function*/
1039  );
1040  }
1041 } // end transitionConfiguringFSMs()
1042 
1043 //==============================================================================
1046 void CoreSupervisorBase::transitionHalting(toolbox::Event::Reference /*event*/)
1047 {
1048  const std::string transitionName = "Halting";
1049  try
1050  {
1051  __SUP_COUT__ << transitionName << " all state machine implementations..."
1052  << __E__;
1053  preStateMachineExecutionLoop();
1054  for(unsigned int i = 0; i < theStateMachineImplementation_.size(); ++i)
1055  {
1056  // if one state machine is doing a sub-iteration, then target that one
1057  if(subIterationWorkStateMachineIndex_ != (unsigned int)-1 &&
1058  i != subIterationWorkStateMachineIndex_)
1059  continue; // skip those not in the sub-iteration
1060 
1062  continue; // skip state machines already done
1063 
1064  preStateMachineExecution(i);
1065  theStateMachineImplementation_[i]->halt(); // e.g. for FESupervisor, this is
1066  // transition of
1067  // FEVInterfacesManager
1068  postStateMachineExecution(i);
1069  }
1070  postStateMachineExecutionLoop();
1071  }
1072  catch(const std::runtime_error& e)
1073  {
1074  // if halting from Failed or Halted state, then ignore errors
1075  if(theStateMachine_.getProvenanceStateName() ==
1076  RunControlStateMachine::FAILED_STATE_NAME ||
1077  theStateMachine_.getProvenanceStateName() ==
1078  RunControlStateMachine::HALTED_STATE_NAME)
1079  {
1080  __SUP_COUT_INFO__ << "Error was caught while halting (but ignoring because "
1081  "previous state was '"
1082  << theStateMachine_.getProvenanceStateName()
1083  << "'): " << e.what() << __E__;
1084  }
1085  else // if not previously in Failed state, then fail
1086  {
1087  __SUP_SS__ << "Error was caught while " << transitionName << ": " << e.what()
1088  << __E__;
1089  __SUP_COUT_ERR__ << "\n" << ss.str();
1090  theStateMachine_.setErrorMessage(ss.str());
1091  throw toolbox::fsm::exception::Exception(
1092  "Transition Error" /*name*/,
1093  ss.str() /* message*/,
1094  "CoreSupervisorBase::transition" + transitionName /*module*/,
1095  __LINE__ /*line*/,
1096  __FUNCTION__ /*function*/
1097  );
1098  }
1099  }
1100  catch(...)
1101  {
1102  // if halting from Failed or Halted state, then ignore errors
1103  if(theStateMachine_.getProvenanceStateName() ==
1104  RunControlStateMachine::FAILED_STATE_NAME ||
1105  theStateMachine_.getProvenanceStateName() ==
1106  RunControlStateMachine::HALTED_STATE_NAME)
1107  {
1108  __SUP_COUT_INFO__ << "Unknown error was caught while halting (but ignoring "
1109  "because previous state was '"
1110  << theStateMachine_.getProvenanceStateName() << "')."
1111  << __E__;
1112  }
1113  else // if not previously in Failed state, then fail
1114  {
1115  __SUP_SS__ << "Unknown error was caught while " << transitionName
1116  << ". Please checked the logs." << __E__;
1117  try
1118  {
1119  throw;
1120  } //one more try to printout extra info
1121  catch(const std::exception& e)
1122  {
1123  ss << "Exception message: " << e.what();
1124  }
1125  catch(...)
1126  {
1127  }
1128  __SUP_COUT_ERR__ << "\n" << ss.str();
1129  theStateMachine_.setErrorMessage(ss.str());
1130  throw toolbox::fsm::exception::Exception(
1131  "Transition Error" /*name*/,
1132  ss.str() /* message*/,
1133  "CoreSupervisorBase::transition" + transitionName /*module*/,
1134  __LINE__ /*line*/,
1135  __FUNCTION__ /*function*/
1136  );
1137  }
1138  }
1139 } // end transitionHalting()
1140 
1141 //==============================================================================
1144 void CoreSupervisorBase::transitionInitializing(toolbox::Event::Reference /*event*/)
1145 {
1146  __SUP_COUT__ << "transitionInitializing" << __E__;
1147 
1148  CorePropertySupervisorBase::resetPropertiesAreSetup(); // indicate need to re-load
1149  // user properties
1150 
1151  // Note: Do not initialize the state machine implementations...
1152  // do any initializing in configure
1153  // This allows re-instantiation at each configure time.
1154  // for(auto& it: theStateMachineImplementation_)
1155  // it->initialize();
1156 } // end transitionInitializing()
1157 
1158 //==============================================================================
1159 void CoreSupervisorBase::transitionPausing(toolbox::Event::Reference /*event*/)
1160 {
1161  const std::string transitionName = "Pausing";
1162  try
1163  {
1164  __SUP_COUT__ << "Configuring all state machine implementations..." << __E__;
1165  preStateMachineExecutionLoop();
1166  for(unsigned int i = 0; i < theStateMachineImplementation_.size(); ++i)
1167  {
1168  // if one state machine is doing a sub-iteration, then target that one
1169  if(subIterationWorkStateMachineIndex_ != (unsigned int)-1 &&
1170  i != subIterationWorkStateMachineIndex_)
1171  continue; // skip those not in the sub-iteration
1172 
1174  continue; // skip state machines already done
1175 
1176  preStateMachineExecution(i);
1177  theStateMachineImplementation_[i]->pause(); // e.g. for FESupervisor, this is
1178  // transition of
1179  // FEVInterfacesManager
1180  postStateMachineExecution(i);
1181  }
1182  postStateMachineExecutionLoop();
1183  }
1184  catch(const std::runtime_error& e)
1185  {
1186  __SUP_SS__ << "Error was caught while " << transitionName << ": " << e.what()
1187  << __E__;
1188  __SUP_COUT_ERR__ << "\n" << ss.str();
1189  theStateMachine_.setErrorMessage(ss.str());
1190  throw toolbox::fsm::exception::Exception(
1191  "Transition Error" /*name*/,
1192  ss.str() /* message*/,
1193  "CoreSupervisorBase::transition" + transitionName /*module*/,
1194  __LINE__ /*line*/,
1195  __FUNCTION__ /*function*/
1196  );
1197  }
1198  catch(...)
1199  {
1200  __SUP_SS__ << "Unknown error was caught while " << transitionName
1201  << ". Please checked the logs." << __E__;
1202  try
1203  {
1204  throw;
1205  } //one more try to printout extra info
1206  catch(const std::exception& e)
1207  {
1208  ss << "Exception message: " << e.what();
1209  }
1210  catch(...)
1211  {
1212  }
1213  __SUP_COUT_ERR__ << "\n" << ss.str();
1214  theStateMachine_.setErrorMessage(ss.str());
1215  throw toolbox::fsm::exception::Exception(
1216  "Transition Error" /*name*/,
1217  ss.str() /* message*/,
1218  "CoreSupervisorBase::transition" + transitionName /*module*/,
1219  __LINE__ /*line*/,
1220  __FUNCTION__ /*function*/
1221  );
1222  }
1223 } // end transitionPausing()
1224 
1225 //==============================================================================
1226 void CoreSupervisorBase::transitionResuming(toolbox::Event::Reference /*event*/)
1227 {
1228  const std::string transitionName = "Resuming";
1229  try
1230  {
1231  __SUP_COUT__ << "Configuring all state machine implementations..." << __E__;
1232  preStateMachineExecutionLoop();
1233  for(unsigned int i = 0; i < theStateMachineImplementation_.size(); ++i)
1234  {
1235  // if one state machine is doing a sub-iteration, then target that one
1236  if(subIterationWorkStateMachineIndex_ != (unsigned int)-1 &&
1237  i != subIterationWorkStateMachineIndex_)
1238  continue; // skip those not in the sub-iteration
1239 
1241  continue; // skip state machines already done
1242 
1243  preStateMachineExecution(i);
1244  theStateMachineImplementation_[i]->resume(); // e.g. for FESupervisor, this
1245  // is transition of
1246  // FEVInterfacesManager
1247  postStateMachineExecution(i);
1248  }
1249  postStateMachineExecutionLoop();
1250  }
1251  catch(const std::runtime_error& e)
1252  {
1253  __SUP_SS__ << "Error was caught while " << transitionName << ": " << e.what()
1254  << __E__;
1255  __SUP_COUT_ERR__ << "\n" << ss.str();
1256  theStateMachine_.setErrorMessage(ss.str());
1257  throw toolbox::fsm::exception::Exception(
1258  "Transition Error" /*name*/,
1259  ss.str() /* message*/,
1260  "CoreSupervisorBase::transition" + transitionName /*module*/,
1261  __LINE__ /*line*/,
1262  __FUNCTION__ /*function*/
1263  );
1264  }
1265  catch(...)
1266  {
1267  __SUP_SS__ << "Unknown error was caught while " << transitionName
1268  << ". Please checked the logs." << __E__;
1269  try
1270  {
1271  throw;
1272  } //one more try to printout extra info
1273  catch(const std::exception& e)
1274  {
1275  ss << "Exception message: " << e.what();
1276  }
1277  catch(...)
1278  {
1279  }
1280  __SUP_COUT_ERR__ << "\n" << ss.str();
1281  theStateMachine_.setErrorMessage(ss.str());
1282  throw toolbox::fsm::exception::Exception(
1283  "Transition Error" /*name*/,
1284  ss.str() /* message*/,
1285  "CoreSupervisorBase::transition" + transitionName /*module*/,
1286  __LINE__ /*line*/,
1287  __FUNCTION__ /*function*/
1288  );
1289  }
1290 } // end transitionResuming()
1291 
1292 //==============================================================================
1293 void CoreSupervisorBase::transitionStarting(toolbox::Event::Reference /*event*/)
1294 {
1295  const std::string transitionName = "Starting";
1296  const std::string runNumber =
1297  SOAPUtilities::translate(theStateMachine_.getCurrentMessage())
1298  .getParameters()
1299  .getValue("RunNumber");
1300  try
1301  {
1302  __SUP_COUT__ << "Configuring all state machine implementations..." << __E__;
1303  preStateMachineExecutionLoop();
1304  for(unsigned int i = 0; i < theStateMachineImplementation_.size(); ++i)
1305  {
1306  // if one state machine is doing a sub-iteration, then target that one
1307  if(subIterationWorkStateMachineIndex_ != (unsigned int)-1 &&
1308  i != subIterationWorkStateMachineIndex_)
1309  continue; // skip those not in the sub-iteration
1310 
1312  continue; // skip state machines already done
1313 
1314  preStateMachineExecution(i);
1315  theStateMachineImplementation_[i]->start(runNumber); // e.g. for
1316  // FESupervisor, this is
1317  // transition of
1318  // FEVInterfacesManager
1319  postStateMachineExecution(i);
1320  }
1321  postStateMachineExecutionLoop();
1322  }
1323  catch(const std::runtime_error& e)
1324  {
1325  __SUP_SS__ << "Error was caught while " << transitionName << ": " << e.what()
1326  << __E__;
1327  __SUP_COUT_ERR__ << "\n" << ss.str();
1328  theStateMachine_.setErrorMessage(ss.str());
1329  throw toolbox::fsm::exception::Exception(
1330  "Transition Error" /*name*/,
1331  ss.str() /* message*/,
1332  "CoreSupervisorBase::transition" + transitionName /*module*/,
1333  __LINE__ /*line*/,
1334  __FUNCTION__ /*function*/
1335  );
1336  }
1337  catch(...)
1338  {
1339  __SUP_SS__ << "Unknown error was caught while " << transitionName
1340  << ". Please checked the logs." << __E__;
1341  try
1342  {
1343  throw;
1344  } //one more try to printout extra info
1345  catch(const std::exception& e)
1346  {
1347  ss << "Exception message: " << e.what();
1348  }
1349  catch(...)
1350  {
1351  }
1352  __SUP_COUT_ERR__ << "\n" << ss.str();
1353  theStateMachine_.setErrorMessage(ss.str());
1354  throw toolbox::fsm::exception::Exception(
1355  "Transition Error" /*name*/,
1356  ss.str() /* message*/,
1357  "CoreSupervisorBase::transition" + transitionName /*module*/,
1358  __LINE__ /*line*/,
1359  __FUNCTION__ /*function*/
1360  );
1361  }
1362 } // end transitionStarting()
1363 
1364 //==============================================================================
1365 void CoreSupervisorBase::transitionStopping(toolbox::Event::Reference /*event*/)
1366 {
1367  const std::string transitionName = "Stopping";
1368  try
1369  {
1370  __SUP_COUT__ << "Configuring all state machine implementations..." << __E__;
1371  preStateMachineExecutionLoop();
1372  for(unsigned int i = 0; i < theStateMachineImplementation_.size(); ++i)
1373  {
1374  // if one state machine is doing a sub-iteration, then target that one
1375  if(subIterationWorkStateMachineIndex_ != (unsigned int)-1 &&
1376  i != subIterationWorkStateMachineIndex_)
1377  continue; // skip those not in the sub-iteration
1378 
1380  continue; // skip state machines already done
1381 
1382  preStateMachineExecution(i);
1383  theStateMachineImplementation_[i]->stop(); // e.g. for FESupervisor, this is
1384  // transition of
1385  // FEVInterfacesManager
1386  postStateMachineExecution(i);
1387  }
1388  postStateMachineExecutionLoop();
1389  }
1390  catch(const std::runtime_error& e)
1391  {
1392  __SUP_SS__ << "Error was caught while " << transitionName << ": " << e.what()
1393  << __E__;
1394  __SUP_COUT_ERR__ << "\n" << ss.str();
1395  theStateMachine_.setErrorMessage(ss.str());
1396  throw toolbox::fsm::exception::Exception(
1397  "Transition Error" /*name*/,
1398  ss.str() /* message*/,
1399  "CoreSupervisorBase::transition" + transitionName /*module*/,
1400  __LINE__ /*line*/,
1401  __FUNCTION__ /*function*/
1402  );
1403  }
1404  catch(...)
1405  {
1406  __SUP_SS__ << "Unknown error was caught while " << transitionName
1407  << ". Please checked the logs." << __E__;
1408  try
1409  {
1410  throw;
1411  } //one more try to printout extra info
1412  catch(const std::exception& e)
1413  {
1414  ss << "Exception message: " << e.what();
1415  }
1416  catch(...)
1417  {
1418  }
1419  __SUP_COUT_ERR__ << "\n" << ss.str();
1420  theStateMachine_.setErrorMessage(ss.str());
1421  throw toolbox::fsm::exception::Exception(
1422  "Transition Error" /*name*/,
1423  ss.str() /* message*/,
1424  "CoreSupervisorBase::transition" + transitionName /*module*/,
1425  __LINE__ /*line*/,
1426  __FUNCTION__ /*function*/
1427  );
1428  }
1429 } // end transitionStopping()
1430 
1431 //==============================================================================
1436 void CoreSupervisorBase::sendAsyncExceptionToGateway(const std::string& errorMessage,
1437  bool isPauseException,
1438  bool isStopException)
1439 try
1440 {
1441  if(isStopException)
1442  __SUP_COUT_ERR__ << "Sending Supervisor Async STOP Running Exception... \n"
1443  << errorMessage << __E__;
1444  else if(isPauseException)
1445  __SUP_COUT_ERR__ << "Sending Supervisor Async SOFT Running Error... \n"
1446  << errorMessage << __E__;
1447  else
1448  __SUP_COUT_ERR__ << "Sending Supervisor Async Running Error... \n"
1449  << errorMessage << __E__;
1450 
1451  theStateMachine_.setErrorMessage(errorMessage);
1452 
1453  XDAQ_CONST_CALL xdaq::ApplicationDescriptor* gatewaySupervisor =
1454  allSupervisorInfo_.getGatewayInfo().getDescriptor();
1455 
1456  SOAPParameters parameters;
1457  parameters.addParameter("ErrorMessage", errorMessage);
1458 
1459  xoap::MessageReference replyMessage = SOAPMessenger::sendWithSOAPReply(
1460  gatewaySupervisor,
1461  isStopException ? "AsyncStopException"
1462  : (isPauseException ? "AsyncPauseException" : "AsyncError"),
1463  parameters);
1464 
1465  std::stringstream replyMessageSStream;
1466  replyMessageSStream << SOAPUtilities::translate(replyMessage);
1467  __SUP_COUT__ << "Received... " << replyMessageSStream.str() << std::endl;
1468 
1469  if(replyMessageSStream.str().find("Fault") != std::string::npos)
1470  {
1471  __SUP_COUT_ERR__ << "Failure to indicate fault to Gateway..." << __E__;
1472  throw;
1473  }
1474 }
1475 catch(const xdaq::exception::Exception& e)
1476 {
1477  if(isStopException)
1478  __SUP_COUT__
1479  << "SOAP message failure indicating Supervisor asynchronous running STOP "
1480  "exception back to Gateway: "
1481  << e.what() << __E__;
1482  else if(isPauseException)
1483  __SUP_COUT__
1484  << "SOAP message failure indicating Supervisor asynchronous running SOFT "
1485  "exception back to Gateway: "
1486  << e.what() << __E__;
1487  else
1488  __SUP_COUT__ << "SOAP message failure indicating Supervisor asynchronous running "
1489  "error back to Gateway: "
1490  << e.what() << __E__;
1491  throw; // rethrow and hope error is noticed
1492 }
1493 catch(...)
1494 {
1495  if(isStopException)
1496  __SUP_COUT__
1497  << "Unknown error encounter indicating Supervisor asynchronous running "
1498  "STOP exception back to Gateway."
1499  << __E__;
1500  else if(isPauseException)
1501  __SUP_COUT__
1502  << "Unknown error encounter indicating Supervisor asynchronous running "
1503  "SOFT error back to Gateway."
1504  << __E__;
1505  else
1506  __SUP_COUT__
1507  << "Unknown error encounter indicating Supervisor asynchronous running "
1508  "error back to Gateway."
1509  << __E__;
1510  throw; // rethrow and hope error is noticed
1511 } // end SendAsyncErrorToGateway()
1512 
1513 //==============================================================================
1514 xoap::MessageReference CoreSupervisorBase::TRACESupervisorRequest(
1515  xoap::MessageReference message)
1516 {
1517  return CorePropertySupervisorBase::TRACESupervisorRequest(message);
1518 } // end TRACESupervisorRequest()
static std::string getOrPostData(cgicc::Cgicc &cgi, const std::string &needle)
static std::string getData(cgicc::Cgicc &cgi, const std::string &needle)
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)
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)
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)