1 #include "otsdaq-core/FiniteStateMachine/RunControlStateMachine.h"
2 #include "otsdaq-core/MessageFacility/MessageFacility.h"
4 #include "otsdaq-core/Macros/CoutMacros.h"
5 #include "otsdaq-core/Macros/StringMacros.h"
7 #include "otsdaq-core/SOAPUtilities/SOAPCommand.h"
8 #include "otsdaq-core/SOAPUtilities/SOAPUtilities.h"
10 #include <toolbox/fsm/FailedEvent.h>
11 #include <xdaq/NamespaceURI.h>
12 #include <xoap/Method.h>
17 #define __MF_SUBJECT__ std::string("FSM-") + theStateMachine_.getStateMachineName()
21 const std::string RunControlStateMachine::FAILED_STATE_NAME =
"Failed";
24 RunControlStateMachine::RunControlStateMachine(
const std::string& name)
25 : theStateMachine_(name)
26 , asyncFailureReceived_(false)
27 , asyncSoftFailureReceived_(false)
29 INIT_MF(
"RunControlStateMachine");
31 theStateMachine_.addState(
32 'I',
"Initial",
this, &RunControlStateMachine::stateInitial);
33 theStateMachine_.addState(
'H',
"Halted",
this, &RunControlStateMachine::stateHalted);
34 theStateMachine_.addState(
35 'C',
"Configured",
this, &RunControlStateMachine::stateConfigured);
36 theStateMachine_.addState(
37 'R',
"Running",
this, &RunControlStateMachine::stateRunning);
38 theStateMachine_.addState(
'P',
"Paused",
this, &RunControlStateMachine::statePaused);
39 theStateMachine_.addState(
40 'X',
"Shutdown",
this, &RunControlStateMachine::stateShutdown);
49 theStateMachine_.setStateName(
'F', RunControlStateMachine::FAILED_STATE_NAME);
50 theStateMachine_.setFailedStateTransitionAction(
51 this, &RunControlStateMachine::enteringError);
52 theStateMachine_.setFailedStateTransitionChanged(
this,
53 &RunControlStateMachine::inError);
56 RunControlStateMachine::addStateTransition(
57 'F',
'H',
"Halt",
"Halting",
this, &RunControlStateMachine::transitionHalting);
58 RunControlStateMachine::addStateTransition(
64 &RunControlStateMachine::transitionShuttingDown);
66 RunControlStateMachine::addStateTransition(
73 &RunControlStateMachine::transitionConfiguring);
74 RunControlStateMachine::addStateTransition(
80 &RunControlStateMachine::transitionShuttingDown);
81 RunControlStateMachine::addStateTransition(
87 &RunControlStateMachine::transitionStartingUp);
90 RunControlStateMachine::addStateTransition(
96 &RunControlStateMachine::transitionInitializing);
97 RunControlStateMachine::addStateTransition(
98 'H',
'H',
"Halt",
"Halting",
this, &RunControlStateMachine::transitionHalting);
99 RunControlStateMachine::addStateTransition(
100 'C',
'H',
"Halt",
"Halting",
this, &RunControlStateMachine::transitionHalting);
101 RunControlStateMachine::addStateTransition(
102 'R',
'H',
"Abort",
"Aborting",
this, &RunControlStateMachine::transitionHalting);
103 RunControlStateMachine::addStateTransition(
104 'P',
'H',
"Abort",
"Aborting",
this, &RunControlStateMachine::transitionHalting);
106 RunControlStateMachine::addStateTransition(
107 'R',
'P',
"Pause",
"Pausing",
this, &RunControlStateMachine::transitionPausing);
108 RunControlStateMachine::addStateTransition(
114 &RunControlStateMachine::transitionResuming);
115 RunControlStateMachine::addStateTransition(
116 'C',
'R',
"Start",
"Starting",
this, &RunControlStateMachine::transitionStarting);
117 RunControlStateMachine::addStateTransition(
118 'R',
'C',
"Stop",
"Stopping",
this, &RunControlStateMachine::transitionStopping);
119 RunControlStateMachine::addStateTransition(
120 'P',
'C',
"Stop",
"Stopping",
this, &RunControlStateMachine::transitionStopping);
125 &RunControlStateMachine::runControlMessageHandler,
129 &RunControlStateMachine::runControlMessageHandler,
133 this, &RunControlStateMachine::runControlMessageHandler,
"Start", XDAQ_NS_URI);
135 this, &RunControlStateMachine::runControlMessageHandler,
"Stop", XDAQ_NS_URI);
137 this, &RunControlStateMachine::runControlMessageHandler,
"Pause", XDAQ_NS_URI);
139 this, &RunControlStateMachine::runControlMessageHandler,
"Resume", XDAQ_NS_URI);
141 this, &RunControlStateMachine::runControlMessageHandler,
"Halt", XDAQ_NS_URI);
143 this, &RunControlStateMachine::runControlMessageHandler,
"Abort", XDAQ_NS_URI);
145 this, &RunControlStateMachine::runControlMessageHandler,
"Shutdown", XDAQ_NS_URI);
147 this, &RunControlStateMachine::runControlMessageHandler,
"Startup", XDAQ_NS_URI);
149 this, &RunControlStateMachine::runControlMessageHandler,
"Fail", XDAQ_NS_URI);
151 this, &RunControlStateMachine::runControlMessageHandler,
"Error", XDAQ_NS_URI);
154 &RunControlStateMachine::runControlMessageHandler,
158 &RunControlStateMachine::runControlMessageHandler,
166 RunControlStateMachine::~RunControlStateMachine(
void) {}
169 void RunControlStateMachine::reset(
void)
171 __COUT__ <<
"Resetting RunControlStateMachine with name '"
172 << theStateMachine_.getStateMachineName() <<
"'..." << __E__;
173 theStateMachine_.setInitialState(
'I');
174 theStateMachine_.reset();
176 theStateMachine_.setErrorMessage(
"",
false );
178 asyncFailureReceived_ =
false;
179 asyncSoftFailureReceived_ =
false;
211 xoap::MessageReference RunControlStateMachine::runControlMessageHandler(
212 xoap::MessageReference message)
215 __COUT__ <<
"Received... \t" << SOAPUtilities::translate(message) << std::endl;
217 std::string command = SOAPUtilities::translate(message).getCommand();
222 StringMacros::getNumber(
223 SOAPUtilities::translate(message).getParameters().getValue(
"iterationIndex"),
228 __COUT__ <<
"Defaulting iteration index to 0." << __E__;
234 StringMacros::getNumber(
235 SOAPUtilities::translate(message).getParameters().getValue(
236 "subIterationIndex"),
241 __COUT__ <<
"Defaulting subIterationIndex_ index to 0." << __E__;
242 subIterationIndex_ = 0;
248 if(SOAPUtilities::translate(message).getParameters().getValue(
"retransmission") ==
254 if(lastIterationCommand_ == command &&
255 lastIterationIndex_ == iterationIndex_ &&
256 lastSubIterationIndex_ == subIterationIndex_)
259 <<
"Assuming a timeout occurred at Gateway waiting for a response. "
260 <<
"Attempting to avoid error, by giving last result for command '"
261 << command <<
"': " << lastIterationResult_ << __E__;
262 return SOAPUtilities::makeSOAPMessageReference(lastIterationResult_);
265 __COUT__ <<
"Looks like Gateway command '" << command
266 <<
"' was lost - attempting to handle retransmission." << __E__;
274 lastIterationIndex_ = iterationIndex_;
275 lastSubIterationIndex_ = subIterationIndex_;
277 std::string currentState;
278 if(iterationIndex_ == 0 && subIterationIndex_ == 0)
281 theProgressBar_.reset(command, theStateMachine_.getStateMachineName());
282 currentState = theStateMachine_.getCurrentStateName();
283 __COUT__ <<
"Starting state for " << theStateMachine_.getStateMachineName()
284 <<
" is " << currentState <<
" and attempting to " << command
289 currentState = theStateMachine_.getStateName(lastIterationState_);
291 __COUT__ <<
"Iteration index " << iterationIndex_ <<
"." << subIterationIndex_
292 <<
" for " << theStateMachine_.getStateMachineName() <<
" from "
293 << currentState <<
" attempting to " << command << std::endl;
296 RunControlStateMachine::theProgressBar_.step();
298 std::string result = command +
"Done";
299 lastIterationResult_ = result;
303 if(command ==
"Error" || command ==
"Fail")
305 __SS__ << command <<
" was received! Halting immediately." << std::endl;
306 __COUT_ERR__ <<
"\n" << ss.str();
310 if(currentState ==
"Configured")
311 theStateMachine_.execTransition(
"Halt", message);
312 else if(currentState ==
"Running" || currentState ==
"Paused")
313 theStateMachine_.execTransition(
"Abort", message);
317 __COUT_ERR__ <<
"Halting failed in reaction to " << command <<
"... ignoring."
320 return SOAPUtilities::makeSOAPMessageReference(result);
322 else if(command ==
"AsyncError")
324 std::string errorMessage =
325 SOAPUtilities::translate(message).getParameters().getValue(
"ErrorMessage");
327 __SS__ << command <<
" was received! Error'ing immediately: " << errorMessage
329 __COUT_ERR__ <<
"\n" << ss.str();
330 theStateMachine_.setErrorMessage(ss.str());
332 asyncFailureReceived_ =
true;
334 theStateMachine_.execTransition(
"fail");
337 return SOAPUtilities::makeSOAPMessageReference(result);
339 else if(command ==
"AsyncSoftError")
341 std::string errorMessage =
342 SOAPUtilities::translate(message).getParameters().getValue(
"ErrorMessage");
344 __SS__ << command <<
" was received! Pause'ing immediately: " << errorMessage
346 __COUT_ERR__ <<
"\n" << ss.str();
347 theStateMachine_.setErrorMessage(ss.str());
349 if(!asyncSoftFailureReceived_)
351 asyncSoftFailureReceived_ =
true;
354 theStateMachine_.execTransition(
"Pause");
357 return SOAPUtilities::makeSOAPMessageReference(result);
362 if(command ==
"Initialize" && currentState ==
"Halted")
364 __COUT__ <<
"Already Initialized.. ignoring Initialize command." << std::endl;
366 theStateMachine_.setErrorMessage(
"",
false );
367 return SOAPUtilities::makeSOAPMessageReference(result);
373 theStateMachine_.setErrorMessage(
"",
false );
375 iterationWorkFlag_ =
false;
376 subIterationWorkFlag_ =
false;
377 if(iterationIndex_ || subIterationIndex_)
379 __COUT__ << command <<
" iteration " << iterationIndex_ <<
"."
380 << subIterationIndex_ << __E__;
381 toolbox::Event::Reference event(
new toolbox::Event(command,
this));
386 __COUT__ <<
"Iterating on the transition function from " << currentState
387 <<
" through " << lastIterationCommand_ << __E__;
389 auto itFrom = stateTransitionFunctionTable_.find(lastIterationState_);
390 if(itFrom == stateTransitionFunctionTable_.end())
392 __SS__ <<
"Cannot find transition function from '" << currentState
393 <<
"' with transition '" << lastIterationCommand_ <<
"!'"
395 __COUT_ERR__ << ss.str();
396 XCEPT_RAISE(toolbox::fsm::exception::Exception, ss.str());
399 auto itTransition = itFrom->second.find(lastIterationCommand_);
400 if(itTransition == itFrom->second.end())
402 __SS__ <<
"Cannot find transition function from '" << currentState
403 <<
"' with transition '" << lastIterationCommand_ <<
"!'"
405 __COUT_ERR__ << ss.str();
406 XCEPT_RAISE(toolbox::fsm::exception::Exception, ss.str());
409 (this->*(itTransition->second))(event);
416 lastIterationState_ = theStateMachine_.getCurrentState();
417 lastIterationCommand_ = command;
419 theStateMachine_.execTransition(command, message);
422 if(subIterationWorkFlag_)
424 __COUTV__(subIterationWorkFlag_);
426 command +
"SubIterate";
428 else if(iterationWorkFlag_)
430 __COUTV__(iterationWorkFlag_);
431 result = command +
"Iterate";
434 catch(toolbox::fsm::exception::Exception& e)
436 __SS__ <<
"Run Control Message Handling Failed: " << e.what() <<
" "
437 << theStateMachine_.getErrorMessage() << __E__;
438 __COUT_ERR__ << ss.str();
439 theStateMachine_.setErrorMessage(ss.str());
441 result = command +
" " + RunControlStateMachine::FAILED_STATE_NAME +
": " +
442 theStateMachine_.getErrorMessage();
446 __SS__ <<
"Run Control Message Handling encountered an unknown error."
447 << theStateMachine_.getErrorMessage() << __E__;
448 __COUT_ERR__ << ss.str();
449 theStateMachine_.setErrorMessage(ss.str());
451 result = command +
" " + RunControlStateMachine::FAILED_STATE_NAME +
": " +
452 theStateMachine_.getErrorMessage();
455 RunControlStateMachine::theProgressBar_.step();
457 currentState = theStateMachine_.getCurrentStateName();
459 if(currentState == RunControlStateMachine::FAILED_STATE_NAME)
461 result = command +
" " + RunControlStateMachine::FAILED_STATE_NAME +
": " +
462 theStateMachine_.getErrorMessage();
463 __COUT_ERR__ <<
"Unexpected Failure state for "
464 << theStateMachine_.getStateMachineName() <<
" is " << currentState
466 __COUT_ERR__ <<
"Error message was as follows: "
467 << theStateMachine_.getErrorMessage() << std::endl;
470 RunControlStateMachine::theProgressBar_.step();
472 if(!iterationWorkFlag_)
473 theProgressBar_.complete();
475 __COUT__ <<
"Ending state for " << theStateMachine_.getStateMachineName() <<
" is "
476 << currentState << std::endl;
477 __COUT__ <<
"result = " << result << std::endl;
478 lastIterationResult_ = result;
479 return SOAPUtilities::makeSOAPMessageReference(result);