otsdaq  v2_00_00
RunControlStateMachine.cc
1 #include "otsdaq-core/FiniteStateMachine/RunControlStateMachine.h"
2 #include "otsdaq-core/MessageFacility/MessageFacility.h"
3 #include "otsdaq-core/Macros/CoutHeaderMacros.h"
4 #include "otsdaq-core/SOAPUtilities/SOAPUtilities.h"
5 #include "otsdaq-core/SOAPUtilities/SOAPCommand.h"
6 
7 #include <toolbox/fsm/FailedEvent.h>
8 #include <xoap/Method.h>
9 #include <xdaq/NamespaceURI.h>
10 
11 #include <iostream>
12 
13 using namespace ots;
14 
15 const std::string RunControlStateMachine::FAILED_STATE_NAME = "Failed";
16 
17 //========================================================================================================================
18 RunControlStateMachine::RunControlStateMachine(std::string name)
19 : stateMachineName_(name)
20 {
21  INIT_MF("RunControlStateMachine");
22 
23  theStateMachine_.addState('I', "Initial", this, &RunControlStateMachine::stateInitial);
24  theStateMachine_.addState('H', "Halted", this, &RunControlStateMachine::stateHalted);
25  theStateMachine_.addState('C', "Configured", this, &RunControlStateMachine::stateConfigured);
26  theStateMachine_.addState('R', "Running", this, &RunControlStateMachine::stateRunning);
27  theStateMachine_.addState('P', "Paused", this, &RunControlStateMachine::statePaused);
28  theStateMachine_.addState('X', "Shutdown", this, &RunControlStateMachine::stateShutdown);
29  //theStateMachine_.addState('v', "Recovering", this, &RunControlStateMachine::stateRecovering);
30  //theStateMachine_.addState('T', "TTSTestMode", this, &RunControlStateMachine::stateTTSTestMode);
31 
32  //RAR added back in on 11/20/2016.. why was it removed..
33  //exceptions like..
34  // XCEPT_RAISE (toolbox::fsm::exception::Exception, ss.str());)
35  // take state machine to "failed" otherwise
36  theStateMachine_.setStateName('F',RunControlStateMachine::FAILED_STATE_NAME);//x
37  theStateMachine_.setFailedStateTransitionAction (this, &RunControlStateMachine::enteringError);
38  theStateMachine_.setFailedStateTransitionChanged(this, &RunControlStateMachine::inError);
39 
40  //this line was added to get out of Failed state
41  theStateMachine_.addStateTransition('F', 'H', "Halt" , "Halting" , this, &RunControlStateMachine::transitionHalting);
42  //this attempt to get out of fail state makes things crash FIXME
43  //end RAR added back in on 11/20/2016.. why was it removed..
44 
45  theStateMachine_.addStateTransition('H', 'C', "Configure" , "Configuring" , "ConfigurationAlias", this, &RunControlStateMachine::transitionConfiguring);
46  theStateMachine_.addStateTransition('H', 'X', "Shutdown" , "Shutting Down", this, &RunControlStateMachine::transitionShuttingDown);
47  theStateMachine_.addStateTransition('X', 'I', "Startup" , "Starting Up" , this, &RunControlStateMachine::transitionStartingUp);
48 
49  //Every state can transition to halted
50  theStateMachine_.addStateTransition('I', 'H', "Initialize", "Initializing" , this, &RunControlStateMachine::transitionInitializing);
51  theStateMachine_.addStateTransition('H', 'H', "Halt" , "Halting" , this, &RunControlStateMachine::transitionHalting);
52  theStateMachine_.addStateTransition('C', 'H', "Halt" , "Halting" , this, &RunControlStateMachine::transitionHalting);
53  theStateMachine_.addStateTransition('R', 'H', "Abort" , "Aborting" , this, &RunControlStateMachine::transitionHalting);
54  theStateMachine_.addStateTransition('P', 'H', "Abort" , "Aborting" , this, &RunControlStateMachine::transitionHalting);
55 
56  theStateMachine_.addStateTransition('R', 'P', "Pause" , "Pausing" , this, &RunControlStateMachine::transitionPausing);
57  theStateMachine_.addStateTransition('P', 'R', "Resume" , "Resuming" , this, &RunControlStateMachine::transitionResuming);
58  theStateMachine_.addStateTransition('C', 'R', "Start" , "Starting" , this, &RunControlStateMachine::transitionStarting);
59  theStateMachine_.addStateTransition('R', 'C', "Stop" , "Stopping" , this, &RunControlStateMachine::transitionStopping);
60  theStateMachine_.addStateTransition('P', 'C', "Stop" , "Stopping" , this, &RunControlStateMachine::transitionStopping);
61 
62 
63  // NOTE!! There must be a defined message handler for each transition name created above
64  xoap::bind(this, &RunControlStateMachine::runControlMessageHandler, "Initialize", XDAQ_NS_URI);
65  xoap::bind(this, &RunControlStateMachine::runControlMessageHandler, "Configure" , XDAQ_NS_URI);
66  xoap::bind(this, &RunControlStateMachine::runControlMessageHandler, "Start" , XDAQ_NS_URI);
67  xoap::bind(this, &RunControlStateMachine::runControlMessageHandler, "Stop" , XDAQ_NS_URI);
68  xoap::bind(this, &RunControlStateMachine::runControlMessageHandler, "Pause" , XDAQ_NS_URI);
69  xoap::bind(this, &RunControlStateMachine::runControlMessageHandler, "Resume" , XDAQ_NS_URI);
70  xoap::bind(this, &RunControlStateMachine::runControlMessageHandler, "Halt" , XDAQ_NS_URI);
71  xoap::bind(this, &RunControlStateMachine::runControlMessageHandler, "Abort" , XDAQ_NS_URI);
72  xoap::bind(this, &RunControlStateMachine::runControlMessageHandler, "Shutdown" , XDAQ_NS_URI);
73  xoap::bind(this, &RunControlStateMachine::runControlMessageHandler, "Startup" , XDAQ_NS_URI);
74  xoap::bind(this, &RunControlStateMachine::runControlMessageHandler, "Fail" , XDAQ_NS_URI);
75  xoap::bind(this, &RunControlStateMachine::runControlMessageHandler, "Error" , XDAQ_NS_URI);
76 
77 
78  reset();
79 }
80 
81 //========================================================================================================================
82 RunControlStateMachine::~RunControlStateMachine(void)
83 {
84 }
85 
86 //========================================================================================================================
87 void RunControlStateMachine::reset(void)
88 {
89  __COUT__ << "Resetting RunControlStateMachine with name '" << stateMachineName_ << "'..." << __E__;
90  theStateMachine_.setInitialState('I');
91  theStateMachine_.reset();
92 }
93 
94 //========================================================================================================================
95 xoap::MessageReference RunControlStateMachine::runControlMessageHandler(
96  xoap::MessageReference message)
97 throw (xoap::exception::Exception)
98 {
99  __COUT__ << "Starting state for " << stateMachineName_ << " is " <<
100  theStateMachine_.getCurrentStateName() << std::endl;
101  __COUT__ << SOAPUtilities::translate(message) << std::endl;
102 
103  theStateMachine_.setErrorMessage(""); //clear error message
104 
105  std::string command = SOAPUtilities::translate(message).getCommand();
106  //__COUT__ << "Command:-" << command << "-" << std::endl;
107  theProgressBar_.reset(command,stateMachineName_);
108  RunControlStateMachine::theProgressBar_.step();
109 
110  std::string result = command + "Done";
111 
112  //if error is received, immediately go to fail state
113  // likely error was sent by central FSM or external xoap
114  if(command == "Error" || command == "Fail")
115  {
116  __SS__ << command << " was received! Halting immediately." << std::endl;
117  __COUT_ERR__ << "\n" << ss.str();
118 
119  try
120  {
121  if(theStateMachine_.getCurrentStateName() == "Configured")
122  theStateMachine_.execTransition("Halt",message);
123  else if(theStateMachine_.getCurrentStateName() == "Running" ||
124  theStateMachine_.getCurrentStateName() == "Paused")
125  theStateMachine_.execTransition("Abort",message);
126  }
127  catch(...)
128  {
129  __COUT_ERR__ << "Halting failed in reaction to Error... ignoring." << __E__;
130  }
131  return SOAPUtilities::makeSOAPMessageReference(result);
132  }
133 
134 
135  //if already Halted, respond to Initialize with "done"
136  // (this avoids race conditions involved with artdaq mpi reset)
137  if(command == "Initialize" &&
138  theStateMachine_.getCurrentStateName() == "Halted")
139  {
140  __COUT__ << "Already Initialized.. ignoring Initialize command." << std::endl;
141  return SOAPUtilities::makeSOAPMessageReference(result);
142  }
143 
144  //handle normal transitions here
145  try
146  {
147  theStateMachine_.execTransition(command,message);
148  //__COUT__ << "I don't know what is going on!" << std::endl;
149 
150  if(theStateMachine_.getCurrentStateName() == RunControlStateMachine::FAILED_STATE_NAME)
151  {
152  result = command + " " + RunControlStateMachine::FAILED_STATE_NAME + ": " + theStateMachine_.getErrorMessage();
153  __COUT_ERR__ << "Unexpected Failure state for " << stateMachineName_ << " is " << theStateMachine_.getCurrentStateName() << std::endl;
154  __COUT_ERR__ << "Error message was as follows: " << theStateMachine_.getErrorMessage() << std::endl;
155  }
156  }
157  catch (toolbox::fsm::exception::Exception& e)
158  {
159  result = command + " " + RunControlStateMachine::FAILED_STATE_NAME + ": " + theStateMachine_.getErrorMessage();
160  __SS__ << "Run Control Message Handling Failed: " << e.what() << std::endl;
161  __COUT_ERR__ << "\n" << ss.str();
162  __COUT_ERR__ << "Error message was as follows: " << theStateMachine_.getErrorMessage() << std::endl;
163  }
164 
165  RunControlStateMachine::theProgressBar_.step();
166  theProgressBar_.complete();
167 
168  __COUT__ << "Ending state for " << stateMachineName_ << " is " << theStateMachine_.getCurrentStateName() << std::endl;
169  __COUT__ << "result = " << result << std::endl;
170  return SOAPUtilities::makeSOAPMessageReference(result);
171 }
172