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