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>
18 #define __MF_SUBJECT__ "FSM"
19 #define mfSubject_ std::string("FSM-") + theStateMachine_.getStateMachineName()
25 const std::string RunControlStateMachine::FAILED_STATE_NAME = FiniteStateMachine::FAILED_STATE_NAME;
26 const std::string RunControlStateMachine::INITIAL_STATE_NAME = FiniteStateMachine::INITIAL_STATE_NAME ;
27 const std::string RunControlStateMachine::HALTED_STATE_NAME =
"Halted";
28 const std::string RunControlStateMachine::PAUSED_STATE_NAME =
"Paused";
29 const std::string RunControlStateMachine::RUNNING_STATE_NAME =
"Running";
30 const std::string RunControlStateMachine::SHUTDOWN_STATE_NAME =
"Shutdown";
31 const std::string RunControlStateMachine::CONFIGURED_STATE_NAME =
"Configured";
33 const std::string RunControlStateMachine::SHUTDOWN_TRANSITION_NAME =
"Shutdown";
34 const std::string RunControlStateMachine::STARTUP_TRANSITION_NAME =
"Startup";
35 const std::string RunControlStateMachine::INIT_TRANSITION_NAME =
"Initialize";
36 const std::string RunControlStateMachine::ERROR_TRANSITION_NAME = FiniteStateMachine::ERROR_TRANSITION_NAME;
37 const std::string RunControlStateMachine::FAIL_TRANSITION_NAME =
"Fail";
38 const std::string RunControlStateMachine::CONFIGURE_TRANSITION_NAME = FiniteStateMachine::CONFIGURE_TRANSITION_NAME;
39 const std::string RunControlStateMachine::HALT_TRANSITION_NAME =
"Halt";
40 const std::string RunControlStateMachine::ABORT_TRANSITION_NAME =
"Abort";
41 const std::string RunControlStateMachine::PAUSE_TRANSITION_NAME =
"Pause";
42 const std::string RunControlStateMachine::RESUME_TRANSITION_NAME =
"Resume";
43 const std::string RunControlStateMachine::START_TRANSITION_NAME =
"Start";
44 const std::string RunControlStateMachine::STOP_TRANSITION_NAME =
"Stop";
49 RunControlStateMachine::RunControlStateMachine(
const std::string& name)
50 : theStateMachine_(name)
54 theStateMachine_.addState(
'I',
55 RunControlStateMachine::INITIAL_STATE_NAME,
57 &RunControlStateMachine::stateInitial);
58 theStateMachine_.addState(
'H',
59 RunControlStateMachine::HALTED_STATE_NAME,
61 &RunControlStateMachine::stateHalted);
62 theStateMachine_.addState(
'C',
63 RunControlStateMachine::CONFIGURED_STATE_NAME,
65 &RunControlStateMachine::stateConfigured);
66 theStateMachine_.addState(
'R',
67 RunControlStateMachine::RUNNING_STATE_NAME,
69 &RunControlStateMachine::stateRunning);
70 theStateMachine_.addState(
'P',
71 RunControlStateMachine::PAUSED_STATE_NAME,
73 &RunControlStateMachine::statePaused);
74 theStateMachine_.addState(
'X',
75 RunControlStateMachine::SHUTDOWN_STATE_NAME,
77 &RunControlStateMachine::stateShutdown);
86 theStateMachine_.setStateName(FiniteStateMachine::FAILED_STATE,
87 RunControlStateMachine::FAILED_STATE_NAME);
88 theStateMachine_.setFailedStateTransitionAction(
89 this, &RunControlStateMachine::enteringError);
90 theStateMachine_.setFailedStateTransitionChanged(
this,
91 &RunControlStateMachine::inError);
95 RunControlStateMachine::addStateTransition(
96 FiniteStateMachine::FAILED_STATE,
98 RunControlStateMachine::HALT_TRANSITION_NAME,
101 &RunControlStateMachine::transitionHalting);
102 RunControlStateMachine::addStateTransition(
103 FiniteStateMachine::FAILED_STATE,
105 RunControlStateMachine::SHUTDOWN_TRANSITION_NAME,
108 &RunControlStateMachine::transitionShuttingDown);
109 RunControlStateMachine::addStateTransition(
110 FiniteStateMachine::FAILED_STATE,
111 FiniteStateMachine::FAILED_STATE,
112 RunControlStateMachine::ERROR_TRANSITION_NAME,
115 &RunControlStateMachine::enteringError);
116 RunControlStateMachine::addStateTransition(
117 FiniteStateMachine::FAILED_STATE,
118 FiniteStateMachine::FAILED_STATE,
119 RunControlStateMachine::FAIL_TRANSITION_NAME,
122 &RunControlStateMachine::transitionShuttingDown);
124 RunControlStateMachine::addStateTransition(
127 RunControlStateMachine::CONFIGURE_TRANSITION_NAME,
129 "ConfigurationAlias",
131 &RunControlStateMachine::transitionConfiguring);
132 RunControlStateMachine::addStateTransition(
135 RunControlStateMachine::SHUTDOWN_TRANSITION_NAME,
138 &RunControlStateMachine::transitionShuttingDown);
139 RunControlStateMachine::addStateTransition(
142 RunControlStateMachine::STARTUP_TRANSITION_NAME,
145 &RunControlStateMachine::transitionStartingUp);
148 RunControlStateMachine::addStateTransition(
151 RunControlStateMachine::INIT_TRANSITION_NAME,
154 &RunControlStateMachine::transitionInitializing);
155 RunControlStateMachine::addStateTransition(
158 RunControlStateMachine::HALT_TRANSITION_NAME,
161 &RunControlStateMachine::transitionHalting);
162 RunControlStateMachine::addStateTransition(
165 RunControlStateMachine::HALT_TRANSITION_NAME,
168 &RunControlStateMachine::transitionHalting);
169 RunControlStateMachine::addStateTransition(
172 RunControlStateMachine::ABORT_TRANSITION_NAME,
175 &RunControlStateMachine::transitionHalting);
176 RunControlStateMachine::addStateTransition(
179 RunControlStateMachine::ABORT_TRANSITION_NAME,
182 &RunControlStateMachine::transitionHalting);
184 RunControlStateMachine::addStateTransition(
187 RunControlStateMachine::PAUSE_TRANSITION_NAME,
190 &RunControlStateMachine::transitionPausing);
191 RunControlStateMachine::addStateTransition(
194 RunControlStateMachine::RESUME_TRANSITION_NAME,
197 &RunControlStateMachine::transitionResuming);
198 RunControlStateMachine::addStateTransition(
201 RunControlStateMachine::START_TRANSITION_NAME,
204 &RunControlStateMachine::transitionStarting);
205 RunControlStateMachine::addStateTransition(
208 RunControlStateMachine::STOP_TRANSITION_NAME,
211 &RunControlStateMachine::transitionStopping);
212 RunControlStateMachine::addStateTransition(
215 RunControlStateMachine::STOP_TRANSITION_NAME,
218 &RunControlStateMachine::transitionStopping);
224 &RunControlStateMachine::runControlMessageHandler,
225 RunControlStateMachine::INIT_TRANSITION_NAME,
228 &RunControlStateMachine::runControlMessageHandler,
229 RunControlStateMachine::CONFIGURE_TRANSITION_NAME,
232 &RunControlStateMachine::runControlMessageHandler,
233 RunControlStateMachine::START_TRANSITION_NAME,
236 &RunControlStateMachine::runControlMessageHandler,
237 RunControlStateMachine::STOP_TRANSITION_NAME,
240 &RunControlStateMachine::runControlMessageHandler,
241 RunControlStateMachine::PAUSE_TRANSITION_NAME,
244 &RunControlStateMachine::runControlMessageHandler,
245 RunControlStateMachine::RESUME_TRANSITION_NAME,
248 &RunControlStateMachine::runControlMessageHandler,
249 RunControlStateMachine::HALT_TRANSITION_NAME,
252 &RunControlStateMachine::runControlMessageHandler,
253 RunControlStateMachine::ABORT_TRANSITION_NAME,
256 &RunControlStateMachine::runControlMessageHandler,
257 RunControlStateMachine::SHUTDOWN_TRANSITION_NAME,
260 &RunControlStateMachine::runControlMessageHandler,
261 RunControlStateMachine::STARTUP_TRANSITION_NAME,
264 &RunControlStateMachine::runControlMessageHandler,
265 RunControlStateMachine::FAIL_TRANSITION_NAME,
268 &RunControlStateMachine::runControlMessageHandler,
269 RunControlStateMachine::ERROR_TRANSITION_NAME,
273 &RunControlStateMachine::runControlMessageHandler,
277 &RunControlStateMachine::runControlMessageHandler,
278 "AsyncPauseException",
285 RunControlStateMachine::~RunControlStateMachine(
void) {}
288 void RunControlStateMachine::reset(
void)
290 __GEN_COUT__ <<
"Resetting RunControlStateMachine with name '"
291 << theStateMachine_.getStateMachineName() <<
"'..." << __E__;
292 theStateMachine_.setInitialState(
'I');
293 theStateMachine_.reset();
295 theStateMachine_.setErrorMessage(
"",
false );
297 asyncFailureReceived_ =
false;
298 asyncPauseExceptionReceived_ =
false;
299 asyncStopExceptionReceived_ =
false;
332 xoap::MessageReference message)
334 __GEN_COUTS__(2) <<
"Received... \t" << SOAPUtilities::translate(message)
337 std::string command = SOAPUtilities::translate(message).getCommand();
343 SOAPUtilities::translate(message).getParameters().getValue(
"iterationIndex"),
348 __GEN_COUT__ <<
"Defaulting iteration index to 0." << __E__;
355 SOAPUtilities::translate(message).getParameters().getValue(
356 "subIterationIndex"),
361 __GEN_COUTT__ <<
"Defaulting subIterationIndex_ index to 0." << __E__;
362 subIterationIndex_ = 0;
369 SOAPUtilities::translate(message).getParameters().getValue(
370 "MinReadyForEventGenerationStartIteration"),
371 minReadyForEventGenerationStartIteration_);
375 minReadyForEventGenerationStartIteration_ = 0;
379 bool retransmittedCommand =
false;
382 retransmittedCommand =
383 (SOAPUtilities::translate(message).getParameters().getValue(
384 "retransmission") ==
"1");
392 if(retransmittedCommand)
395 __GEN_COUT__ <<
"retransmission identified..." << __E__;
398 if(lastIterationCommand_ == command && lastIterationIndex_ == iterationIndex_ &&
399 lastSubIterationIndex_ == subIterationIndex_)
402 <<
"Assuming a timeout occurred at Gateway waiting for a response. "
403 <<
"Attempting to avoid error, by giving last result for command '"
404 << command <<
"': " << lastIterationResult_ << __E__;
407 return SOAPUtilities::makeSOAPMessageReference(lastIterationResult_);
409 catch(
const std::exception&
412 __GEN_COUT__ <<
"There was an illegal result propagation: "
413 << lastIterationResult_
414 <<
". Here was the error: " << e.what() << __E__;
419 __GEN_COUT__ <<
"Looks like Gateway command '" << command
420 <<
"' was lost - attempting to handle retransmission." << __E__;
423 lastIterationIndex_ = iterationIndex_;
424 lastSubIterationIndex_ = subIterationIndex_;
426 std::string currentState;
427 if(iterationIndex_ == 0 && subIterationIndex_ == 0)
430 theProgressBar_.
reset(command, theStateMachine_.getStateMachineName());
431 currentState = theStateMachine_.getCurrentStateName();
432 __GEN_COUT__ <<
"Starting state for " << theStateMachine_.getStateMachineName()
433 <<
" is " << currentState <<
" and attempting to " << command
438 currentState = theStateMachine_.getStateName(lastIterationState_);
440 __GEN_COUTS__(2) <<
"Iteration index " << iterationIndex_ <<
"."
441 << subIterationIndex_ <<
" for "
442 << theStateMachine_.getStateMachineName() <<
" from "
443 << currentState <<
" attempting to " << command << std::endl;
446 RunControlStateMachine::theProgressBar_.step();
448 std::string result = command +
"Done";
449 lastIterationResult_ = result;
453 if(command ==
"Error" || command ==
"Fail")
455 __GEN_SS__ << command <<
" was received! Halting immediately." << std::endl;
456 __GEN_COUT_ERR__ <<
"\n" << ss.str();
460 if(currentState ==
"Configured")
461 theStateMachine_.execTransition(
462 RunControlStateMachine::HALT_TRANSITION_NAME, message);
463 else if(currentState ==
"Running" || currentState ==
"Paused")
464 theStateMachine_.execTransition(
465 RunControlStateMachine::ABORT_TRANSITION_NAME, message);
469 __GEN_COUT_ERR__ <<
"Halting failed in reaction to " << command
470 <<
"... ignoring." << __E__;
473 return SOAPUtilities::makeSOAPMessageReference(result);
475 else if(command ==
"AsyncError")
477 std::string errorMessage =
478 SOAPUtilities::translate(message).getParameters().getValue(
"ErrorMessage");
480 __GEN_SS__ << command <<
" was received! Error'ing immediately: " << errorMessage
482 __GEN_COUT_ERR__ <<
"\n" << ss.str();
483 theStateMachine_.setErrorMessage(ss.str());
485 if(!asyncFailureReceived_.exchange(
true))
491 std::thread([
this]() {
494 theStateMachine_.execTransition(
"fail");
498 __GEN_COUT_ERR__ <<
"AsyncError: execTransition(fail) threw" << __E__;
503 return SOAPUtilities::makeSOAPMessageReference(result);
505 else if(command ==
"AsyncPauseException")
507 std::string errorMessage =
508 SOAPUtilities::translate(message).getParameters().getValue(
"ErrorMessage");
510 __GEN_SS__ << command <<
" was received! Pause'ing immediately: " << errorMessage
512 __GEN_COUT_ERR__ <<
"\n" << ss.str();
513 theStateMachine_.setErrorMessage(ss.str());
515 if(!asyncPauseExceptionReceived_.exchange(
true))
519 std::thread([
this]() {
522 theStateMachine_.execTransition(
"Pause");
526 __GEN_COUT_ERR__ <<
"AsyncPauseException: execTransition(Pause) threw"
532 return SOAPUtilities::makeSOAPMessageReference(result);
534 else if(command ==
"AsyncStopException")
536 std::string errorMessage =
537 SOAPUtilities::translate(message).getParameters().getValue(
"ErrorMessage");
539 __GEN_SS__ << command <<
" was received! Stop'ing immediately: " << errorMessage
541 __GEN_COUT_ERR__ <<
"\n" << ss.str();
542 theStateMachine_.setErrorMessage(ss.str());
544 if(!asyncStopExceptionReceived_.exchange(
true))
548 std::thread([
this]() {
551 theStateMachine_.execTransition(
"Stop");
555 __GEN_COUT_ERR__ <<
"AsyncStopException: execTransition(Stop) threw"
561 return SOAPUtilities::makeSOAPMessageReference(result);
566 if(command == RunControlStateMachine::INIT_TRANSITION_NAME &&
567 currentState == RunControlStateMachine::HALTED_STATE_NAME)
569 __GEN_COUT__ <<
"Already Initialized.. ignoring Initialize command." << std::endl;
571 theStateMachine_.setErrorMessage(
"",
false );
572 return SOAPUtilities::makeSOAPMessageReference(result);
575 if(command == RunControlStateMachine::INIT_TRANSITION_NAME &&
576 currentState == RunControlStateMachine::FAILED_STATE_NAME)
578 __GEN_COUT__ <<
"Converting Initialize command to Halt, since currently in "
579 << currentState <<
" state." << std::endl;
580 command = RunControlStateMachine::HALT_TRANSITION_NAME;
581 message = SOAPUtilities::makeSOAPMessageReference(command);
584 if((command == RunControlStateMachine::HALT_TRANSITION_NAME ||
585 command == RunControlStateMachine::SHUTDOWN_TRANSITION_NAME) &&
586 currentState == RunControlStateMachine::FAILED_STATE_NAME)
588 __GEN_COUT__ <<
"Clearing Errors after failure..." << std::endl;
589 theStateMachine_.setErrorMessage(
"",
false );
590 asyncFailureReceived_ =
false;
591 asyncPauseExceptionReceived_ =
false;
592 asyncStopExceptionReceived_ =
false;
595 if(command == RunControlStateMachine::RESUME_TRANSITION_NAME)
596 asyncPauseExceptionReceived_ =
false;
597 if(command == RunControlStateMachine::START_TRANSITION_NAME)
598 asyncStopExceptionReceived_ =
false;
600 __GEN_COUTVS__(2, command);
601 __GEN_COUTVS__(2, currentState);
602 __GEN_COUTVS__(2, asyncFailureReceived_);
603 __GEN_COUTVS__(2, asyncPauseExceptionReceived_);
604 __GEN_COUTVS__(2, asyncStopExceptionReceived_);
605 __GEN_COUTVS__(2, getErrorMessage());
606 __GEN_COUTVS__(2, retransmittedCommand);
614 if(!((asyncPauseExceptionReceived_ &&
615 command == RunControlStateMachine::PAUSE_TRANSITION_NAME) ||
616 (asyncStopExceptionReceived_ &&
617 command == RunControlStateMachine::STOP_TRANSITION_NAME)))
618 theStateMachine_.setErrorMessage(
"",
621 if(command == RunControlStateMachine::HALT_TRANSITION_NAME &&
622 currentState == RunControlStateMachine::INITIAL_STATE_NAME)
624 command = RunControlStateMachine::INIT_TRANSITION_NAME;
625 __GEN_COUT__ <<
"Converting Halt command to " << command
626 <<
", since currently in " << currentState <<
" state."
628 message = SOAPUtilities::makeSOAPMessageReference(command);
630 if(command == RunControlStateMachine::HALT_TRANSITION_NAME &&
631 (currentState == RunControlStateMachine::PAUSED_STATE_NAME ||
632 currentState == RunControlStateMachine::RUNNING_STATE_NAME))
634 command = RunControlStateMachine::ABORT_TRANSITION_NAME;
635 __GEN_COUT__ <<
"Converting Halt command to " << command
636 <<
", since currently in " << currentState <<
" state."
638 message = SOAPUtilities::makeSOAPMessageReference(command);
640 if(command == RunControlStateMachine::CONFIGURE_TRANSITION_NAME &&
641 currentState == RunControlStateMachine::INITIAL_STATE_NAME)
644 <<
"Pre-empting Configure command with Initialize, since currently in "
645 << currentState <<
" state." << std::endl;
646 std::string precommand = RunControlStateMachine::INIT_TRANSITION_NAME;
647 xoap::MessageReference premessage =
648 SOAPUtilities::makeSOAPMessageReference(precommand);
649 theStateMachine_.execTransition(precommand, premessage);
650 __GEN_COUT__ <<
"Now proceeding with Configure command" << __E__;
653 iterationWorkFlag_ =
false;
654 subIterationWorkFlag_ =
false;
655 if(iterationIndex_ || subIterationIndex_)
657 __GEN_COUTS__(2) << command <<
" iteration " << iterationIndex_ <<
"."
658 << subIterationIndex_ << __E__;
659 toolbox::Event::Reference event(
new toolbox::Event(command,
this));
665 <<
"Iterating on the transition function from " << currentState
666 <<
" through " << lastIterationCommand_ << __E__;
668 auto itFrom = stateTransitionFunctionTable_.find(lastIterationState_);
669 if(itFrom == stateTransitionFunctionTable_.end())
671 __GEN_SS__ <<
"Cannot find transition function from '" << currentState
672 <<
"' with transition '" << lastIterationCommand_ <<
"!'"
674 __GEN_COUT_ERR__ << ss.str();
675 XCEPT_RAISE(toolbox::fsm::exception::Exception, ss.str());
678 auto itTransition = itFrom->second.find(lastIterationCommand_);
679 if(itTransition == itFrom->second.end())
681 __GEN_SS__ <<
"Cannot find transition function from '" << currentState
682 <<
"' with transition '" << lastIterationCommand_ <<
"!'"
684 __GEN_COUT_ERR__ << ss.str();
685 XCEPT_RAISE(toolbox::fsm::exception::Exception, ss.str());
688 (this->*(itTransition->second))(event);
695 lastIterationState_ = theStateMachine_.getCurrentState();
696 lastIterationCommand_ = command;
697 if(command == RunControlStateMachine::CONFIGURE_TRANSITION_NAME)
699 lastAttemptedConfigureGroup_ =
700 SOAPUtilities::translate(message).getParameters().getValue(
701 "ConfigurationAlias");
706 lastAttemptedConfigureGroup_ +=
708 SOAPUtilities::translate(message).getParameters().getValue(
709 "ConfigurationTableGroupName") +
711 SOAPUtilities::translate(message).getParameters().getValue(
712 "ConfigurationTableGroupKey") +
720 theStateMachine_.execTransition(command, message);
723 if(subIterationWorkFlag_)
725 __GEN_COUTV__(subIterationWorkFlag_);
727 command +
"SubIterate";
729 else if(iterationWorkFlag_)
731 __GEN_COUTVS__(2, iterationWorkFlag_);
732 result = command +
"Iterate";
735 catch(
const std::runtime_error& e)
737 __GEN_SS__ <<
"Run Control Message Handling Failed with command '" << command
738 <<
"': " << e.what() <<
" " << theStateMachine_.getErrorMessage()
740 __GEN_COUT_ERR__ << ss.str();
741 theStateMachine_.setErrorMessage(ss.str());
743 result = command + RunControlStateMachine::FAILED_STATE_NAME;
745 catch(toolbox::fsm::exception::Exception& e)
747 __GEN_SS__ <<
"Run Control Message Handling Failed with command '" << command
748 <<
"': " << e.what() <<
" " << theStateMachine_.getErrorMessage()
750 __GEN_COUT_ERR__ << ss.str();
751 theStateMachine_.setErrorMessage(ss.str());
753 result = command + RunControlStateMachine::FAILED_STATE_NAME;
757 __GEN_SS__ <<
"Run Control Message Handling Failed with command '" << command
758 <<
"' and encountered an unknown error."
759 << theStateMachine_.getErrorMessage() << __E__;
764 catch(
const std::exception& e)
766 ss <<
"Exception message: " << e.what();
771 __GEN_COUT_ERR__ << ss.str();
772 theStateMachine_.setErrorMessage(ss.str());
774 result = command + RunControlStateMachine::FAILED_STATE_NAME;
777 RunControlStateMachine::theProgressBar_.step();
779 currentState = theStateMachine_.getCurrentStateName();
781 if(currentState == RunControlStateMachine::FAILED_STATE_NAME)
783 result = command + RunControlStateMachine::FAILED_STATE_NAME;
784 __GEN_COUT_ERR__ <<
"Unexpected Failure state for "
785 << theStateMachine_.getStateMachineName() <<
" is "
786 << currentState << std::endl;
787 __GEN_COUT_ERR__ <<
"Error message was as follows: "
788 << theStateMachine_.getErrorMessage() << std::endl;
791 RunControlStateMachine::theProgressBar_.step();
793 if(!iterationWorkFlag_ && !subIterationWorkFlag_)
797 __GEN_COUTVS__(2, theProgressBar_.
read());
798 __GEN_COUTVS__(2, theProgressBar_.
isComplete());
801 __GEN_COUTS__(2) <<
"Ending state for " << theStateMachine_.getStateMachineName()
802 <<
" is " << currentState << std::endl;
803 __GEN_COUTS__(2) <<
"result = " << result << std::endl;
804 lastIterationResult_ = result;
805 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.
defines used also by OtsConfigurationWizardSupervisor
void INIT_MF(const char *name)
static bool getNumber(const std::string &s, T &retValue)