otsdaq  3.06.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  {
851  //disable version tracking to accept untracked versions to be selected by the FSM transition source
852  theConfigurationManager_->loadTableGroup(
853  theGroup.first,
854  theGroup.second,
855  true /*doActivate*/,
856  0 /*groupMembers */,
857  0 /*progressBar */,
858  0 /*accumulateWarnings*/,
859  0 /*groupComment */,
860  0 /*groupAuthor */,
861  0 /*groupCreateTime */,
862  false /*doNotLoadMember */,
863  0 /*groupTypeString */,
864  0 /*groupAliases */,
865  ConfigurationManager::LoadGroupType::ALL_TYPES,
866  true /*ignoreVersionTracking*/,
867  mergeInTables /* mergeInTables */,
868  overrideTables /* overrideTables */
869  );
870  }
871  catch(const std::runtime_error& e)
872  {
873  __SS__ << "Error loading table group '" << theGroup.first << "("
874  << theGroup.second << ")! \n"
875  << e.what() << __E__;
876  __SUP_COUT_ERR__ << ss.str();
877  // ExceptionHandler(ExceptionHandlerRethrow::no, ss.str());
878 
879  //__SS_THROW_ONLY__;
880  theStateMachine_.setErrorMessage(ss.str());
881  throw toolbox::fsm::exception::Exception(
882  "Transition Error" /*name*/,
883  ss.str() /* message*/,
884  "CoreSupervisorBase::configureInit" /*module*/,
885  __LINE__ /*line*/,
886  __FUNCTION__ /*function*/
887  );
888  }
889  catch(...)
890  {
891  __SS__ << "Unknown error loading table group '" << theGroup.first << "("
892  << theGroup.second << ")!" << __E__;
893  try
894  {
895  throw;
896  } //one more try to printout extra info
897  catch(const std::exception& e)
898  {
899  ss << "Exception message: " << e.what();
900  }
901  catch(...)
902  {
903  }
904  __SUP_COUT_ERR__ << ss.str();
905  // ExceptionHandler(ExceptionHandlerRethrow::no, ss.str());
906 
907  //__SS_THROW_ONLY__;
908  theStateMachine_.setErrorMessage(ss.str());
909  throw toolbox::fsm::exception::Exception(
910  "Transition Error" /*name*/,
911  ss.str() /* message*/,
912  "CoreSupervisorBase::configureInit" /*module*/,
913  __LINE__ /*line*/,
914  __FUNCTION__ /*function*/
915  );
916  }
917 } //end configureInit()
918 
919 //==============================================================================
920 void CoreSupervisorBase::transitionConfiguring(toolbox::Event::Reference /*event*/)
921 {
922  __SUP_COUT__ << "transitionConfiguring()" << __E__;
923 
924  CoreSupervisorBase::configureInit();
925 
926  CoreSupervisorBase::transitionConfiguringFSMs();
927 
928  __SUP_COUT__ << "Configured." << __E__;
929 } // end transitionConfiguring()
930 
931 //==============================================================================
932 void CoreSupervisorBase::transitionConfiguringFSMs()
933 {
934  // Now that the configuration manager has all the necessary configurations,
935  // create all objects that depend on the configuration (the first iteration)
936 
937  try
938  {
939  __SUP_COUT__ << "Configuring all state machine implementations..." << __E__;
940  preStateMachineExecutionLoop();
941  for(unsigned int i = 0; i < theStateMachineImplementation_.size(); ++i)
942  {
943  // if one state machine is doing a sub-iteration, then target that one
944  if(subIterationWorkStateMachineIndex_ != (unsigned int)-1 &&
945  i != subIterationWorkStateMachineIndex_)
946  continue; // skip those not in the sub-iteration
947 
949  continue; // skip state machines already done
950 
951  preStateMachineExecution(i);
952  theStateMachineImplementation_[i]->parentSupervisor_ =
953  this; // for backwards compatibility, kept out of configure parameters
954  theStateMachineImplementation_[i]->configure(); // e.g. for FESupervisor,
955  // this is configure of
956  // FEVInterfacesManager
957  postStateMachineExecution(i);
958  }
959  postStateMachineExecutionLoop();
960  }
961  catch(const std::runtime_error& e)
962  {
963  __SUP_SS__ << "Error was caught while configuring: " << e.what() << __E__;
964  __SUP_COUT_ERR__ << "\n" << ss.str();
965  theStateMachine_.setErrorMessage(ss.str());
966  throw toolbox::fsm::exception::Exception(
967  "Transition Error" /*name*/,
968  ss.str() /* message*/,
969  "CoreSupervisorBase::transitionConfiguringFSMs" /*module*/,
970  __LINE__ /*line*/,
971  __FUNCTION__ /*function*/
972  );
973  }
974  catch(...)
975  {
976  __SUP_SS__
977  << "Unknown error was caught while configuring. Please checked the logs."
978  << __E__;
979  try
980  {
981  throw;
982  } //one more try to printout extra info
983  catch(const std::exception& e)
984  {
985  ss << "Exception message: " << e.what();
986  }
987  catch(...)
988  {
989  }
990  __SUP_COUT_ERR__ << "\n" << ss.str();
991  theStateMachine_.setErrorMessage(ss.str());
992  throw toolbox::fsm::exception::Exception(
993  "Transition Error" /*name*/,
994  ss.str() /* message*/,
995  "CoreSupervisorBase::transitionConfiguringFSMs" /*module*/,
996  __LINE__ /*line*/,
997  __FUNCTION__ /*function*/
998  );
999  }
1000 } // end transitionConfiguringFSMs()
1001 
1002 //==============================================================================
1005 void CoreSupervisorBase::transitionHalting(toolbox::Event::Reference /*event*/)
1006 {
1007  const std::string transitionName = "Halting";
1008  try
1009  {
1010  __SUP_COUT__ << transitionName << " all state machine implementations..."
1011  << __E__;
1012  preStateMachineExecutionLoop();
1013  for(unsigned int i = 0; i < theStateMachineImplementation_.size(); ++i)
1014  {
1015  // if one state machine is doing a sub-iteration, then target that one
1016  if(subIterationWorkStateMachineIndex_ != (unsigned int)-1 &&
1017  i != subIterationWorkStateMachineIndex_)
1018  continue; // skip those not in the sub-iteration
1019 
1021  continue; // skip state machines already done
1022 
1023  preStateMachineExecution(i);
1024  theStateMachineImplementation_[i]->halt(); // e.g. for FESupervisor, this is
1025  // transition of
1026  // FEVInterfacesManager
1027  postStateMachineExecution(i);
1028  }
1029  postStateMachineExecutionLoop();
1030  }
1031  catch(const std::runtime_error& e)
1032  {
1033  // if halting from Failed or Halted state, then ignore errors
1034  if(theStateMachine_.getProvenanceStateName() ==
1035  RunControlStateMachine::FAILED_STATE_NAME ||
1036  theStateMachine_.getProvenanceStateName() ==
1037  RunControlStateMachine::HALTED_STATE_NAME)
1038  {
1039  __SUP_COUT_INFO__ << "Error was caught while halting (but ignoring because "
1040  "previous state was '"
1041  << theStateMachine_.getProvenanceStateName()
1042  << "'): " << e.what() << __E__;
1043  }
1044  else // if not previously in Failed state, then fail
1045  {
1046  __SUP_SS__ << "Error was caught while " << transitionName << ": " << e.what()
1047  << __E__;
1048  __SUP_COUT_ERR__ << "\n" << ss.str();
1049  theStateMachine_.setErrorMessage(ss.str());
1050  throw toolbox::fsm::exception::Exception(
1051  "Transition Error" /*name*/,
1052  ss.str() /* message*/,
1053  "CoreSupervisorBase::transition" + transitionName /*module*/,
1054  __LINE__ /*line*/,
1055  __FUNCTION__ /*function*/
1056  );
1057  }
1058  }
1059  catch(...)
1060  {
1061  // if halting from Failed or Halted state, then ignore errors
1062  if(theStateMachine_.getProvenanceStateName() ==
1063  RunControlStateMachine::FAILED_STATE_NAME ||
1064  theStateMachine_.getProvenanceStateName() ==
1065  RunControlStateMachine::HALTED_STATE_NAME)
1066  {
1067  __SUP_COUT_INFO__ << "Unknown error was caught while halting (but ignoring "
1068  "because previous state was '"
1069  << theStateMachine_.getProvenanceStateName() << "')."
1070  << __E__;
1071  }
1072  else // if not previously in Failed state, then fail
1073  {
1074  __SUP_SS__ << "Unknown error was caught while " << transitionName
1075  << ". Please checked the logs." << __E__;
1076  try
1077  {
1078  throw;
1079  } //one more try to printout extra info
1080  catch(const std::exception& e)
1081  {
1082  ss << "Exception message: " << e.what();
1083  }
1084  catch(...)
1085  {
1086  }
1087  __SUP_COUT_ERR__ << "\n" << ss.str();
1088  theStateMachine_.setErrorMessage(ss.str());
1089  throw toolbox::fsm::exception::Exception(
1090  "Transition Error" /*name*/,
1091  ss.str() /* message*/,
1092  "CoreSupervisorBase::transition" + transitionName /*module*/,
1093  __LINE__ /*line*/,
1094  __FUNCTION__ /*function*/
1095  );
1096  }
1097  }
1098 } // end transitionHalting()
1099 
1100 //==============================================================================
1103 void CoreSupervisorBase::transitionInitializing(toolbox::Event::Reference /*event*/)
1104 {
1105  __SUP_COUT__ << "transitionInitializing" << __E__;
1106 
1107  CorePropertySupervisorBase::resetPropertiesAreSetup(); // indicate need to re-load
1108  // user properties
1109 
1110  // Note: Do not initialize the state machine implementations...
1111  // do any initializing in configure
1112  // This allows re-instantiation at each configure time.
1113  // for(auto& it: theStateMachineImplementation_)
1114  // it->initialize();
1115 } // end transitionInitializing()
1116 
1117 //==============================================================================
1118 void CoreSupervisorBase::transitionPausing(toolbox::Event::Reference /*event*/)
1119 {
1120  const std::string transitionName = "Pausing";
1121  try
1122  {
1123  __SUP_COUT__ << "Configuring all state machine implementations..." << __E__;
1124  preStateMachineExecutionLoop();
1125  for(unsigned int i = 0; i < theStateMachineImplementation_.size(); ++i)
1126  {
1127  // if one state machine is doing a sub-iteration, then target that one
1128  if(subIterationWorkStateMachineIndex_ != (unsigned int)-1 &&
1129  i != subIterationWorkStateMachineIndex_)
1130  continue; // skip those not in the sub-iteration
1131 
1133  continue; // skip state machines already done
1134 
1135  preStateMachineExecution(i);
1136  theStateMachineImplementation_[i]->pause(); // e.g. for FESupervisor, this is
1137  // transition of
1138  // FEVInterfacesManager
1139  postStateMachineExecution(i);
1140  }
1141  postStateMachineExecutionLoop();
1142  }
1143  catch(const std::runtime_error& e)
1144  {
1145  __SUP_SS__ << "Error was caught while " << transitionName << ": " << e.what()
1146  << __E__;
1147  __SUP_COUT_ERR__ << "\n" << ss.str();
1148  theStateMachine_.setErrorMessage(ss.str());
1149  throw toolbox::fsm::exception::Exception(
1150  "Transition Error" /*name*/,
1151  ss.str() /* message*/,
1152  "CoreSupervisorBase::transition" + transitionName /*module*/,
1153  __LINE__ /*line*/,
1154  __FUNCTION__ /*function*/
1155  );
1156  }
1157  catch(...)
1158  {
1159  __SUP_SS__ << "Unknown error was caught while " << transitionName
1160  << ". Please checked the logs." << __E__;
1161  try
1162  {
1163  throw;
1164  } //one more try to printout extra info
1165  catch(const std::exception& e)
1166  {
1167  ss << "Exception message: " << e.what();
1168  }
1169  catch(...)
1170  {
1171  }
1172  __SUP_COUT_ERR__ << "\n" << ss.str();
1173  theStateMachine_.setErrorMessage(ss.str());
1174  throw toolbox::fsm::exception::Exception(
1175  "Transition Error" /*name*/,
1176  ss.str() /* message*/,
1177  "CoreSupervisorBase::transition" + transitionName /*module*/,
1178  __LINE__ /*line*/,
1179  __FUNCTION__ /*function*/
1180  );
1181  }
1182 } // end transitionPausing()
1183 
1184 //==============================================================================
1185 void CoreSupervisorBase::transitionResuming(toolbox::Event::Reference /*event*/)
1186 {
1187  const std::string transitionName = "Resuming";
1188  try
1189  {
1190  __SUP_COUT__ << "Configuring all state machine implementations..." << __E__;
1191  preStateMachineExecutionLoop();
1192  for(unsigned int i = 0; i < theStateMachineImplementation_.size(); ++i)
1193  {
1194  // if one state machine is doing a sub-iteration, then target that one
1195  if(subIterationWorkStateMachineIndex_ != (unsigned int)-1 &&
1196  i != subIterationWorkStateMachineIndex_)
1197  continue; // skip those not in the sub-iteration
1198 
1200  continue; // skip state machines already done
1201 
1202  preStateMachineExecution(i);
1203  theStateMachineImplementation_[i]->resume(); // e.g. for FESupervisor, this
1204  // is transition of
1205  // FEVInterfacesManager
1206  postStateMachineExecution(i);
1207  }
1208  postStateMachineExecutionLoop();
1209  }
1210  catch(const std::runtime_error& e)
1211  {
1212  __SUP_SS__ << "Error was caught while " << transitionName << ": " << e.what()
1213  << __E__;
1214  __SUP_COUT_ERR__ << "\n" << ss.str();
1215  theStateMachine_.setErrorMessage(ss.str());
1216  throw toolbox::fsm::exception::Exception(
1217  "Transition Error" /*name*/,
1218  ss.str() /* message*/,
1219  "CoreSupervisorBase::transition" + transitionName /*module*/,
1220  __LINE__ /*line*/,
1221  __FUNCTION__ /*function*/
1222  );
1223  }
1224  catch(...)
1225  {
1226  __SUP_SS__ << "Unknown error was caught while " << transitionName
1227  << ". Please checked the logs." << __E__;
1228  try
1229  {
1230  throw;
1231  } //one more try to printout extra info
1232  catch(const std::exception& e)
1233  {
1234  ss << "Exception message: " << e.what();
1235  }
1236  catch(...)
1237  {
1238  }
1239  __SUP_COUT_ERR__ << "\n" << ss.str();
1240  theStateMachine_.setErrorMessage(ss.str());
1241  throw toolbox::fsm::exception::Exception(
1242  "Transition Error" /*name*/,
1243  ss.str() /* message*/,
1244  "CoreSupervisorBase::transition" + transitionName /*module*/,
1245  __LINE__ /*line*/,
1246  __FUNCTION__ /*function*/
1247  );
1248  }
1249 } // end transitionResuming()
1250 
1251 //==============================================================================
1252 void CoreSupervisorBase::transitionStarting(toolbox::Event::Reference /*event*/)
1253 {
1254  const std::string transitionName = "Starting";
1255  const std::string runNumber =
1256  SOAPUtilities::translate(theStateMachine_.getCurrentMessage())
1257  .getParameters()
1258  .getValue("RunNumber");
1259  try
1260  {
1261  __SUP_COUT__ << "Configuring all state machine implementations..." << __E__;
1262  preStateMachineExecutionLoop();
1263  for(unsigned int i = 0; i < theStateMachineImplementation_.size(); ++i)
1264  {
1265  // if one state machine is doing a sub-iteration, then target that one
1266  if(subIterationWorkStateMachineIndex_ != (unsigned int)-1 &&
1267  i != subIterationWorkStateMachineIndex_)
1268  continue; // skip those not in the sub-iteration
1269 
1271  continue; // skip state machines already done
1272 
1273  preStateMachineExecution(i);
1274  theStateMachineImplementation_[i]->start(runNumber); // e.g. for
1275  // FESupervisor, this is
1276  // transition of
1277  // FEVInterfacesManager
1278  postStateMachineExecution(i);
1279  }
1280  postStateMachineExecutionLoop();
1281  }
1282  catch(const std::runtime_error& e)
1283  {
1284  __SUP_SS__ << "Error was caught while " << transitionName << ": " << e.what()
1285  << __E__;
1286  __SUP_COUT_ERR__ << "\n" << ss.str();
1287  theStateMachine_.setErrorMessage(ss.str());
1288  throw toolbox::fsm::exception::Exception(
1289  "Transition Error" /*name*/,
1290  ss.str() /* message*/,
1291  "CoreSupervisorBase::transition" + transitionName /*module*/,
1292  __LINE__ /*line*/,
1293  __FUNCTION__ /*function*/
1294  );
1295  }
1296  catch(...)
1297  {
1298  __SUP_SS__ << "Unknown error was caught while " << transitionName
1299  << ". Please checked the logs." << __E__;
1300  try
1301  {
1302  throw;
1303  } //one more try to printout extra info
1304  catch(const std::exception& e)
1305  {
1306  ss << "Exception message: " << e.what();
1307  }
1308  catch(...)
1309  {
1310  }
1311  __SUP_COUT_ERR__ << "\n" << ss.str();
1312  theStateMachine_.setErrorMessage(ss.str());
1313  throw toolbox::fsm::exception::Exception(
1314  "Transition Error" /*name*/,
1315  ss.str() /* message*/,
1316  "CoreSupervisorBase::transition" + transitionName /*module*/,
1317  __LINE__ /*line*/,
1318  __FUNCTION__ /*function*/
1319  );
1320  }
1321 } // end transitionStarting()
1322 
1323 //==============================================================================
1324 void CoreSupervisorBase::transitionStopping(toolbox::Event::Reference /*event*/)
1325 {
1326  const std::string transitionName = "Stopping";
1327  try
1328  {
1329  __SUP_COUT__ << "Configuring all state machine implementations..." << __E__;
1330  preStateMachineExecutionLoop();
1331  for(unsigned int i = 0; i < theStateMachineImplementation_.size(); ++i)
1332  {
1333  // if one state machine is doing a sub-iteration, then target that one
1334  if(subIterationWorkStateMachineIndex_ != (unsigned int)-1 &&
1335  i != subIterationWorkStateMachineIndex_)
1336  continue; // skip those not in the sub-iteration
1337 
1339  continue; // skip state machines already done
1340 
1341  preStateMachineExecution(i);
1342  theStateMachineImplementation_[i]->stop(); // e.g. for FESupervisor, this is
1343  // transition of
1344  // FEVInterfacesManager
1345  postStateMachineExecution(i);
1346  }
1347  postStateMachineExecutionLoop();
1348  }
1349  catch(const std::runtime_error& e)
1350  {
1351  __SUP_SS__ << "Error was caught while " << transitionName << ": " << e.what()
1352  << __E__;
1353  __SUP_COUT_ERR__ << "\n" << ss.str();
1354  theStateMachine_.setErrorMessage(ss.str());
1355  throw toolbox::fsm::exception::Exception(
1356  "Transition Error" /*name*/,
1357  ss.str() /* message*/,
1358  "CoreSupervisorBase::transition" + transitionName /*module*/,
1359  __LINE__ /*line*/,
1360  __FUNCTION__ /*function*/
1361  );
1362  }
1363  catch(...)
1364  {
1365  __SUP_SS__ << "Unknown error was caught while " << transitionName
1366  << ". Please checked the logs." << __E__;
1367  try
1368  {
1369  throw;
1370  } //one more try to printout extra info
1371  catch(const std::exception& e)
1372  {
1373  ss << "Exception message: " << e.what();
1374  }
1375  catch(...)
1376  {
1377  }
1378  __SUP_COUT_ERR__ << "\n" << ss.str();
1379  theStateMachine_.setErrorMessage(ss.str());
1380  throw toolbox::fsm::exception::Exception(
1381  "Transition Error" /*name*/,
1382  ss.str() /* message*/,
1383  "CoreSupervisorBase::transition" + transitionName /*module*/,
1384  __LINE__ /*line*/,
1385  __FUNCTION__ /*function*/
1386  );
1387  }
1388 } // end transitionStopping()
1389 
1390 //==============================================================================
1395 void CoreSupervisorBase::sendAsyncExceptionToGateway(const std::string& errorMessage,
1396  bool isPauseException,
1397  bool isStopException)
1398 try
1399 {
1400  if(isStopException)
1401  __SUP_COUT_ERR__ << "Sending Supervisor Async STOP Running Exception... \n"
1402  << errorMessage << __E__;
1403  else if(isPauseException)
1404  __SUP_COUT_ERR__ << "Sending Supervisor Async SOFT Running Error... \n"
1405  << errorMessage << __E__;
1406  else
1407  __SUP_COUT_ERR__ << "Sending Supervisor Async Running Error... \n"
1408  << errorMessage << __E__;
1409 
1410  theStateMachine_.setErrorMessage(errorMessage);
1411 
1412  XDAQ_CONST_CALL xdaq::ApplicationDescriptor* gatewaySupervisor =
1413  allSupervisorInfo_.getGatewayInfo().getDescriptor();
1414 
1415  SOAPParameters parameters;
1416  parameters.addParameter("ErrorMessage", errorMessage);
1417 
1418  xoap::MessageReference replyMessage = SOAPMessenger::sendWithSOAPReply(
1419  gatewaySupervisor,
1420  isStopException ? "AsyncStopException"
1421  : (isPauseException ? "AsyncPauseException" : "AsyncError"),
1422  parameters);
1423 
1424  std::stringstream replyMessageSStream;
1425  replyMessageSStream << SOAPUtilities::translate(replyMessage);
1426  __SUP_COUT__ << "Received... " << replyMessageSStream.str() << std::endl;
1427 
1428  if(replyMessageSStream.str().find("Fault") != std::string::npos)
1429  {
1430  __SUP_COUT_ERR__ << "Failure to indicate fault to Gateway..." << __E__;
1431  throw;
1432  }
1433 }
1434 catch(const xdaq::exception::Exception& e)
1435 {
1436  if(isStopException)
1437  __SUP_COUT__
1438  << "SOAP message failure indicating Supervisor asynchronous running STOP "
1439  "exception back to Gateway: "
1440  << e.what() << __E__;
1441  else if(isPauseException)
1442  __SUP_COUT__
1443  << "SOAP message failure indicating Supervisor asynchronous running SOFT "
1444  "exception back to Gateway: "
1445  << e.what() << __E__;
1446  else
1447  __SUP_COUT__ << "SOAP message failure indicating Supervisor asynchronous running "
1448  "error back to Gateway: "
1449  << e.what() << __E__;
1450  throw; // rethrow and hope error is noticed
1451 }
1452 catch(...)
1453 {
1454  if(isStopException)
1455  __SUP_COUT__
1456  << "Unknown error encounter indicating Supervisor asynchronous running "
1457  "STOP exception back to Gateway."
1458  << __E__;
1459  else if(isPauseException)
1460  __SUP_COUT__
1461  << "Unknown error encounter indicating Supervisor asynchronous running "
1462  "SOFT error back to Gateway."
1463  << __E__;
1464  else
1465  __SUP_COUT__
1466  << "Unknown error encounter indicating Supervisor asynchronous running "
1467  "error back to Gateway."
1468  << __E__;
1469  throw; // rethrow and hope error is noticed
1470 } // end SendAsyncErrorToGateway()
1471 
1472 //==============================================================================
1473 xoap::MessageReference CoreSupervisorBase::TRACESupervisorRequest(
1474  xoap::MessageReference message)
1475 {
1476  return CorePropertySupervisorBase::TRACESupervisorRequest(message);
1477 } // 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)