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()
24 const std::string RunControlStateMachine::FAILED_STATE_NAME = FiniteStateMachine::FAILED_STATE_NAME;
25 const std::string RunControlStateMachine::INITIAL_STATE_NAME =
"Initial";
26 const std::string RunControlStateMachine::HALTED_STATE_NAME =
"Halted";
27 const std::string RunControlStateMachine::PAUSED_STATE_NAME =
"Paused";
28 const std::string RunControlStateMachine::RUNNING_STATE_NAME =
"Running";
29 const std::string RunControlStateMachine::SHUTDOWN_STATE_NAME =
"Shutdown";
30 const std::string RunControlStateMachine::CONFIGURED_STATE_NAME =
"Configured";
32 const std::string RunControlStateMachine::SHUTDOWN_TRANSITION_NAME =
"Shutdown";
33 const std::string RunControlStateMachine::STARTUP_TRANSITION_NAME =
"Startup";
34 const std::string RunControlStateMachine::INIT_TRANSITION_NAME =
"Initialize";
35 const std::string RunControlStateMachine::ERROR_TRANSITION_NAME = FiniteStateMachine::ERROR_TRANSITION_NAME;
36 const std::string RunControlStateMachine::FAIL_TRANSITION_NAME =
"Fail";
37 const std::string RunControlStateMachine::CONFIGURE_TRANSITION_NAME =
"Configure";
38 const std::string RunControlStateMachine::HALT_TRANSITION_NAME =
"Halt";
39 const std::string RunControlStateMachine::ABORT_TRANSITION_NAME =
"Abort";
40 const std::string RunControlStateMachine::PAUSE_TRANSITION_NAME =
"Pause";
41 const std::string RunControlStateMachine::RESUME_TRANSITION_NAME =
"Resume";
42 const std::string RunControlStateMachine::START_TRANSITION_NAME =
"Start";
43 const std::string RunControlStateMachine::STOP_TRANSITION_NAME =
"Stop";
48 RunControlStateMachine::RunControlStateMachine(
const std::string& name)
49 : theStateMachine_(name)
50 , asyncFailureReceived_(false)
51 , asyncPauseExceptionReceived_(false)
52 , asyncStopExceptionReceived_(false)
56 theStateMachine_.addState(
'I',
57 RunControlStateMachine::INITIAL_STATE_NAME,
59 &RunControlStateMachine::stateInitial);
60 theStateMachine_.addState(
'H',
61 RunControlStateMachine::HALTED_STATE_NAME,
63 &RunControlStateMachine::stateHalted);
64 theStateMachine_.addState(
'C',
65 RunControlStateMachine::CONFIGURED_STATE_NAME,
67 &RunControlStateMachine::stateConfigured);
68 theStateMachine_.addState(
'R',
69 RunControlStateMachine::RUNNING_STATE_NAME,
71 &RunControlStateMachine::stateRunning);
72 theStateMachine_.addState(
'P',
73 RunControlStateMachine::PAUSED_STATE_NAME,
75 &RunControlStateMachine::statePaused);
76 theStateMachine_.addState(
'X',
77 RunControlStateMachine::SHUTDOWN_STATE_NAME,
79 &RunControlStateMachine::stateShutdown);
88 theStateMachine_.setStateName(FiniteStateMachine::FAILED_STATE,
89 RunControlStateMachine::FAILED_STATE_NAME);
90 theStateMachine_.setFailedStateTransitionAction(
91 this, &RunControlStateMachine::enteringError);
92 theStateMachine_.setFailedStateTransitionChanged(
this,
93 &RunControlStateMachine::inError);
97 RunControlStateMachine::addStateTransition(
98 FiniteStateMachine::FAILED_STATE,
100 RunControlStateMachine::HALT_TRANSITION_NAME,
103 &RunControlStateMachine::transitionHalting);
104 RunControlStateMachine::addStateTransition(
105 FiniteStateMachine::FAILED_STATE,
107 RunControlStateMachine::SHUTDOWN_TRANSITION_NAME,
110 &RunControlStateMachine::transitionShuttingDown);
111 RunControlStateMachine::addStateTransition(
112 FiniteStateMachine::FAILED_STATE,
113 FiniteStateMachine::FAILED_STATE,
114 RunControlStateMachine::ERROR_TRANSITION_NAME,
117 &RunControlStateMachine::enteringError);
118 RunControlStateMachine::addStateTransition(
119 FiniteStateMachine::FAILED_STATE,
120 FiniteStateMachine::FAILED_STATE,
121 RunControlStateMachine::FAIL_TRANSITION_NAME,
124 &RunControlStateMachine::transitionShuttingDown);
126 RunControlStateMachine::addStateTransition(
129 RunControlStateMachine::CONFIGURE_TRANSITION_NAME,
131 "ConfigurationAlias",
133 &RunControlStateMachine::transitionConfiguring);
134 RunControlStateMachine::addStateTransition(
137 RunControlStateMachine::SHUTDOWN_TRANSITION_NAME,
140 &RunControlStateMachine::transitionShuttingDown);
141 RunControlStateMachine::addStateTransition(
144 RunControlStateMachine::STARTUP_TRANSITION_NAME,
147 &RunControlStateMachine::transitionStartingUp);
150 RunControlStateMachine::addStateTransition(
153 RunControlStateMachine::INIT_TRANSITION_NAME,
156 &RunControlStateMachine::transitionInitializing);
157 RunControlStateMachine::addStateTransition(
160 RunControlStateMachine::HALT_TRANSITION_NAME,
163 &RunControlStateMachine::transitionHalting);
164 RunControlStateMachine::addStateTransition(
167 RunControlStateMachine::HALT_TRANSITION_NAME,
170 &RunControlStateMachine::transitionHalting);
171 RunControlStateMachine::addStateTransition(
174 RunControlStateMachine::ABORT_TRANSITION_NAME,
177 &RunControlStateMachine::transitionHalting);
178 RunControlStateMachine::addStateTransition(
181 RunControlStateMachine::ABORT_TRANSITION_NAME,
184 &RunControlStateMachine::transitionHalting);
186 RunControlStateMachine::addStateTransition(
189 RunControlStateMachine::PAUSE_TRANSITION_NAME,
192 &RunControlStateMachine::transitionPausing);
193 RunControlStateMachine::addStateTransition(
196 RunControlStateMachine::RESUME_TRANSITION_NAME,
199 &RunControlStateMachine::transitionResuming);
200 RunControlStateMachine::addStateTransition(
203 RunControlStateMachine::START_TRANSITION_NAME,
206 &RunControlStateMachine::transitionStarting);
207 RunControlStateMachine::addStateTransition(
210 RunControlStateMachine::STOP_TRANSITION_NAME,
213 &RunControlStateMachine::transitionStopping);
214 RunControlStateMachine::addStateTransition(
217 RunControlStateMachine::STOP_TRANSITION_NAME,
220 &RunControlStateMachine::transitionStopping);
226 &RunControlStateMachine::runControlMessageHandler,
227 RunControlStateMachine::INIT_TRANSITION_NAME,
230 &RunControlStateMachine::runControlMessageHandler,
231 RunControlStateMachine::CONFIGURE_TRANSITION_NAME,
234 &RunControlStateMachine::runControlMessageHandler,
235 RunControlStateMachine::START_TRANSITION_NAME,
238 &RunControlStateMachine::runControlMessageHandler,
239 RunControlStateMachine::STOP_TRANSITION_NAME,
242 &RunControlStateMachine::runControlMessageHandler,
243 RunControlStateMachine::PAUSE_TRANSITION_NAME,
246 &RunControlStateMachine::runControlMessageHandler,
247 RunControlStateMachine::RESUME_TRANSITION_NAME,
250 &RunControlStateMachine::runControlMessageHandler,
251 RunControlStateMachine::HALT_TRANSITION_NAME,
254 &RunControlStateMachine::runControlMessageHandler,
255 RunControlStateMachine::ABORT_TRANSITION_NAME,
258 &RunControlStateMachine::runControlMessageHandler,
259 RunControlStateMachine::SHUTDOWN_TRANSITION_NAME,
262 &RunControlStateMachine::runControlMessageHandler,
263 RunControlStateMachine::STARTUP_TRANSITION_NAME,
266 &RunControlStateMachine::runControlMessageHandler,
267 RunControlStateMachine::FAIL_TRANSITION_NAME,
270 &RunControlStateMachine::runControlMessageHandler,
271 RunControlStateMachine::ERROR_TRANSITION_NAME,
275 &RunControlStateMachine::runControlMessageHandler,
279 &RunControlStateMachine::runControlMessageHandler,
280 "AsyncPauseException",
287 RunControlStateMachine::~RunControlStateMachine(
void) {}
290 void RunControlStateMachine::reset(
void)
292 __GEN_COUT__ <<
"Resetting RunControlStateMachine with name '"
293 << theStateMachine_.getStateMachineName() <<
"'..." << __E__;
294 theStateMachine_.setInitialState(
'I');
295 theStateMachine_.reset();
297 theStateMachine_.setErrorMessage(
"",
false );
299 asyncFailureReceived_ =
false;
300 asyncPauseExceptionReceived_ =
false;
301 asyncStopExceptionReceived_ =
false;
334 xoap::MessageReference message)
336 __GEN_COUT__ <<
"Received... \t" << SOAPUtilities::translate(message) << std::endl;
338 std::string command = SOAPUtilities::translate(message).getCommand();
344 SOAPUtilities::translate(message).getParameters().getValue(
"iterationIndex"),
349 __GEN_COUT__ <<
"Defaulting iteration index to 0." << __E__;
356 SOAPUtilities::translate(message).getParameters().getValue(
357 "subIterationIndex"),
362 __GEN_COUT__ <<
"Defaulting subIterationIndex_ index to 0." << __E__;
363 subIterationIndex_ = 0;
367 bool retransmittedCommand =
false;
370 retransmittedCommand =
371 (SOAPUtilities::translate(message).getParameters().getValue(
372 "retransmission") ==
"1");
380 if(retransmittedCommand)
385 if(lastIterationCommand_ == command && lastIterationIndex_ == iterationIndex_ &&
386 lastSubIterationIndex_ == subIterationIndex_)
389 <<
"Assuming a timeout occurred at Gateway waiting for a response. "
390 <<
"Attempting to avoid error, by giving last result for command '"
391 << command <<
"': " << lastIterationResult_ << __E__;
394 return SOAPUtilities::makeSOAPMessageReference(lastIterationResult_);
396 catch(
const std::exception&
399 __GEN_COUT__ <<
"There was an illegal result propagation: "
400 << lastIterationResult_
401 <<
". Here was the error: " << e.what() << __E__;
406 __GEN_COUT__ <<
"Looks like Gateway command '" << command
407 <<
"' was lost - attempting to handle retransmission." << __E__;
410 lastIterationIndex_ = iterationIndex_;
411 lastSubIterationIndex_ = subIterationIndex_;
413 std::string currentState;
414 if(iterationIndex_ == 0 && subIterationIndex_ == 0)
417 theProgressBar_.
reset(command, theStateMachine_.getStateMachineName());
418 currentState = theStateMachine_.getCurrentStateName();
419 __GEN_COUT__ <<
"Starting state for " << theStateMachine_.getStateMachineName()
420 <<
" is " << currentState <<
" and attempting to " << command
425 currentState = theStateMachine_.getStateName(lastIterationState_);
427 __GEN_COUT__ <<
"Iteration index " << iterationIndex_ <<
"." << subIterationIndex_
428 <<
" for " << theStateMachine_.getStateMachineName() <<
" from "
429 << currentState <<
" attempting to " << command << std::endl;
432 RunControlStateMachine::theProgressBar_.step();
434 std::string result = command +
"Done";
435 lastIterationResult_ = result;
439 if(command ==
"Error" || command ==
"Fail")
441 __GEN_SS__ << command <<
" was received! Halting immediately." << std::endl;
442 __GEN_COUT_ERR__ <<
"\n" << ss.str();
446 if(currentState ==
"Configured")
447 theStateMachine_.execTransition(
448 RunControlStateMachine::HALT_TRANSITION_NAME, message);
449 else if(currentState ==
"Running" || currentState ==
"Paused")
450 theStateMachine_.execTransition(
451 RunControlStateMachine::ABORT_TRANSITION_NAME, message);
455 __GEN_COUT_ERR__ <<
"Halting failed in reaction to " << command
456 <<
"... ignoring." << __E__;
458 return SOAPUtilities::makeSOAPMessageReference(result);
460 else if(command ==
"AsyncError")
462 std::string errorMessage =
463 SOAPUtilities::translate(message).getParameters().getValue(
"ErrorMessage");
465 __GEN_SS__ << command <<
" was received! Error'ing immediately: " << errorMessage
467 __GEN_COUT_ERR__ <<
"\n" << ss.str();
468 theStateMachine_.setErrorMessage(ss.str());
470 asyncFailureReceived_ =
true;
472 theStateMachine_.execTransition(
"fail");
475 return SOAPUtilities::makeSOAPMessageReference(result);
477 else if(command ==
"AsyncPauseException")
479 std::string errorMessage =
480 SOAPUtilities::translate(message).getParameters().getValue(
"ErrorMessage");
482 __GEN_SS__ << command <<
" was received! Pause'ing immediately: " << errorMessage
484 __GEN_COUT_ERR__ <<
"\n" << ss.str();
485 theStateMachine_.setErrorMessage(ss.str());
487 if(!asyncPauseExceptionReceived_)
489 asyncPauseExceptionReceived_ =
true;
492 theStateMachine_.execTransition(
"Pause");
495 return SOAPUtilities::makeSOAPMessageReference(result);
497 else if(command ==
"AsyncStopException")
499 std::string errorMessage =
500 SOAPUtilities::translate(message).getParameters().getValue(
"ErrorMessage");
502 __GEN_SS__ << command <<
" was received! Stop'ing immediately: " << errorMessage
504 __GEN_COUT_ERR__ <<
"\n" << ss.str();
505 theStateMachine_.setErrorMessage(ss.str());
507 if(!asyncStopExceptionReceived_)
509 asyncStopExceptionReceived_ =
true;
512 theStateMachine_.execTransition(
"Stop");
515 return SOAPUtilities::makeSOAPMessageReference(result);
520 if(command == RunControlStateMachine::INIT_TRANSITION_NAME &&
521 currentState == RunControlStateMachine::HALTED_STATE_NAME)
523 __GEN_COUT__ <<
"Already Initialized.. ignoring Initialize command." << std::endl;
525 theStateMachine_.setErrorMessage(
"",
false );
526 return SOAPUtilities::makeSOAPMessageReference(result);
529 if(command == RunControlStateMachine::INIT_TRANSITION_NAME &&
530 currentState == RunControlStateMachine::FAILED_STATE_NAME)
532 __GEN_COUT__ <<
"Converting Initialize command to Halt, since currently in "
533 << currentState <<
" state." << std::endl;
534 command = RunControlStateMachine::HALT_TRANSITION_NAME;
535 message = SOAPUtilities::makeSOAPMessageReference(command);
538 if(command == RunControlStateMachine::HALT_TRANSITION_NAME &&
539 currentState == RunControlStateMachine::FAILED_STATE_NAME)
541 __GEN_COUT__ <<
"Clearing Errors after failure..." << std::endl;
542 theStateMachine_.setErrorMessage(
"",
false );
543 asyncFailureReceived_ =
false;
546 __GEN_COUTV__(command);
547 __GEN_COUTV__(currentState);
548 __GEN_COUTV__(asyncFailureReceived_);
549 __GEN_COUTV__(asyncPauseExceptionReceived_);
550 __GEN_COUTV__(asyncStopExceptionReceived_);
551 __GEN_COUTV__(getErrorMessage());
552 __GEN_COUTV__(retransmittedCommand);
560 if(!((asyncPauseExceptionReceived_ &&
561 command == RunControlStateMachine::PAUSE_TRANSITION_NAME) ||
562 (asyncStopExceptionReceived_ &&
563 command == RunControlStateMachine::STOP_TRANSITION_NAME)))
564 theStateMachine_.setErrorMessage(
"",
567 if(command == RunControlStateMachine::HALT_TRANSITION_NAME &&
568 currentState == RunControlStateMachine::INITIAL_STATE_NAME)
570 command = RunControlStateMachine::INIT_TRANSITION_NAME;
571 __GEN_COUT__ <<
"Converting Halt command to " << command
572 <<
", since currently in " << currentState <<
" state."
574 message = SOAPUtilities::makeSOAPMessageReference(command);
576 if(command == RunControlStateMachine::HALT_TRANSITION_NAME &&
577 (currentState == RunControlStateMachine::PAUSED_STATE_NAME ||
578 currentState == RunControlStateMachine::RUNNING_STATE_NAME))
580 command = RunControlStateMachine::ABORT_TRANSITION_NAME;
581 __GEN_COUT__ <<
"Converting Halt command to " << command
582 <<
", since currently in " << currentState <<
" state."
584 message = SOAPUtilities::makeSOAPMessageReference(command);
586 if(command == RunControlStateMachine::CONFIGURE_TRANSITION_NAME &&
587 currentState == RunControlStateMachine::INITIAL_STATE_NAME)
590 <<
"Pre-empting Configure command with Initialize, since currently in "
591 << currentState <<
" state." << std::endl;
592 std::string precommand = RunControlStateMachine::INIT_TRANSITION_NAME;
593 xoap::MessageReference premessage =
594 SOAPUtilities::makeSOAPMessageReference(precommand);
595 theStateMachine_.execTransition(precommand, premessage);
596 __GEN_COUT__ <<
"Now proceeding with Configure command" << __E__;
599 iterationWorkFlag_ =
false;
600 subIterationWorkFlag_ =
false;
601 if(iterationIndex_ || subIterationIndex_)
603 __GEN_COUT__ << command <<
" iteration " << iterationIndex_ <<
"."
604 << subIterationIndex_ << __E__;
605 toolbox::Event::Reference event(
new toolbox::Event(command,
this));
610 __GEN_COUT__ <<
"Iterating on the transition function from "
611 << currentState <<
" through " << lastIterationCommand_
614 auto itFrom = stateTransitionFunctionTable_.find(lastIterationState_);
615 if(itFrom == stateTransitionFunctionTable_.end())
617 __GEN_SS__ <<
"Cannot find transition function from '" << currentState
618 <<
"' with transition '" << lastIterationCommand_ <<
"!'"
620 __GEN_COUT_ERR__ << ss.str();
621 XCEPT_RAISE(toolbox::fsm::exception::Exception, ss.str());
624 auto itTransition = itFrom->second.find(lastIterationCommand_);
625 if(itTransition == itFrom->second.end())
627 __GEN_SS__ <<
"Cannot find transition function from '" << currentState
628 <<
"' with transition '" << lastIterationCommand_ <<
"!'"
630 __GEN_COUT_ERR__ << ss.str();
631 XCEPT_RAISE(toolbox::fsm::exception::Exception, ss.str());
634 (this->*(itTransition->second))(event);
641 lastIterationState_ = theStateMachine_.getCurrentState();
642 lastIterationCommand_ = command;
643 if(command == RunControlStateMachine::CONFIGURE_TRANSITION_NAME)
645 lastAttemptedConfigureGroup_ =
646 SOAPUtilities::translate(message).getParameters().getValue(
647 "ConfigurationAlias");
652 lastAttemptedConfigureGroup_ +=
654 SOAPUtilities::translate(message).getParameters().getValue(
655 "ConfigurationTableGroupName") +
657 SOAPUtilities::translate(message).getParameters().getValue(
658 "ConfigurationTableGroupKey") +
666 theStateMachine_.execTransition(command, message);
669 if(subIterationWorkFlag_)
671 __GEN_COUTV__(subIterationWorkFlag_);
673 command +
"SubIterate";
675 else if(iterationWorkFlag_)
677 __GEN_COUTV__(iterationWorkFlag_);
678 result = command +
"Iterate";
681 catch(
const std::runtime_error& e)
683 __GEN_SS__ <<
"Run Control Message Handling Failed with command '" << command
684 <<
"': " << e.what() <<
" " << theStateMachine_.getErrorMessage()
686 __GEN_COUT_ERR__ << ss.str();
687 theStateMachine_.setErrorMessage(ss.str());
689 result = command + RunControlStateMachine::FAILED_STATE_NAME;
691 catch(toolbox::fsm::exception::Exception& e)
693 __GEN_SS__ <<
"Run Control Message Handling Failed with command '" << command
694 <<
"': " << e.what() <<
" " << theStateMachine_.getErrorMessage()
696 __GEN_COUT_ERR__ << ss.str();
697 theStateMachine_.setErrorMessage(ss.str());
699 result = command + RunControlStateMachine::FAILED_STATE_NAME;
703 __GEN_SS__ <<
"Run Control Message Handling Failed with command '" << command
704 <<
"' and encountered an unknown error."
705 << theStateMachine_.getErrorMessage() << __E__;
710 catch(
const std::exception& e)
712 ss <<
"Exception message: " << e.what();
717 __GEN_COUT_ERR__ << ss.str();
718 theStateMachine_.setErrorMessage(ss.str());
720 result = command + RunControlStateMachine::FAILED_STATE_NAME;
723 RunControlStateMachine::theProgressBar_.step();
725 currentState = theStateMachine_.getCurrentStateName();
727 if(currentState == RunControlStateMachine::FAILED_STATE_NAME)
729 result = command + RunControlStateMachine::FAILED_STATE_NAME;
730 __GEN_COUT_ERR__ <<
"Unexpected Failure state for "
731 << theStateMachine_.getStateMachineName() <<
" is "
732 << currentState << std::endl;
733 __GEN_COUT_ERR__ <<
"Error message was as follows: "
734 << theStateMachine_.getErrorMessage() << std::endl;
737 RunControlStateMachine::theProgressBar_.step();
739 if(!iterationWorkFlag_ && !subIterationWorkFlag_)
743 __GEN_COUTV__(theProgressBar_.
read());
747 __GEN_COUT__ <<
"Ending state for " << theStateMachine_.getStateMachineName()
748 <<
" is " << currentState << std::endl;
749 __GEN_COUT__ <<
"result = " << result << std::endl;
750 lastIterationResult_ = result;
751 return SOAPUtilities::makeSOAPMessageReference(result);
bool isComplete()
get functions
void reset(std::string file, std::string lineNumber, int id=0)
will call this reset:
int read()
if stepsToComplete==0, then define any progress as 50%, thread safe
void complete()
declare complete, thread safe
xoap::MessageReference runControlMessageHandler(xoap::MessageReference message)
Run Control Messages.
void INIT_MF(const char *name)
static bool getNumber(const std::string &s, T &retValue)