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