otsdaq  v2_03_00
CoreSupervisorBase.cc
1 #include "otsdaq-core/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 {
28  __SUP_COUT__ << "Constructor." << __E__;
29 
30  INIT_MF("CoreSupervisorBase");
31 
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 
52  __SUP_COUT__ << "Constructed." << __E__;
53 } //end constructor
54 
55 //========================================================================================================================
56 CoreSupervisorBase::~CoreSupervisorBase(void)
57 {
58  __SUP_COUT__ << "Destructor." << __E__;
59  destroy();
60  __SUP_COUT__ << "Destructed." << __E__;
61 } // end destructor()
62 
63 //========================================================================================================================
64 void CoreSupervisorBase::destroy(void)
65 {
66  __SUP_COUT__ << "Destroying..." << __E__;
67  for(auto& it : theStateMachineImplementation_)
68  delete it;
69  theStateMachineImplementation_.clear();
70 } //end destroy()
71 
72 //========================================================================================================================
73 // wrapper for inheritance call
74 void CoreSupervisorBase::defaultPageWrapper(xgi::Input* in, xgi::Output* out)
75 {
76  return defaultPage(in, out);
77 }
78 
79 //========================================================================================================================
80 void CoreSupervisorBase::defaultPage(xgi::Input* in, xgi::Output* out)
81 {
82  __SUP_COUT__ << "Supervisor class " << supervisorClass_ << __E__;
83 
84  std::stringstream pagess;
85  pagess << "/WebPath/html/" << supervisorClassNoNamespace_
86  << ".html?urn=" << this->getApplicationDescriptor()->getLocalId();
87 
88  __SUP_COUT__ << "Default page = " << pagess.str() << __E__;
89 
90  *out << "<!DOCTYPE HTML><html lang='en'><frameset col='100%' row='100%'><frame src='"
91  << pagess.str() << "'></frameset></html>";
92 }
93 
94 //========================================================================================================================
95 // requestWrapper ~
96 // wrapper for inheritance Supervisor request call
97 void CoreSupervisorBase::requestWrapper(xgi::Input* in, xgi::Output* out)
98 
99 {
100  // checkSupervisorPropertySetup();
101 
102  cgicc::Cgicc cgiIn(in);
103  std::string requestType = CgiDataUtilities::getData(cgiIn, "RequestType");
104 
105  //__SUP_COUT__ << "requestType " << requestType << " files: " <<
106  // cgiIn.getFiles().size() << __E__;
107 
108  HttpXmlDocument xmlOut;
109  WebUsers::RequestUserInfo userInfo(
110  requestType, CgiDataUtilities::getOrPostData(cgiIn, "CookieCode"));
111 
112  CorePropertySupervisorBase::getRequestUserInfo(userInfo);
113 
114  if(!theRemoteWebUsers_.xmlRequestToGateway(
115  cgiIn, out, &xmlOut, CorePropertySupervisorBase::allSupervisorInfo_, userInfo))
116  return; // access failed
117 
118  // done checking cookieCode, sequence, userWithLock, and permissions access all in one
119  // shot!
120  //**** end LOGIN GATEWAY CODE ***//
121 
122  if(!userInfo.automatedCommand_)
123  __SUP_COUT__ << "requestType: " << requestType << __E__;
124 
125  if(userInfo.NonXMLRequestType_)
126  {
127  try
128  {
129  nonXmlRequest(requestType, cgiIn, *out, userInfo);
130  }
131  catch(const std::runtime_error& e)
132  {
133  __SUP_SS__ << "An error was encountered handling requestType '" << requestType
134  << "':" << e.what() << __E__;
135  __SUP_COUT_ERR__ << "\n" << ss.str();
136  __SUP_MOUT_ERR__ << "\n" << ss.str();
137  }
138  catch(...)
139  {
140  __SUP_SS__ << "An unknown error was encountered handling requestType '"
141  << requestType << ".' "
142  << "Please check the printouts to debug." << __E__;
143  __SUP_COUT_ERR__ << "\n" << ss.str();
144  __SUP_MOUT_ERR__ << "\n" << ss.str();
145  }
146  return;
147  }
148  // else xml request type
149 
150  try
151  {
152  // call derived class' request()
153  request(requestType, cgiIn, xmlOut, userInfo);
154  }
155  catch(const std::runtime_error& e)
156  {
157  __SUP_SS__ << "An error was encountered handling requestType '" << requestType
158  << "':" << e.what() << __E__;
159  __SUP_COUT_ERR__ << "\n" << ss.str();
160  xmlOut.addTextElementToData("Error", ss.str());
161  }
162  catch(...)
163  {
164  __SUP_SS__ << "An unknown error was encountered handling requestType '"
165  << requestType << ".' "
166  << "Please check the printouts to debug." << __E__;
167  __SUP_COUT_ERR__ << "\n" << ss.str();
168  xmlOut.addTextElementToData("Error", ss.str());
169  }
170 
171  // report any errors encountered
172  {
173  unsigned int occurance = 0;
174  std::string err = xmlOut.getMatchingValue("Error", occurance++);
175  while(err != "")
176  {
177  __SUP_COUT_ERR__ << "'" << requestType << "' ERROR encountered: " << err
178  << __E__;
179  __SUP_MOUT_ERR__ << "'" << requestType << "' ERROR encountered: " << err
180  << __E__;
181  err = xmlOut.getMatchingValue("Error", occurance++);
182  }
183  }
184 
185  // return xml doc holding server response
186  xmlOut.outputXmlDocument((std::ostringstream*)out,
187  false /*print to cout*/,
188  !userInfo.NoXmlWhiteSpace_ /*allow whitespace*/);
189 }
190 
191 //========================================================================================================================
192 // request
193 // Supervisors should override this function. It will be called after user access has
194 // been verified according to the Supervisor Property settings. The
195 // CoreSupervisorBase class provides consistent access, responses, and error
196 // handling across all inheriting supervisors that use ::request.
197 void CoreSupervisorBase::request(const std::string& requestType,
198  cgicc::Cgicc& cgiIn,
199  HttpXmlDocument& xmlOut,
200  const WebUsers::RequestUserInfo& userInfo)
201 {
202  __SUP_SS__ << "This is the empty Core Supervisor request. Supervisors should "
203  "override this function."
204  << __E__;
205  __SUP_COUT__ << ss.str();
206  xmlOut.addTextElementToData("Error", ss.str());
207  return;
208 
209  // KEEP:
210  // here are some possibly interesting example lines of code for overriding
211  // supervisors
212  //
213  // try
214  //{
215  //
216  // if(requestType == "savePlanCommandSequence")
217  // {
218  // std::string planName = CgiDataUtilities::getData(cgiIn,"planName");
220  // CgiDataUtilities::postData(cgiIn,"commands");
222  //
223  // cgiIn.getFiles()
224  // __SUP_COUT__ << "planName: " << planName << __E__;
225  // __SUP_COUTV__(commands);
226  //
227  //
228  // }
229  // else
230  // {
231  // __SUP_SS__ << "requestType '" << requestType << "' request not recognized." <<
232  // __E__;
233  // __SUP_SS_THROW__;
234  // }
235  // xmlOut.addTextElementToData("Error",
236  // "request encountered an error!");
237  //}
238  // catch(const std::runtime_error& e)
239  // {
240  // __SUP_SS__ << "An error was encountered handling requestType '" << requestType
241  //<< "':" << e.what() << __E__;
242  // __SUP_COUT_ERR__ << "\n" << ss.str();
243  // xmlOut.addTextElementToData("Error", ss.str());
244  // }
245  // catch(...)
246  // {
247  // __SUP_SS__ << "An unknown error was encountered handling requestType '" <<
248  // requestType << ".' " << "Please check the printouts to debug." <<
249  //__E__;
250  // __SUP_COUT_ERR__ << "\n" << ss.str();
251  // xmlOut.addTextElementToData("Error", ss.str());
252  // }
253  // END KEEP.
254 } // end request()
255 
256 //========================================================================================================================
257 // nonXmlRequest
258 // Supervisors should override this function. It will be called after user access has
259 // been verified according to the Supervisor Property settings. The
260 // CoreSupervisorBase class provides consistent access, responses, and error
261 // handling across all inheriting supervisors that use ::request.
262 void CoreSupervisorBase::nonXmlRequest(const std::string& requestType,
263  cgicc::Cgicc& cgiIn,
264  std::ostream& out,
265  const WebUsers::RequestUserInfo& userInfo)
266 {
267  __SUP_COUT__ << "This is the empty Core Supervisor non-xml request. Supervisors "
268  "should override this function."
269  << __E__;
270  out << "This is the empty Core Supervisor non-xml request. Supervisors should "
271  "override this function."
272  << __E__;
273 }
274 
275 //========================================================================================================================
276 void CoreSupervisorBase::stateMachineXgiHandler(xgi::Input* in, xgi::Output* out) {}
277 
278 //========================================================================================================================
279 void CoreSupervisorBase::stateMachineResultXgiHandler(xgi::Input* in, xgi::Output* out) {}
280 
281 //========================================================================================================================
282 xoap::MessageReference CoreSupervisorBase::stateMachineXoapHandler(
283  xoap::MessageReference message)
284 
285 {
286  __SUP_COUT__ << "Soap Handler!" << __E__;
287  stateMachineWorkLoopManager_.removeProcessedRequests();
288  stateMachineWorkLoopManager_.processRequest(message);
289  __SUP_COUT__ << "Done - Soap Handler!" << __E__;
290  return message;
291 }
292 
293 //========================================================================================================================
294 xoap::MessageReference CoreSupervisorBase::stateMachineResultXoapHandler(
295  xoap::MessageReference message)
296 
297 {
298  __SUP_COUT__ << "Soap Handler!" << __E__;
299  // stateMachineWorkLoopManager_.removeProcessedRequests();
300  // stateMachineWorkLoopManager_.processRequest(message);
301  __SUP_COUT__ << "Done - Soap Handler!" << __E__;
302  return message;
303 }
304 
305 //========================================================================================================================
306 // indirection to allow for overriding handler
307 xoap::MessageReference CoreSupervisorBase::workLoopStatusRequestWrapper(
308  xoap::MessageReference message)
309 
310 {
311  // this should have an override for monitoring work loops being done
312  return workLoopStatusRequest(message);
313 } // end workLoopStatusRequest()
314 
315 //========================================================================================================================
316 xoap::MessageReference CoreSupervisorBase::workLoopStatusRequest(
317  xoap::MessageReference message)
318 
319 {
320  // this should have an override for monitoring work loops being done
321  return SOAPUtilities::makeSOAPMessageReference(CoreSupervisorBase::WORK_LOOP_DONE);
322 } // end workLoopStatusRequest()
323 
324 //========================================================================================================================
325 bool CoreSupervisorBase::stateMachineThread(toolbox::task::WorkLoop* workLoop)
326 {
327  stateMachineSemaphore_.take();
328  __SUP_COUT__ << "Re-sending message..."
329  << SOAPUtilities::translate(
330  stateMachineWorkLoopManager_.getMessage(workLoop))
331  .getCommand()
332  << __E__;
333  std::string reply = send(this->getApplicationDescriptor(),
334  stateMachineWorkLoopManager_.getMessage(workLoop));
335  stateMachineWorkLoopManager_.report(workLoop, reply, 100, true);
336  __SUP_COUT__ << "Done with message" << __E__;
337  stateMachineSemaphore_.give();
338  return false; // execute once and automatically remove the workloop so in
339  // WorkLoopManager the try workLoop->remove(job_) could be commented
340  // out return true;//go on and then you must do the
341  // workLoop->remove(job_) in WorkLoopManager
342 }
343 
344 //========================================================================================================================
345 xoap::MessageReference CoreSupervisorBase::stateMachineStateRequest(
346  xoap::MessageReference message)
347 
348 {
349  __SUP_COUT__ << "theStateMachine_.getCurrentStateName() = "
350  << theStateMachine_.getCurrentStateName() << __E__;
351  return SOAPUtilities::makeSOAPMessageReference(
352  theStateMachine_.getCurrentStateName());
353 }
354 
355 //========================================================================================================================
356 xoap::MessageReference CoreSupervisorBase::stateMachineErrorMessageRequest(
357  xoap::MessageReference message)
358 
359 {
360  __SUP_COUT__ << "theStateMachine_.getErrorMessage() = "
361  << theStateMachine_.getErrorMessage() << __E__;
362 
363  SOAPParameters retParameters;
364  retParameters.addParameter("ErrorMessage", theStateMachine_.getErrorMessage());
365  return SOAPUtilities::makeSOAPMessageReference("stateMachineErrorMessageRequestReply",
366  retParameters);
367 }
368 
369 //========================================================================================================================
370 void CoreSupervisorBase::stateInitial(toolbox::fsm::FiniteStateMachine& fsm)
371 
372 {
373  __SUP_COUT__ << "CoreSupervisorBase::stateInitial" << __E__;
374 }
375 
376 //========================================================================================================================
377 void CoreSupervisorBase::stateHalted(toolbox::fsm::FiniteStateMachine& fsm)
378 
379 {
380  __SUP_COUT__ << "CoreSupervisorBase::stateHalted" << __E__;
381 }
382 
383 //========================================================================================================================
384 void CoreSupervisorBase::stateRunning(toolbox::fsm::FiniteStateMachine& fsm)
385 
386 {
387  __SUP_COUT__ << "CoreSupervisorBase::stateRunning" << __E__;
388 }
389 
390 //========================================================================================================================
391 void CoreSupervisorBase::stateConfigured(toolbox::fsm::FiniteStateMachine& fsm)
392 
393 {
394  __SUP_COUT__ << "CoreSupervisorBase::stateConfigured" << __E__;
395 }
396 
397 //========================================================================================================================
398 void CoreSupervisorBase::statePaused(toolbox::fsm::FiniteStateMachine& fsm)
399 
400 {
401  __SUP_COUT__ << "CoreSupervisorBase::statePaused" << __E__;
402 }
403 
404 //========================================================================================================================
405 void CoreSupervisorBase::inError(toolbox::fsm::FiniteStateMachine& fsm)
406 
407 {
408  __SUP_COUT__ << "Fsm current state: " << theStateMachine_.getCurrentStateName()
409  << __E__;
410  // rcmsStateNotifier_.stateChanged("Error", "");
411 }
412 
413 //========================================================================================================================
414 void CoreSupervisorBase::enteringError(toolbox::Event::Reference e)
415 
416 {
417  // __SUP_COUT__<< "Fsm current state: " << theStateMachine_.getCurrentStateName()
418  // << "\n\nError Message: " <<
419  // theStateMachine_.getErrorMessage() << __E__;
420  toolbox::fsm::FailedEvent& failedEvent = dynamic_cast<toolbox::fsm::FailedEvent&>(*e);
421  std::ostringstream error;
422  error << "Failure performing transition from " << failedEvent.getFromState() << " to "
423  << failedEvent.getToState()
424  << " exception: " << failedEvent.getException().what();
425  __SUP_COUT_ERR__ << error.str() << __E__;
426  // diagService_->reportError(errstr.str(),DIAGERROR);
427 }
428 
429 //========================================================================================================================
430 void CoreSupervisorBase::preStateMachineExecutionLoop(void)
431 {
432  RunControlStateMachine::clearIterationWork();
433  RunControlStateMachine::clearSubIterationWork();
434 
435  stateMachinesIterationWorkCount_ = 0;
436 
437  if(RunControlStateMachine::getIterationIndex() == 0 &&
438  RunControlStateMachine::getSubIterationIndex() == 0)
439  {
440  // reset vector for iterations done on first iteration
441 
442  subIterationWorkStateMachineIndex_ = -1; // clear sub iteration work index
443 
444  stateMachinesIterationDone_.resize(theStateMachineImplementation_.size());
445  for(unsigned int i = 0; i < stateMachinesIterationDone_.size(); ++i)
446  stateMachinesIterationDone_[i] = false;
447  }
448  else
449  __SUP_COUT__ << "Iteration " << RunControlStateMachine::getIterationIndex() << "."
450  << RunControlStateMachine::getSubIterationIndex() << "("
451  << subIterationWorkStateMachineIndex_ << ")" << __E__;
452 }
453 
454 //========================================================================================================================
455 void CoreSupervisorBase::preStateMachineExecution(unsigned int i)
456 {
457  if(i >= theStateMachineImplementation_.size())
458  {
459  __SUP_SS__ << "State Machine " << i << " not found!" << __E__;
460  __SUP_SS_THROW__;
461  }
462 
463  theStateMachineImplementation_[i]->VStateMachine::setIterationIndex(
464  RunControlStateMachine::getIterationIndex());
465  theStateMachineImplementation_[i]->VStateMachine::setSubIterationIndex(
466  RunControlStateMachine::getSubIterationIndex());
467 
468  theStateMachineImplementation_[i]->VStateMachine::clearIterationWork();
469  theStateMachineImplementation_[i]->VStateMachine::clearSubIterationWork();
470 
471  __SUP_COUT__
472  << "theStateMachineImplementation Iteration "
473  << theStateMachineImplementation_[i]->VStateMachine::getIterationIndex() << "."
474  << theStateMachineImplementation_[i]->VStateMachine::getSubIterationIndex()
475  << __E__;
476 }
477 
478 //========================================================================================================================
479 void CoreSupervisorBase::postStateMachineExecution(unsigned int i)
480 {
481  if(i >= theStateMachineImplementation_.size())
482  {
483  __SUP_SS__ << "State Machine " << i << " not found!" << __E__;
484  __SUP_SS_THROW__;
485  }
486 
487  // sub-iteration has priority
488  if(theStateMachineImplementation_[i]->VStateMachine::getSubIterationWork())
489  {
490  subIterationWorkStateMachineIndex_ = i;
491  RunControlStateMachine::indicateSubIterationWork();
492 
493  __SUP_COUT__ << "State machine " << i
494  << " is flagged for another sub-iteration..." << __E__;
495  }
496  else
497  {
498  stateMachinesIterationDone_[i] =
499  !theStateMachineImplementation_[i]->VStateMachine::getIterationWork();
500 
501  if(!stateMachinesIterationDone_[i])
502  {
503  __SUP_COUT__ << "State machine " << i
504  << " is flagged for another iteration..." << __E__;
505  RunControlStateMachine::indicateIterationWork(); // mark not done at
506  // CoreSupervisorBase level
507  ++stateMachinesIterationWorkCount_; // increment still working count
508  }
509  }
510 }
511 
512 //========================================================================================================================
513 void CoreSupervisorBase::postStateMachineExecutionLoop(void)
514 {
515  if(RunControlStateMachine::subIterationWorkFlag_)
516  __SUP_COUT__ << "State machine implementation "
517  << subIterationWorkStateMachineIndex_
518  << " is flagged for another sub-iteration..." << __E__;
519  else if(RunControlStateMachine::iterationWorkFlag_)
520  __SUP_COUT__
521  << stateMachinesIterationWorkCount_
522  << " state machine implementation(s) flagged for another iteration..."
523  << __E__;
524  else
525  __SUP_COUT__ << "Done configuration all state machine implementations..."
526  << __E__;
527 }
528 
529 //========================================================================================================================
530 void CoreSupervisorBase::transitionConfiguring(toolbox::Event::Reference e)
531 {
532  __SUP_COUT__ << "transitionConfiguring" << __E__;
533 
534  // activate the configuration tree (the first iteration)
535  if(RunControlStateMachine::getIterationIndex() == 0 &&
536  RunControlStateMachine::getSubIterationIndex() == 0)
537  {
538  std::pair<std::string /*group name*/, TableGroupKey> theGroup(
539  SOAPUtilities::translate(theStateMachine_.getCurrentMessage())
540  .getParameters()
541  .getValue("ConfigurationTableGroupName"),
542  TableGroupKey(SOAPUtilities::translate(theStateMachine_.getCurrentMessage())
543  .getParameters()
544  .getValue("ConfigurationTableGroupKey")));
545 
546  __SUP_COUT__ << "Configuration table group name: " << theGroup.first
547  << " key: " << theGroup.second << __E__;
548 
549  theConfigurationManager_->loadTableGroup(theGroup.first, theGroup.second, true);
550  }
551 
552  // Now that the configuration manager has all the necessary configurations,
553  // create all objects that depend on the configuration (the first iteration)
554 
555  try
556  {
557  __SUP_COUT__ << "Configuring all state machine implementations..." << __E__;
558  preStateMachineExecutionLoop();
559  for(unsigned int i = 0; i < theStateMachineImplementation_.size(); ++i)
560  {
561  // if one state machine is doing a sub-iteration, then target that one
562  if(subIterationWorkStateMachineIndex_ != (unsigned int)-1 &&
563  i != subIterationWorkStateMachineIndex_)
564  continue; // skip those not in the sub-iteration
565 
566  if(stateMachinesIterationDone_[i])
567  continue; // skip state machines already done
568 
569  preStateMachineExecution(i);
570  theStateMachineImplementation_[i]->parentSupervisor_ =
571  this; // for backwards compatibility, kept out of configure parameters
572  theStateMachineImplementation_[i]->configure(); // e.g. for FESupervisor,
573  // this is configure of
574  // FEVInterfacesManager
575  postStateMachineExecution(i);
576  }
577  postStateMachineExecutionLoop();
578  }
579  catch(const std::runtime_error& e)
580  {
581  __SUP_SS__ << "Error was caught while configuring: " << e.what() << __E__;
582  __SUP_COUT_ERR__ << "\n" << ss.str();
583  theStateMachine_.setErrorMessage(ss.str());
584  throw toolbox::fsm::exception::Exception(
585  "Transition Error" /*name*/,
586  ss.str() /* message*/,
587  "CoreSupervisorBase::transitionConfiguring" /*module*/,
588  __LINE__ /*line*/,
589  __FUNCTION__ /*function*/
590  );
591  }
592  catch(...)
593  {
594  __SUP_SS__
595  << "Unknown error was caught while configuring. Please checked the logs."
596  << __E__;
597  __SUP_COUT_ERR__ << "\n" << ss.str();
598  theStateMachine_.setErrorMessage(ss.str());
599  throw toolbox::fsm::exception::Exception(
600  "Transition Error" /*name*/,
601  ss.str() /* message*/,
602  "CoreSupervisorBase::transitionConfiguring" /*module*/,
603  __LINE__ /*line*/,
604  __FUNCTION__ /*function*/
605  );
606  }
607 } // end transitionConfiguring()
608 
609 //========================================================================================================================
610 // transitionHalting
611 // Ignore errors if coming from Failed state
612 void CoreSupervisorBase::transitionHalting(toolbox::Event::Reference e)
613 {
614  const std::string transitionName = "Halting";
615  try
616  {
617  __SUP_COUT__ << transitionName << " all state machine implementations..."
618  << __E__;
619  preStateMachineExecutionLoop();
620  for(unsigned int i = 0; i < theStateMachineImplementation_.size(); ++i)
621  {
622  // if one state machine is doing a sub-iteration, then target that one
623  if(subIterationWorkStateMachineIndex_ != (unsigned int)-1 &&
624  i != subIterationWorkStateMachineIndex_)
625  continue; // skip those not in the sub-iteration
626 
627  if(stateMachinesIterationDone_[i])
628  continue; // skip state machines already done
629 
630  preStateMachineExecution(i);
631  theStateMachineImplementation_[i]->halt(); // e.g. for FESupervisor, this is
632  // transition of
633  // FEVInterfacesManager
634  postStateMachineExecution(i);
635  }
636  postStateMachineExecutionLoop();
637  }
638  catch(const std::runtime_error& e)
639  {
640  // if halting from Failed state, then ignore errors
641  if(theStateMachine_.getProvenanceStateName() ==
642  RunControlStateMachine::FAILED_STATE_NAME)
643  {
644  __SUP_COUT_INFO__ << "Error was caught while halting (but ignoring because "
645  "previous state was '"
646  << RunControlStateMachine::FAILED_STATE_NAME
647  << "'): " << e.what() << __E__;
648  }
649  else // if not previously in Failed state, then fail
650  {
651  __SUP_SS__ << "Error was caught while " << transitionName << ": " << e.what()
652  << __E__;
653  __SUP_COUT_ERR__ << "\n" << ss.str();
654  theStateMachine_.setErrorMessage(ss.str());
655  throw toolbox::fsm::exception::Exception(
656  "Transition Error" /*name*/,
657  ss.str() /* message*/,
658  "CoreSupervisorBase::transition" + transitionName /*module*/,
659  __LINE__ /*line*/,
660  __FUNCTION__ /*function*/
661  );
662  }
663  }
664  catch(...)
665  {
666  // if halting from Failed state, then ignore errors
667  if(theStateMachine_.getProvenanceStateName() ==
668  RunControlStateMachine::FAILED_STATE_NAME)
669  {
670  __SUP_COUT_INFO__ << "Unknown error was caught while halting (but ignoring "
671  "because previous state was '"
672  << RunControlStateMachine::FAILED_STATE_NAME << "')."
673  << __E__;
674  }
675  else // if not previously in Failed state, then fail
676  {
677  __SUP_SS__ << "Unknown error was caught while " << transitionName
678  << ". Please checked the logs." << __E__;
679  __SUP_COUT_ERR__ << "\n" << ss.str();
680  theStateMachine_.setErrorMessage(ss.str());
681  throw toolbox::fsm::exception::Exception(
682  "Transition Error" /*name*/,
683  ss.str() /* message*/,
684  "CoreSupervisorBase::transition" + transitionName /*module*/,
685  __LINE__ /*line*/,
686  __FUNCTION__ /*function*/
687  );
688  }
689  }
690 } // end transitionHalting()
691 
692 //========================================================================================================================
693 // Inheriting supervisor classes should not override this function, or should at least
694 // also call it in the override to maintain property functionality.
695 void CoreSupervisorBase::transitionInitializing(toolbox::Event::Reference e)
696 {
697  __SUP_COUT__ << "transitionInitializing" << __E__;
698 
699  CorePropertySupervisorBase::resetPropertiesAreSetup(); // indicate need to re-load
700  // user properties
701 
702  // Note: Do not initialize the state machine implementations...
703  // do any initializing in configure
704  // This allows re-instantiation at each configure time.
705  // for(auto& it: theStateMachineImplementation_)
706  // it->initialize();
707 } // end transitionInitializing()
708 
709 //========================================================================================================================
710 void CoreSupervisorBase::transitionPausing(toolbox::Event::Reference e)
711 {
712  const std::string transitionName = "Pausing";
713  try
714  {
715  __SUP_COUT__ << "Configuring all state machine implementations..." << __E__;
716  preStateMachineExecutionLoop();
717  for(unsigned int i = 0; i < theStateMachineImplementation_.size(); ++i)
718  {
719  // if one state machine is doing a sub-iteration, then target that one
720  if(subIterationWorkStateMachineIndex_ != (unsigned int)-1 &&
721  i != subIterationWorkStateMachineIndex_)
722  continue; // skip those not in the sub-iteration
723 
724  if(stateMachinesIterationDone_[i])
725  continue; // skip state machines already done
726 
727  preStateMachineExecution(i);
728  theStateMachineImplementation_[i]->pause(); // e.g. for FESupervisor, this is
729  // transition of
730  // FEVInterfacesManager
731  postStateMachineExecution(i);
732  }
733  postStateMachineExecutionLoop();
734  }
735  catch(const std::runtime_error& e)
736  {
737  __SUP_SS__ << "Error was caught while " << transitionName << ": " << e.what()
738  << __E__;
739  __SUP_COUT_ERR__ << "\n" << ss.str();
740  theStateMachine_.setErrorMessage(ss.str());
741  throw toolbox::fsm::exception::Exception(
742  "Transition Error" /*name*/,
743  ss.str() /* message*/,
744  "CoreSupervisorBase::transition" + transitionName /*module*/,
745  __LINE__ /*line*/,
746  __FUNCTION__ /*function*/
747  );
748  }
749  catch(...)
750  {
751  __SUP_SS__ << "Unknown error was caught while " << transitionName
752  << ". Please checked the logs." << __E__;
753  __SUP_COUT_ERR__ << "\n" << ss.str();
754  theStateMachine_.setErrorMessage(ss.str());
755  throw toolbox::fsm::exception::Exception(
756  "Transition Error" /*name*/,
757  ss.str() /* message*/,
758  "CoreSupervisorBase::transition" + transitionName /*module*/,
759  __LINE__ /*line*/,
760  __FUNCTION__ /*function*/
761  );
762  }
763 } // end transitionPausing()
764 
765 //========================================================================================================================
766 void CoreSupervisorBase::transitionResuming(toolbox::Event::Reference e)
767 {
768  const std::string transitionName = "Resuming";
769  try
770  {
771  __SUP_COUT__ << "Configuring all state machine implementations..." << __E__;
772  preStateMachineExecutionLoop();
773  for(unsigned int i = 0; i < theStateMachineImplementation_.size(); ++i)
774  {
775  // if one state machine is doing a sub-iteration, then target that one
776  if(subIterationWorkStateMachineIndex_ != (unsigned int)-1 &&
777  i != subIterationWorkStateMachineIndex_)
778  continue; // skip those not in the sub-iteration
779 
780  if(stateMachinesIterationDone_[i])
781  continue; // skip state machines already done
782 
783  preStateMachineExecution(i);
784  theStateMachineImplementation_[i]->resume(); // e.g. for FESupervisor, this
785  // is transition of
786  // FEVInterfacesManager
787  postStateMachineExecution(i);
788  }
789  postStateMachineExecutionLoop();
790  }
791  catch(const std::runtime_error& e)
792  {
793  __SUP_SS__ << "Error was caught while " << transitionName << ": " << e.what()
794  << __E__;
795  __SUP_COUT_ERR__ << "\n" << ss.str();
796  theStateMachine_.setErrorMessage(ss.str());
797  throw toolbox::fsm::exception::Exception(
798  "Transition Error" /*name*/,
799  ss.str() /* message*/,
800  "CoreSupervisorBase::transition" + transitionName /*module*/,
801  __LINE__ /*line*/,
802  __FUNCTION__ /*function*/
803  );
804  }
805  catch(...)
806  {
807  __SUP_SS__ << "Unknown error was caught while " << transitionName
808  << ". Please checked the logs." << __E__;
809  __SUP_COUT_ERR__ << "\n" << ss.str();
810  theStateMachine_.setErrorMessage(ss.str());
811  throw toolbox::fsm::exception::Exception(
812  "Transition Error" /*name*/,
813  ss.str() /* message*/,
814  "CoreSupervisorBase::transition" + transitionName /*module*/,
815  __LINE__ /*line*/,
816  __FUNCTION__ /*function*/
817  );
818  }
819 } // end transitionResuming()
820 
821 //========================================================================================================================
822 void CoreSupervisorBase::transitionStarting(toolbox::Event::Reference e)
823 {
824  const std::string transitionName = "Starting";
825  const std::string runNumber =
826  SOAPUtilities::translate(theStateMachine_.getCurrentMessage())
827  .getParameters()
828  .getValue("RunNumber");
829  try
830  {
831  __SUP_COUT__ << "Configuring all state machine implementations..." << __E__;
832  preStateMachineExecutionLoop();
833  for(unsigned int i = 0; i < theStateMachineImplementation_.size(); ++i)
834  {
835  // if one state machine is doing a sub-iteration, then target that one
836  if(subIterationWorkStateMachineIndex_ != (unsigned int)-1 &&
837  i != subIterationWorkStateMachineIndex_)
838  continue; // skip those not in the sub-iteration
839 
840  if(stateMachinesIterationDone_[i])
841  continue; // skip state machines already done
842 
843  preStateMachineExecution(i);
844  theStateMachineImplementation_[i]->start(runNumber); // e.g. for
845  // FESupervisor, this is
846  // transition of
847  // FEVInterfacesManager
848  postStateMachineExecution(i);
849  }
850  postStateMachineExecutionLoop();
851  }
852  catch(const std::runtime_error& e)
853  {
854  __SUP_SS__ << "Error was caught while " << transitionName << ": " << e.what()
855  << __E__;
856  __SUP_COUT_ERR__ << "\n" << ss.str();
857  theStateMachine_.setErrorMessage(ss.str());
858  throw toolbox::fsm::exception::Exception(
859  "Transition Error" /*name*/,
860  ss.str() /* message*/,
861  "CoreSupervisorBase::transition" + transitionName /*module*/,
862  __LINE__ /*line*/,
863  __FUNCTION__ /*function*/
864  );
865  }
866  catch(...)
867  {
868  __SUP_SS__ << "Unknown error was caught while " << transitionName
869  << ". Please checked the logs." << __E__;
870  __SUP_COUT_ERR__ << "\n" << ss.str();
871  theStateMachine_.setErrorMessage(ss.str());
872  throw toolbox::fsm::exception::Exception(
873  "Transition Error" /*name*/,
874  ss.str() /* message*/,
875  "CoreSupervisorBase::transition" + transitionName /*module*/,
876  __LINE__ /*line*/,
877  __FUNCTION__ /*function*/
878  );
879  }
880 } // end transitionStarting()
881 
882 //========================================================================================================================
883 void CoreSupervisorBase::transitionStopping(toolbox::Event::Reference e)
884 {
885  const std::string transitionName = "Stopping";
886  try
887  {
888  __SUP_COUT__ << "Configuring all state machine implementations..." << __E__;
889  preStateMachineExecutionLoop();
890  for(unsigned int i = 0; i < theStateMachineImplementation_.size(); ++i)
891  {
892  // if one state machine is doing a sub-iteration, then target that one
893  if(subIterationWorkStateMachineIndex_ != (unsigned int)-1 &&
894  i != subIterationWorkStateMachineIndex_)
895  continue; // skip those not in the sub-iteration
896 
897  if(stateMachinesIterationDone_[i])
898  continue; // skip state machines already done
899 
900  preStateMachineExecution(i);
901  theStateMachineImplementation_[i]->stop(); // e.g. for FESupervisor, this is
902  // transition of
903  // FEVInterfacesManager
904  postStateMachineExecution(i);
905  }
906  postStateMachineExecutionLoop();
907  }
908  catch(const std::runtime_error& e)
909  {
910  __SUP_SS__ << "Error was caught while " << transitionName << ": " << e.what()
911  << __E__;
912  __SUP_COUT_ERR__ << "\n" << ss.str();
913  theStateMachine_.setErrorMessage(ss.str());
914  throw toolbox::fsm::exception::Exception(
915  "Transition Error" /*name*/,
916  ss.str() /* message*/,
917  "CoreSupervisorBase::transition" + transitionName /*module*/,
918  __LINE__ /*line*/,
919  __FUNCTION__ /*function*/
920  );
921  }
922  catch(...)
923  {
924  __SUP_SS__ << "Unknown error was caught while " << transitionName
925  << ". Please checked the logs." << __E__;
926  __SUP_COUT_ERR__ << "\n" << ss.str();
927  theStateMachine_.setErrorMessage(ss.str());
928  throw toolbox::fsm::exception::Exception(
929  "Transition Error" /*name*/,
930  ss.str() /* message*/,
931  "CoreSupervisorBase::transition" + transitionName /*module*/,
932  __LINE__ /*line*/,
933  __FUNCTION__ /*function*/
934  );
935  }
936 } // end transitionStopping()