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