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