otsdaq  v2_04_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  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 {
99  // checkSupervisorPropertySetup();
100 
101  cgicc::Cgicc cgiIn(in);
102  std::string requestType = CgiDataUtilities::getData(cgiIn, "RequestType");
103 
104  // __SUP_COUT__ << "requestType " << requestType << " files: " <<
105  // cgiIn.getFiles().size() << __E__;
106 
107  HttpXmlDocument xmlOut;
108  WebUsers::RequestUserInfo userInfo(
109  requestType, CgiDataUtilities::getOrPostData(cgiIn, "CookieCode"));
110 
111  CorePropertySupervisorBase::getRequestUserInfo(userInfo);
112 
113  if(!theRemoteWebUsers_.xmlRequestToGateway(
114  cgiIn, out, &xmlOut, CorePropertySupervisorBase::allSupervisorInfo_, userInfo))
115  return; // access failed
116 
117  // done checking cookieCode, sequence, userWithLock, and permissions access all in one
118  // shot!
119  //**** end LOGIN GATEWAY CODE ***//
120 
121  if(!userInfo.automatedCommand_)
122  __SUP_COUT__ << "requestType: " << requestType << __E__;
123 
124  if(userInfo.NonXMLRequestType_)
125  {
126  try
127  {
128  nonXmlRequest(requestType, cgiIn, *out, userInfo);
129  }
130  catch(const std::runtime_error& e)
131  {
132  __SUP_SS__ << "An error was encountered handling requestType '" << requestType
133  << "':" << e.what() << __E__;
134  __SUP_COUT_ERR__ << "\n" << ss.str();
135  __SUP_MOUT_ERR__ << "\n" << ss.str();
136  }
137  catch(...)
138  {
139  __SUP_SS__ << "An unknown error was encountered handling requestType '"
140  << requestType << ".' "
141  << "Please check the printouts to debug." << __E__;
142  __SUP_COUT_ERR__ << "\n" << ss.str();
143  __SUP_MOUT_ERR__ << "\n" << ss.str();
144  }
145  return;
146  }
147  // else xml request type
148 
149  try
150  {
151  // call derived class' request()
152  request(requestType, cgiIn, xmlOut, 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  xmlOut.addTextElementToData("Error", ss.str());
160  }
161  catch(...)
162  {
163  __SUP_SS__ << "An unknown error was encountered handling requestType '"
164  << requestType << ".' "
165  << "Please check the printouts to debug." << __E__;
166  __SUP_COUT_ERR__ << "\n" << ss.str();
167  xmlOut.addTextElementToData("Error", ss.str());
168  }
169 
170  // report any errors encountered
171  {
172  unsigned int occurance = 0;
173  std::string err = xmlOut.getMatchingValue("Error", occurance++);
174  while(err != "")
175  {
176  __SUP_COUT_ERR__ << "'" << requestType << "' ERROR encountered: " << err
177  << __E__;
178  __SUP_MOUT_ERR__ << "'" << requestType << "' ERROR encountered: " << err
179  << __E__;
180  err = xmlOut.getMatchingValue("Error", occurance++);
181  }
182  }
183 
184  // return xml doc holding server response
185  xmlOut.outputXmlDocument((std::ostringstream*)out,
186  false /*print to cout*/,
187  !userInfo.NoXmlWhiteSpace_ /*allow whitespace*/);
188 }
189 
190 //========================================================================================================================
191 // request
192 // Supervisors should override this function. It will be called after user access has
193 // been verified according to the Supervisor Property settings. The
194 // CoreSupervisorBase class provides consistent access, responses, and error
195 // handling across all inheriting supervisors that use ::request.
196 void CoreSupervisorBase::request(const std::string& requestType,
197  cgicc::Cgicc& cgiIn,
198  HttpXmlDocument& xmlOut,
199  const WebUsers::RequestUserInfo& userInfo)
200 {
201  __SUP_SS__ << "This is the empty Core Supervisor request. Supervisors should "
202  "override this function."
203  << __E__;
204  __SUP_COUT__ << ss.str();
205  xmlOut.addTextElementToData("Error", ss.str());
206  return;
207 
208  // KEEP:
209  // here are some possibly interesting example lines of code for overriding
210  // supervisors
211  //
212  // try
213  //{
214  //
215  // if(requestType == "savePlanCommandSequence")
216  // {
217  // std::string planName = CgiDataUtilities::getData(cgiIn,"planName");
219  // CgiDataUtilities::postData(cgiIn,"commands");
221  //
222  // cgiIn.getFiles()
223  // __SUP_COUT__ << "planName: " << planName << __E__;
224  // __SUP_COUTV__(commands);
225  //
226  //
227  // }
228  // else
229  // {
230  // __SUP_SS__ << "requestType '" << requestType << "' request not recognized." <<
231  // __E__;
232  // __SUP_SS_THROW__;
233  // }
234  // xmlOut.addTextElementToData("Error",
235  // "request encountered an error!");
236  //}
237  // catch(const std::runtime_error& e)
238  // {
239  // __SUP_SS__ << "An error was encountered handling requestType '" << requestType
240  //<< "':" << e.what() << __E__;
241  // __SUP_COUT_ERR__ << "\n" << ss.str();
242  // xmlOut.addTextElementToData("Error", ss.str());
243  // }
244  // catch(...)
245  // {
246  // __SUP_SS__ << "An unknown error was encountered handling requestType '" <<
247  // requestType << ".' " << "Please check the printouts to debug." <<
248  //__E__;
249  // __SUP_COUT_ERR__ << "\n" << ss.str();
250  // xmlOut.addTextElementToData("Error", ss.str());
251  // }
252  // END KEEP.
253 } // end request()
254 
255 //========================================================================================================================
256 // nonXmlRequest
257 // Supervisors should override this function. It will be called after user access has
258 // been verified according to the Supervisor Property settings. The
259 // CoreSupervisorBase class provides consistent access, responses, and error
260 // handling across all inheriting supervisors that use ::request.
261 void CoreSupervisorBase::nonXmlRequest(const std::string& requestType,
262  cgicc::Cgicc& cgiIn,
263  std::ostream& out,
264  const WebUsers::RequestUserInfo& userInfo)
265 {
266  __SUP_COUT__ << "This is the empty Core Supervisor non-xml request. Supervisors "
267  "should override this function."
268  << __E__;
269  out << "This is the empty Core Supervisor non-xml request. Supervisors should "
270  "override this function."
271  << __E__;
272 }
273 
274 //========================================================================================================================
275 void CoreSupervisorBase::stateMachineXgiHandler(xgi::Input* in, xgi::Output* out) {}
276 
277 //========================================================================================================================
278 void CoreSupervisorBase::stateMachineResultXgiHandler(xgi::Input* in, xgi::Output* out) {}
279 
280 //========================================================================================================================
281 xoap::MessageReference CoreSupervisorBase::stateMachineXoapHandler(
282  xoap::MessageReference message)
283 
284 {
285  __SUP_COUT__ << "Soap Handler!" << __E__;
286  stateMachineWorkLoopManager_.removeProcessedRequests();
287  stateMachineWorkLoopManager_.processRequest(message);
288  __SUP_COUT__ << "Done - Soap Handler!" << __E__;
289  return message;
290 }
291 
292 //========================================================================================================================
293 xoap::MessageReference CoreSupervisorBase::stateMachineResultXoapHandler(
294  xoap::MessageReference message)
295 
296 {
297  __SUP_COUT__ << "Soap Handler!" << __E__;
298  // stateMachineWorkLoopManager_.removeProcessedRequests();
299  // stateMachineWorkLoopManager_.processRequest(message);
300  __SUP_COUT__ << "Done - Soap Handler!" << __E__;
301  return message;
302 }
303 
304 //========================================================================================================================
305 // indirection to allow for overriding handler
306 xoap::MessageReference CoreSupervisorBase::workLoopStatusRequestWrapper(
307  xoap::MessageReference message)
308 
309 {
310  // this should have an override for monitoring work loops being done
311  return workLoopStatusRequest(message);
312 } // end workLoopStatusRequest()
313 
314 //========================================================================================================================
315 xoap::MessageReference CoreSupervisorBase::workLoopStatusRequest(
316  xoap::MessageReference message)
317 
318 {
319  // this should have an override for monitoring work loops being done
320  return SOAPUtilities::makeSOAPMessageReference(CoreSupervisorBase::WORK_LOOP_DONE);
321 } // end workLoopStatusRequest()
322 
323 //========================================================================================================================
324 bool CoreSupervisorBase::stateMachineThread(toolbox::task::WorkLoop* workLoop)
325 {
326  stateMachineSemaphore_.take();
327  __SUP_COUT__ << "Re-sending message..."
328  << SOAPUtilities::translate(
329  stateMachineWorkLoopManager_.getMessage(workLoop))
330  .getCommand()
331  << __E__;
332  std::string reply = send(this->getApplicationDescriptor(),
333  stateMachineWorkLoopManager_.getMessage(workLoop));
334  stateMachineWorkLoopManager_.report(workLoop, reply, 100, true);
335  __SUP_COUT__ << "Done with message" << __E__;
336  stateMachineSemaphore_.give();
337  return false; // execute once and automatically remove the workloop so in
338  // WorkLoopManager the try workLoop->remove(job_) could be commented
339  // out return true;//go on and then you must do the
340  // workLoop->remove(job_) in WorkLoopManager
341 }
342 
343 //========================================================================================================================
344 xoap::MessageReference CoreSupervisorBase::stateMachineStateRequest(
345  xoap::MessageReference message)
346 
347 {
348  __SUP_COUT__ << "theStateMachine_.getCurrentStateName() = "
349  << theStateMachine_.getCurrentStateName() << __E__;
350  return SOAPUtilities::makeSOAPMessageReference(
351  theStateMachine_.getCurrentStateName());
352 }
353 
354 //========================================================================================================================
355 xoap::MessageReference CoreSupervisorBase::stateMachineErrorMessageRequest(
356  xoap::MessageReference message)
357 
358 {
359  __SUP_COUT__ << "theStateMachine_.getErrorMessage() = "
360  << theStateMachine_.getErrorMessage() << __E__;
361 
362  SOAPParameters retParameters;
363  retParameters.addParameter("ErrorMessage", theStateMachine_.getErrorMessage());
364  return SOAPUtilities::makeSOAPMessageReference("stateMachineErrorMessageRequestReply",
365  retParameters);
366 }
367 
368 //========================================================================================================================
369 void CoreSupervisorBase::stateInitial(toolbox::fsm::FiniteStateMachine& fsm)
370 
371 {
372  __SUP_COUT__ << "CoreSupervisorBase::stateInitial" << __E__;
373 }
374 
375 //========================================================================================================================
376 void CoreSupervisorBase::stateHalted(toolbox::fsm::FiniteStateMachine& fsm)
377 
378 {
379  __SUP_COUT__ << "CoreSupervisorBase::stateHalted" << __E__;
380 }
381 
382 //========================================================================================================================
383 void CoreSupervisorBase::stateRunning(toolbox::fsm::FiniteStateMachine& fsm)
384 
385 {
386  __SUP_COUT__ << "CoreSupervisorBase::stateRunning" << __E__;
387 }
388 
389 //========================================================================================================================
390 void CoreSupervisorBase::stateConfigured(toolbox::fsm::FiniteStateMachine& fsm)
391 
392 {
393  __SUP_COUT__ << "CoreSupervisorBase::stateConfigured" << __E__;
394 }
395 
396 //========================================================================================================================
397 void CoreSupervisorBase::statePaused(toolbox::fsm::FiniteStateMachine& fsm)
398 
399 {
400  __SUP_COUT__ << "CoreSupervisorBase::statePaused" << __E__;
401 }
402 
403 //========================================================================================================================
404 void CoreSupervisorBase::inError(toolbox::fsm::FiniteStateMachine& fsm)
405 
406 {
407  __SUP_COUT__ << "Fsm current state: " << theStateMachine_.getCurrentStateName()
408  << __E__;
409  // rcmsStateNotifier_.stateChanged("Error", "");
410 }
411 
412 //========================================================================================================================
413 void CoreSupervisorBase::enteringError(toolbox::Event::Reference e)
414 
415 {
416  // __SUP_COUT__<< "Fsm current state: " << theStateMachine_.getCurrentStateName()
417  // << "\n\nError Message: " <<
418  // theStateMachine_.getErrorMessage() << __E__;
419  toolbox::fsm::FailedEvent& failedEvent = dynamic_cast<toolbox::fsm::FailedEvent&>(*e);
420  std::ostringstream error;
421  error << "Failure performing transition from " << failedEvent.getFromState() << " to "
422  << failedEvent.getToState()
423  << " exception: " << failedEvent.getException().what();
424  __SUP_COUT_ERR__ << error.str() << __E__;
425  // diagService_->reportError(errstr.str(),DIAGERROR);
426 }
427 
428 //========================================================================================================================
429 void CoreSupervisorBase::preStateMachineExecutionLoop(void)
430 {
431  RunControlStateMachine::clearIterationWork();
432  RunControlStateMachine::clearSubIterationWork();
433 
434  stateMachinesIterationWorkCount_ = 0;
435 
436  if(RunControlStateMachine::getIterationIndex() == 0 &&
437  RunControlStateMachine::getSubIterationIndex() == 0)
438  {
439  // reset vector for iterations done on first iteration
440 
441  subIterationWorkStateMachineIndex_ = -1; // clear sub iteration work index
442 
443  stateMachinesIterationDone_.resize(theStateMachineImplementation_.size());
444  for(unsigned int i = 0; i < stateMachinesIterationDone_.size(); ++i)
445  stateMachinesIterationDone_[i] = false;
446  }
447  else
448  __SUP_COUT__ << "Iteration " << RunControlStateMachine::getIterationIndex() << "."
449  << RunControlStateMachine::getSubIterationIndex() << "("
450  << subIterationWorkStateMachineIndex_ << ")" << __E__;
451 }
452 
453 //========================================================================================================================
454 void CoreSupervisorBase::preStateMachineExecution(unsigned int i)
455 {
456  if(i >= theStateMachineImplementation_.size())
457  {
458  __SUP_SS__ << "State Machine " << i << " not found!" << __E__;
459  __SUP_SS_THROW__;
460  }
461 
462  theStateMachineImplementation_[i]->VStateMachine::setIterationIndex(
463  RunControlStateMachine::getIterationIndex());
464  theStateMachineImplementation_[i]->VStateMachine::setSubIterationIndex(
465  RunControlStateMachine::getSubIterationIndex());
466 
467  theStateMachineImplementation_[i]->VStateMachine::clearIterationWork();
468  theStateMachineImplementation_[i]->VStateMachine::clearSubIterationWork();
469 
470  __SUP_COUT__
471  << "theStateMachineImplementation Iteration "
472  << theStateMachineImplementation_[i]->VStateMachine::getIterationIndex() << "."
473  << theStateMachineImplementation_[i]->VStateMachine::getSubIterationIndex()
474  << __E__;
475 }
476 
477 //========================================================================================================================
478 void CoreSupervisorBase::postStateMachineExecution(unsigned int i)
479 {
480  if(i >= theStateMachineImplementation_.size())
481  {
482  __SUP_SS__ << "State Machine " << i << " not found!" << __E__;
483  __SUP_SS_THROW__;
484  }
485 
486  // sub-iteration has priority
487  if(theStateMachineImplementation_[i]->VStateMachine::getSubIterationWork())
488  {
489  subIterationWorkStateMachineIndex_ = i;
490  RunControlStateMachine::indicateSubIterationWork();
491 
492  __SUP_COUT__ << "State machine " << i
493  << " is flagged for another sub-iteration..." << __E__;
494  }
495  else
496  {
497  stateMachinesIterationDone_[i] =
498  !theStateMachineImplementation_[i]->VStateMachine::getIterationWork();
499 
500  if(!stateMachinesIterationDone_[i])
501  {
502  __SUP_COUT__ << "State machine " << i
503  << " is flagged for another iteration..." << __E__;
504  RunControlStateMachine::indicateIterationWork(); // mark not done at
505  // CoreSupervisorBase level
506  ++stateMachinesIterationWorkCount_; // increment still working count
507  }
508  }
509 }
510 
511 //========================================================================================================================
512 void CoreSupervisorBase::postStateMachineExecutionLoop(void)
513 {
514  if(RunControlStateMachine::subIterationWorkFlag_)
515  __SUP_COUT__ << "State machine implementation "
516  << subIterationWorkStateMachineIndex_
517  << " is flagged for another sub-iteration..." << __E__;
518  else if(RunControlStateMachine::iterationWorkFlag_)
519  __SUP_COUT__
520  << stateMachinesIterationWorkCount_
521  << " state machine implementation(s) flagged for another iteration..."
522  << __E__;
523  else
524  __SUP_COUT__ << "Done configuration all state machine implementations..."
525  << __E__;
526 }
527 
528 //========================================================================================================================
529 void CoreSupervisorBase::transitionConfiguring(toolbox::Event::Reference e)
530 {
531  __SUP_COUT__ << "transitionConfiguring" << __E__;
532 
533  // activate the configuration tree (the first iteration)
534  if(RunControlStateMachine::getIterationIndex() == 0 &&
535  RunControlStateMachine::getSubIterationIndex() == 0)
536  {
537  std::pair<std::string /*group name*/, TableGroupKey> theGroup(
538  SOAPUtilities::translate(theStateMachine_.getCurrentMessage())
539  .getParameters()
540  .getValue("ConfigurationTableGroupName"),
541  TableGroupKey(SOAPUtilities::translate(theStateMachine_.getCurrentMessage())
542  .getParameters()
543  .getValue("ConfigurationTableGroupKey")));
544 
545  __SUP_COUT__ << "Configuration table group name: " << theGroup.first
546  << " key: " << theGroup.second << __E__;
547 
548  theConfigurationManager_->loadTableGroup(
549  theGroup.first, theGroup.second, true /*doActivate*/);
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()