otsdaq  v2_03_00
FiniteStateMachine.cc
1 #include "otsdaq-core/FiniteStateMachine/FiniteStateMachine.h"
2 #include "otsdaq-core/MessageFacility/MessageFacility.h"
3 
4 #include "otsdaq-core/Macros/CoutMacros.h"
5 
6 #include <map>
7 #include <sstream>
8 
9 using namespace ots;
10 
11 #undef __MF_SUBJECT__
12 #define __MF_SUBJECT__ std::string("FSM-") + getStateMachineName()
13 
14 //========================================================================================================================
15 FiniteStateMachine::FiniteStateMachine(const std::string& stateMachineName)
16  : stateEntranceTime_(0)
17  , inTransition_(false)
18  , provenanceState_('X')
19  , theErrorMessage_("")
20  , stateMachineName_(stateMachineName)
21 {
22  __COUT__ << "Constructing FiniteStateMachine" << std::endl;
23 }
24 
25 //========================================================================================================================
26 FiniteStateMachine::~FiniteStateMachine(void) {}
27 
28 //========================================================================================================================
29 toolbox::fsm::State FiniteStateMachine::getProvenanceState(void)
30 {
31  return provenanceState_;
32 }
33 
34 //========================================================================================================================
35 toolbox::fsm::State FiniteStateMachine::getTransitionFinalState(
36  const std::string& transition)
37 {
38  if(stateTransitionTable_[currentState_].find(transition) !=
39  stateTransitionTable_[currentState_].end())
40  return stateTransitionTable_[currentState_][transition];
41  else
42  {
43  std::ostringstream error;
44  error << "Cannot find transition name with transition: " << transition
45  << ", unknown!";
46  XCEPT_RAISE(toolbox::fsm::exception::Exception, error.str());
47  }
48 }
49 
50 //========================================================================================================================
51 std::string FiniteStateMachine::getProvenanceStateName(void)
52 {
53  return getStateName(getProvenanceState());
54 }
55 
56 //========================================================================================================================
57 std::string FiniteStateMachine::getCurrentStateName(void)
58 {
59  return getStateName(getCurrentState());
60 }
61 
62 //========================================================================================================================
63 // getTimeInState
64 // returns number of seconds elapsed while in current state
65 // returns 0 if invalid (i.e. stateEntranceTime_ is not set - stateEntranceTime_ is
66 // initialized to 0)
67 time_t FiniteStateMachine::getTimeInState(void)
68 {
69  return stateEntranceTime_ ? (time(0) - stateEntranceTime_) : 0;
70 }
71 
72 //========================================================================================================================
73 std::string FiniteStateMachine::getCurrentTransitionName(const std::string& transition)
74 {
75  if(stateTransitionNameTable_[currentState_].find(transition) !=
76  stateTransitionNameTable_[currentState_].end())
77  {
78  return stateTransitionNameTable_[currentState_][transition];
79  }
80  else
81  {
82  std::ostringstream error;
83  error << "Cannot find transition name with transition: " << transition
84  << ", unknown!";
85  XCEPT_RAISE(toolbox::fsm::exception::Exception, error.str());
86  }
87 }
88 
89 //========================================================================================================================
90 std::string FiniteStateMachine::getTransitionName(const toolbox::fsm::State from,
91  const std::string& transition)
92 {
93  if(stateTransitionNameTable_[from].find(transition) !=
94  stateTransitionNameTable_[from].end())
95  {
96  return stateTransitionNameTable_[from][transition];
97  }
98  else
99  {
100  std::ostringstream error;
101  error << "Cannot find transition name from " << from
102  << " with transition: " << transition << ", unknown!";
103  XCEPT_RAISE(toolbox::fsm::exception::Exception, error.str());
104  }
105 }
106 
107 //========================================================================================================================
108 std::string FiniteStateMachine::getTransitionParameter(const toolbox::fsm::State from,
109  const std::string& transition)
110 {
111  if(stateTransitionParameterTable_[from].find(transition) !=
112  stateTransitionParameterTable_[from].end())
113  {
114  return stateTransitionParameterTable_[from][transition];
115  }
116  return "";
117 }
118 
119 //========================================================================================================================
120 std::string FiniteStateMachine::getTransitionFinalStateName(const std::string& transition)
121 {
122  return getStateName(getTransitionFinalState(transition));
123 }
124 
125 //========================================================================================================================
126 bool FiniteStateMachine::execTransition(const std::string& transition)
127 {
128  const xoap::MessageReference message;
129  return execTransition(transition, message);
130 }
131 
132 //========================================================================================================================
133 // execTransition
134 //
135 // Returns true if transition is successfully executed
136 // else false if this exec did not complete a transition.
137 //
138 // Note: For iteration handling, there is iterationIndex_ and iterationWorkFlag_.
139 // These are different (higher level) than the members of VStateMachine.
140 bool FiniteStateMachine::execTransition(const std::string& transition,
141  const xoap::MessageReference& message)
142 {
143  __COUTV__(transition);
144 
145  if(transition == "fail")
146  {
147  __COUT_INFO__ << "Failing now!!" << __E__;
148 
149  while(inTransition_)
150  {
151  __COUT__ << "Currently in a transition executed from current state "
152  << getProvenanceStateName()
153  << ". Attempting to wait for the transition to complete." << __E__;
154  sleep(1);
155  }
156  sleep(1);
157 
158  // find any valid transition and take it..
159  // all transition functions must check for a failure
160  // flag, and throw an exception to go to Fail state
161 
162  std::map<std::string, toolbox::fsm::State> transitions =
163  getTransitions(getCurrentState());
164  for(const auto& transitionPair : transitions)
165  {
166  __COUT__ << "Taking transition to indirect failure: " << transitionPair.first
167  << __E__;
168  toolbox::Event::Reference event(
169  new toolbox::Event(transitionPair.first, this));
170 
171  try
172  {
173  this->fireEvent(event);
174  }
175  catch(toolbox::fsm::exception::Exception& e)
176  {
177  std::ostringstream error;
178  error << "Transition " << transition
179  << " was not executed from current state "
180  << getStateName(getCurrentState())
181  << ". There was an error: " << e.what();
182  __COUT_ERR__ << error.str() << std::endl;
183  }
184  inTransition_ = false;
185  stateEntranceTime_ = time(0);
186  return true;
187  }
188  // //XCEPT_RAISE (toolbox::fsm::exception::Exception, transition);
189  // theMessage_ = message;
190  // toolbox::Event::Reference event(new toolbox::Event(, this));
191  //
192  }
193 
194  if(inTransition_)
195  {
196  __COUT_WARN__ << "In transition, and received another transition: " << transition
197  << ". Ignoring..." << __E__;
198 
199  return false;
200  }
201  inTransition_ = true;
202  bool transitionSuccessful = true;
203  provenanceState_ = getCurrentState();
204 
205  std::map<std::string, toolbox::fsm::State> transitions =
206  getTransitions(getCurrentState());
207  if(transitions.find(transition) == transitions.end())
208  {
209  inTransition_ = false;
210  std::ostringstream error;
211  error << transition
212  << " is not in the list of the transitions from current state "
213  << getStateName(getCurrentState());
214  __COUT_ERR__ << error.str() << std::endl;
215  XCEPT_RAISE(toolbox::fsm::exception::Exception, error.str());
216  //__COUT__ << error << std::endl;
217  // __COUT__ << "Transition?" << inTransition_ << std::endl;
218  return false;
219  }
220 
221  // fire FSM event by calling mapped function
222  // (e.g. mapped by RunControlStateMachine and function implemented by
223  // CoreSupervisorBase class inheriting from RunControlStateMachine)
224  try
225  {
226  toolbox::Event::Reference event(new toolbox::Event(transition, this));
227  theMessage_ =
228  message; // Even if it is bad, there can only be 1 transition at a time
229  // so this parameter should not change during all transition
230 
231  this->fireEvent(event);
232  }
233  catch(toolbox::fsm::exception::Exception& e)
234  {
235  inTransition_ = false;
236  transitionSuccessful = false;
237  std::ostringstream error;
238  __SS__ << "Transition " << transition << " was not executed from current state "
239  << getStateName(getCurrentState()) << ". There was an error: " << e.what();
240  __COUT_ERR__ << ss.str() << std::endl;
241  // diagService_->reportError(err.str(),DIAGERROR);
242 
243  // send state machine to error
244  XCEPT_RAISE(toolbox::fsm::exception::Exception, ss.str());
245  }
246  catch(...)
247  {
248  inTransition_ = false;
249  transitionSuccessful = false;
250  __SS__ << "Transition " << transition << " was not executed from current state "
251  << getStateName(getCurrentState()) << ". There was an unknown error.";
252  __COUT_ERR__ << ss.str() << std::endl;
253  // diagService_->reportError(err.str(),DIAGERROR);
254 
255  // send state machine to error
256  XCEPT_RAISE(toolbox::fsm::exception::Exception, ss.str());
257  }
258 
259  inTransition_ = false;
260  stateEntranceTime_ = time(0);
261  return transitionSuccessful;
262 }
263 
264 //========================================================================================================================
265 bool FiniteStateMachine::isInTransition(void) { return inTransition_; }
266 
267 //========================================================================================================================
268 void FiniteStateMachine::setErrorMessage(const std::string& errMessage, bool append)
269 {
270  if(append)
271  theErrorMessage_ += errMessage;
272  else
273  theErrorMessage_ = errMessage;
274 }
275 
276 //========================================================================================================================
277 const std::string& FiniteStateMachine::getErrorMessage() const
278 {
279  return theErrorMessage_;
280 }
281 
282 //========================================================================================================================
283 void FiniteStateMachine::setInitialState(toolbox::fsm::State state)
284 {
285  toolbox::fsm::FiniteStateMachine::setInitialState(state);
286  provenanceState_ = state;
287  stateEntranceTime_ = time(0);
288 }
289 
290 //========================================================================================================================
291 const xoap::MessageReference& FiniteStateMachine::getCurrentMessage(void)
292 {
293  return theMessage_;
294 }