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