1 #include "otsdaq/FiniteStateMachine/RunControlStateMachine.h"
2 #include "otsdaq/MessageFacility/MessageFacility.h"
4 #include "otsdaq/Macros/CoutMacros.h"
5 #include "otsdaq/Macros/StringMacros.h"
7 #include "otsdaq/SOAPUtilities/SOAPCommand.h"
8 #include "otsdaq/SOAPUtilities/SOAPUtilities.h"
10 #include <toolbox/fsm/FailedEvent.h>
11 #include <xdaq/NamespaceURI.h>
12 #include <xoap/Method.h>
17 #define __MF_SUBJECT__ "FSM"
18 #define mfSubject_ std::string("FSM-") + theStateMachine_.getStateMachineName()
22 const std::string RunControlStateMachine::FAILED_STATE_NAME =
"Failed";
23 const std::string RunControlStateMachine::HALTED_STATE_NAME =
"Halted";
26 RunControlStateMachine::RunControlStateMachine(
const std::string& name) : theStateMachine_(name), asyncFailureReceived_(false), asyncSoftFailureReceived_(false)
30 theStateMachine_.addState(
'I',
"Initial",
this, &RunControlStateMachine::stateInitial);
31 theStateMachine_.addState(
'H', RunControlStateMachine::HALTED_STATE_NAME,
this, &RunControlStateMachine::stateHalted);
32 theStateMachine_.addState(
'C',
"Configured",
this, &RunControlStateMachine::stateConfigured);
33 theStateMachine_.addState(
'R',
"Running",
this, &RunControlStateMachine::stateRunning);
34 theStateMachine_.addState(
'P',
"Paused",
this, &RunControlStateMachine::statePaused);
35 theStateMachine_.addState(
'X',
"Shutdown",
this, &RunControlStateMachine::stateShutdown);
44 theStateMachine_.setStateName(
'F', RunControlStateMachine::FAILED_STATE_NAME);
45 theStateMachine_.setFailedStateTransitionAction(
this, &RunControlStateMachine::enteringError);
46 theStateMachine_.setFailedStateTransitionChanged(
this, &RunControlStateMachine::inError);
49 RunControlStateMachine::addStateTransition(
'F',
'H',
"Halt",
"Halting",
this, &RunControlStateMachine::transitionHalting);
50 RunControlStateMachine::addStateTransition(
'F',
'X',
"Shutdown",
"Shutting Down",
this, &RunControlStateMachine::transitionShuttingDown);
52 RunControlStateMachine::addStateTransition(
53 'H',
'C',
"Configure",
"Configuring",
"ConfigurationAlias",
this, &RunControlStateMachine::transitionConfiguring);
54 RunControlStateMachine::addStateTransition(
'H',
'X',
"Shutdown",
"Shutting Down",
this, &RunControlStateMachine::transitionShuttingDown);
55 RunControlStateMachine::addStateTransition(
'X',
'I',
"Startup",
"Starting Up",
this, &RunControlStateMachine::transitionStartingUp);
58 RunControlStateMachine::addStateTransition(
'I',
'H',
"Initialize",
"Initializing",
this, &RunControlStateMachine::transitionInitializing);
59 RunControlStateMachine::addStateTransition(
'H',
'H',
"Halt",
"Halting",
this, &RunControlStateMachine::transitionHalting);
60 RunControlStateMachine::addStateTransition(
'C',
'H',
"Halt",
"Halting",
this, &RunControlStateMachine::transitionHalting);
61 RunControlStateMachine::addStateTransition(
'R',
'H',
"Abort",
"Aborting",
this, &RunControlStateMachine::transitionHalting);
62 RunControlStateMachine::addStateTransition(
'P',
'H',
"Abort",
"Aborting",
this, &RunControlStateMachine::transitionHalting);
64 RunControlStateMachine::addStateTransition(
'R',
'P',
"Pause",
"Pausing",
this, &RunControlStateMachine::transitionPausing);
65 RunControlStateMachine::addStateTransition(
'P',
'R',
"Resume",
"Resuming",
this, &RunControlStateMachine::transitionResuming);
66 RunControlStateMachine::addStateTransition(
'C',
'R',
"Start",
"Starting",
this, &RunControlStateMachine::transitionStarting);
67 RunControlStateMachine::addStateTransition(
'R',
'C',
"Stop",
"Stopping",
this, &RunControlStateMachine::transitionStopping);
68 RunControlStateMachine::addStateTransition(
'P',
'C',
"Stop",
"Stopping",
this, &RunControlStateMachine::transitionStopping);
72 xoap::bind(
this, &RunControlStateMachine::runControlMessageHandler,
"Initialize", XDAQ_NS_URI);
73 xoap::bind(
this, &RunControlStateMachine::runControlMessageHandler,
"Configure", XDAQ_NS_URI);
74 xoap::bind(
this, &RunControlStateMachine::runControlMessageHandler,
"Start", XDAQ_NS_URI);
75 xoap::bind(
this, &RunControlStateMachine::runControlMessageHandler,
"Stop", XDAQ_NS_URI);
76 xoap::bind(
this, &RunControlStateMachine::runControlMessageHandler,
"Pause", XDAQ_NS_URI);
77 xoap::bind(
this, &RunControlStateMachine::runControlMessageHandler,
"Resume", XDAQ_NS_URI);
78 xoap::bind(
this, &RunControlStateMachine::runControlMessageHandler,
"Halt", XDAQ_NS_URI);
79 xoap::bind(
this, &RunControlStateMachine::runControlMessageHandler,
"Abort", XDAQ_NS_URI);
80 xoap::bind(
this, &RunControlStateMachine::runControlMessageHandler,
"Shutdown", XDAQ_NS_URI);
81 xoap::bind(
this, &RunControlStateMachine::runControlMessageHandler,
"Startup", XDAQ_NS_URI);
82 xoap::bind(
this, &RunControlStateMachine::runControlMessageHandler,
"Fail", XDAQ_NS_URI);
83 xoap::bind(
this, &RunControlStateMachine::runControlMessageHandler,
"Error", XDAQ_NS_URI);
85 xoap::bind(
this, &RunControlStateMachine::runControlMessageHandler,
"AsyncError", XDAQ_NS_URI);
86 xoap::bind(
this, &RunControlStateMachine::runControlMessageHandler,
"AsyncSoftError", XDAQ_NS_URI);
92 RunControlStateMachine::~RunControlStateMachine(
void) {}
95 void RunControlStateMachine::reset(
void)
97 __GEN_COUT__ <<
"Resetting RunControlStateMachine with name '" << theStateMachine_.getStateMachineName() <<
"'..." << __E__;
98 theStateMachine_.setInitialState(
'I');
99 theStateMachine_.reset();
101 theStateMachine_.setErrorMessage(
"",
false );
103 asyncFailureReceived_ =
false;
104 asyncSoftFailureReceived_ =
false;
136 xoap::MessageReference RunControlStateMachine::runControlMessageHandler(xoap::MessageReference message)
139 __GEN_COUT__ <<
"Received... \t" << SOAPUtilities::translate(message) << std::endl;
141 std::string command = SOAPUtilities::translate(message).getCommand();
146 StringMacros::getNumber(SOAPUtilities::translate(message).getParameters().getValue(
"iterationIndex"), iterationIndex_);
150 __GEN_COUT__ <<
"Defaulting iteration index to 0." << __E__;
156 StringMacros::getNumber(SOAPUtilities::translate(message).getParameters().getValue(
"subIterationIndex"), subIterationIndex_);
160 __GEN_COUT__ <<
"Defaulting subIterationIndex_ index to 0." << __E__;
161 subIterationIndex_ = 0;
167 if(SOAPUtilities::translate(message).getParameters().getValue(
"retransmission") ==
"1")
172 if(lastIterationCommand_ == command && lastIterationIndex_ == iterationIndex_ && lastSubIterationIndex_ == subIterationIndex_)
174 __GEN_COUT__ <<
"Assuming a timeout occurred at Gateway waiting for a response. "
175 <<
"Attempting to avoid error, by giving last result for command '" << command <<
"': " << lastIterationResult_ << __E__;
176 return SOAPUtilities::makeSOAPMessageReference(lastIterationResult_);
179 __GEN_COUT__ <<
"Looks like Gateway command '" << command <<
"' was lost - attempting to handle retransmission." << __E__;
187 lastIterationIndex_ = iterationIndex_;
188 lastSubIterationIndex_ = subIterationIndex_;
190 std::string currentState;
191 if(iterationIndex_ == 0 && subIterationIndex_ == 0)
194 theProgressBar_.reset(command, theStateMachine_.getStateMachineName());
195 currentState = theStateMachine_.getCurrentStateName();
196 __GEN_COUT__ <<
"Starting state for " << theStateMachine_.getStateMachineName() <<
" is " << currentState <<
" and attempting to " << command
201 currentState = theStateMachine_.getStateName(lastIterationState_);
203 __GEN_COUT__ <<
"Iteration index " << iterationIndex_ <<
"." << subIterationIndex_ <<
" for " << theStateMachine_.getStateMachineName() <<
" from "
204 << currentState <<
" attempting to " << command << std::endl;
207 RunControlStateMachine::theProgressBar_.step();
209 std::string result = command +
"Done";
210 lastIterationResult_ = result;
214 if(command ==
"Error" || command ==
"Fail")
216 __GEN_SS__ << command <<
" was received! Halting immediately." << std::endl;
217 __GEN_COUT_ERR__ <<
"\n" << ss.str();
221 if(currentState ==
"Configured")
222 theStateMachine_.execTransition(
"Halt", message);
223 else if(currentState ==
"Running" || currentState ==
"Paused")
224 theStateMachine_.execTransition(
"Abort", message);
228 __GEN_COUT_ERR__ <<
"Halting failed in reaction to " << command <<
"... ignoring." << __E__;
230 return SOAPUtilities::makeSOAPMessageReference(result);
232 else if(command ==
"AsyncError")
234 std::string errorMessage = SOAPUtilities::translate(message).getParameters().getValue(
"ErrorMessage");
236 __GEN_SS__ << command <<
" was received! Error'ing immediately: " << errorMessage << std::endl;
237 __GEN_COUT_ERR__ <<
"\n" << ss.str();
238 theStateMachine_.setErrorMessage(ss.str());
240 asyncFailureReceived_ =
true;
242 theStateMachine_.execTransition(
"fail");
245 return SOAPUtilities::makeSOAPMessageReference(result);
247 else if(command ==
"AsyncSoftError")
249 std::string errorMessage = SOAPUtilities::translate(message).getParameters().getValue(
"ErrorMessage");
251 __GEN_SS__ << command <<
" was received! Pause'ing immediately: " << errorMessage << std::endl;
252 __GEN_COUT_ERR__ <<
"\n" << ss.str();
253 theStateMachine_.setErrorMessage(ss.str());
255 if(!asyncSoftFailureReceived_)
257 asyncSoftFailureReceived_ =
true;
260 theStateMachine_.execTransition(
"Pause");
263 return SOAPUtilities::makeSOAPMessageReference(result);
268 if(command ==
"Initialize" && currentState == RunControlStateMachine::HALTED_STATE_NAME)
270 __GEN_COUT__ <<
"Already Initialized.. ignoring Initialize command." << std::endl;
272 theStateMachine_.setErrorMessage(
"",
false );
273 return SOAPUtilities::makeSOAPMessageReference(result);
276 __GEN_COUTV__(command);
277 __GEN_COUTV__(currentState);
279 if(command ==
"Halt" && currentState ==
"Initial")
281 __GEN_COUT__ <<
"Converting Halt command to Initialize, since currently in "
284 command =
"Initialize";
285 message = SOAPUtilities::makeSOAPMessageReference(command);
291 if(!(asyncSoftFailureReceived_ && command ==
"Pause"))
292 theStateMachine_.setErrorMessage(
"",
false );
294 iterationWorkFlag_ =
false;
295 subIterationWorkFlag_ =
false;
296 if(iterationIndex_ || subIterationIndex_)
298 __GEN_COUT__ << command <<
" iteration " << iterationIndex_ <<
"." << subIterationIndex_ << __E__;
299 toolbox::Event::Reference event(
new toolbox::Event(command,
this));
304 __GEN_COUT__ <<
"Iterating on the transition function from " << currentState <<
" through " << lastIterationCommand_ << __E__;
306 auto itFrom = stateTransitionFunctionTable_.find(lastIterationState_);
307 if(itFrom == stateTransitionFunctionTable_.end())
309 __GEN_SS__ <<
"Cannot find transition function from '" << currentState <<
"' with transition '" << lastIterationCommand_ <<
"!'" << __E__;
310 __GEN_COUT_ERR__ << ss.str();
311 XCEPT_RAISE(toolbox::fsm::exception::Exception, ss.str());
314 auto itTransition = itFrom->second.find(lastIterationCommand_);
315 if(itTransition == itFrom->second.end())
317 __GEN_SS__ <<
"Cannot find transition function from '" << currentState <<
"' with transition '" << lastIterationCommand_ <<
"!'" << __E__;
318 __GEN_COUT_ERR__ << ss.str();
319 XCEPT_RAISE(toolbox::fsm::exception::Exception, ss.str());
322 (this->*(itTransition->second))(event);
329 lastIterationState_ = theStateMachine_.getCurrentState();
330 lastIterationCommand_ = command;
332 theStateMachine_.execTransition(command, message);
335 if(subIterationWorkFlag_)
337 __GEN_COUTV__(subIterationWorkFlag_);
338 result = command +
"SubIterate";
340 else if(iterationWorkFlag_)
342 __GEN_COUTV__(iterationWorkFlag_);
343 result = command +
"Iterate";
346 catch(toolbox::fsm::exception::Exception& e)
348 __GEN_SS__ <<
"Run Control Message Handling Failed: " << e.what() <<
" " << theStateMachine_.getErrorMessage() << __E__;
349 __GEN_COUT_ERR__ << ss.str();
350 theStateMachine_.setErrorMessage(ss.str());
352 result = command +
" " + RunControlStateMachine::FAILED_STATE_NAME +
": " + theStateMachine_.getErrorMessage();
356 __GEN_SS__ <<
"Run Control Message Handling encountered an unknown error." << theStateMachine_.getErrorMessage() << __E__;
357 __GEN_COUT_ERR__ << ss.str();
358 theStateMachine_.setErrorMessage(ss.str());
360 result = command +
" " + RunControlStateMachine::FAILED_STATE_NAME +
": " + theStateMachine_.getErrorMessage();
363 RunControlStateMachine::theProgressBar_.step();
365 currentState = theStateMachine_.getCurrentStateName();
367 if(currentState == RunControlStateMachine::FAILED_STATE_NAME)
369 result = command +
" " + RunControlStateMachine::FAILED_STATE_NAME +
": " + theStateMachine_.getErrorMessage();
370 __GEN_COUT_ERR__ <<
"Unexpected Failure state for " << theStateMachine_.getStateMachineName() <<
" is " << currentState << std::endl;
371 __GEN_COUT_ERR__ <<
"Error message was as follows: " << theStateMachine_.getErrorMessage() << std::endl;
374 RunControlStateMachine::theProgressBar_.step();
376 if(!iterationWorkFlag_ && !subIterationWorkFlag_)
377 theProgressBar_.complete();
380 __GEN_COUTV__(theProgressBar_.read());
381 __GEN_COUTV__(theProgressBar_.isComplete());
384 __GEN_COUT__ <<
"Ending state for " << theStateMachine_.getStateMachineName() <<
" is " << currentState << std::endl;
385 __GEN_COUT__ <<
"result = " << result << std::endl;
386 lastIterationResult_ = result;
387 return SOAPUtilities::makeSOAPMessageReference(result);