$treeview $search $mathjax $extrastylesheet
otsdaq
v2_03_00
$projectbrief
|
$projectbrief
|
$searchbox |
00001 #include "otsdaq-core/FiniteStateMachine/FiniteStateMachine.h" 00002 #include "otsdaq-core/MessageFacility/MessageFacility.h" 00003 00004 #include "otsdaq-core/Macros/CoutMacros.h" 00005 00006 #include <map> 00007 #include <sstream> 00008 00009 using namespace ots; 00010 00011 #undef __MF_SUBJECT__ 00012 #define __MF_SUBJECT__ std::string("FSM-") + getStateMachineName() 00013 00014 //======================================================================================================================== 00015 FiniteStateMachine::FiniteStateMachine(const std::string& stateMachineName) 00016 : stateEntranceTime_(0) 00017 , inTransition_(false) 00018 , provenanceState_('X') 00019 , theErrorMessage_("") 00020 , stateMachineName_(stateMachineName) 00021 { 00022 __COUT__ << "Constructing FiniteStateMachine" << std::endl; 00023 } 00024 00025 //======================================================================================================================== 00026 FiniteStateMachine::~FiniteStateMachine(void) {} 00027 00028 //======================================================================================================================== 00029 toolbox::fsm::State FiniteStateMachine::getProvenanceState(void) 00030 { 00031 return provenanceState_; 00032 } 00033 00034 //======================================================================================================================== 00035 toolbox::fsm::State FiniteStateMachine::getTransitionFinalState( 00036 const std::string& transition) 00037 { 00038 if(stateTransitionTable_[currentState_].find(transition) != 00039 stateTransitionTable_[currentState_].end()) 00040 return stateTransitionTable_[currentState_][transition]; 00041 else 00042 { 00043 std::ostringstream error; 00044 error << "Cannot find transition name with transition: " << transition 00045 << ", unknown!"; 00046 XCEPT_RAISE(toolbox::fsm::exception::Exception, error.str()); 00047 } 00048 } 00049 00050 //======================================================================================================================== 00051 std::string FiniteStateMachine::getProvenanceStateName(void) 00052 { 00053 return getStateName(getProvenanceState()); 00054 } 00055 00056 //======================================================================================================================== 00057 std::string FiniteStateMachine::getCurrentStateName(void) 00058 { 00059 return getStateName(getCurrentState()); 00060 } 00061 00062 //======================================================================================================================== 00063 // getTimeInState 00064 // returns number of seconds elapsed while in current state 00065 // returns 0 if invalid (i.e. stateEntranceTime_ is not set - stateEntranceTime_ is 00066 // initialized to 0) 00067 time_t FiniteStateMachine::getTimeInState(void) 00068 { 00069 return stateEntranceTime_ ? (time(0) - stateEntranceTime_) : 0; 00070 } 00071 00072 //======================================================================================================================== 00073 std::string FiniteStateMachine::getCurrentTransitionName(const std::string& transition) 00074 { 00075 if(stateTransitionNameTable_[currentState_].find(transition) != 00076 stateTransitionNameTable_[currentState_].end()) 00077 { 00078 return stateTransitionNameTable_[currentState_][transition]; 00079 } 00080 else 00081 { 00082 std::ostringstream error; 00083 error << "Cannot find transition name with transition: " << transition 00084 << ", unknown!"; 00085 XCEPT_RAISE(toolbox::fsm::exception::Exception, error.str()); 00086 } 00087 } 00088 00089 //======================================================================================================================== 00090 std::string FiniteStateMachine::getTransitionName(const toolbox::fsm::State from, 00091 const std::string& transition) 00092 { 00093 if(stateTransitionNameTable_[from].find(transition) != 00094 stateTransitionNameTable_[from].end()) 00095 { 00096 return stateTransitionNameTable_[from][transition]; 00097 } 00098 else 00099 { 00100 std::ostringstream error; 00101 error << "Cannot find transition name from " << from 00102 << " with transition: " << transition << ", unknown!"; 00103 XCEPT_RAISE(toolbox::fsm::exception::Exception, error.str()); 00104 } 00105 } 00106 00107 //======================================================================================================================== 00108 std::string FiniteStateMachine::getTransitionParameter(const toolbox::fsm::State from, 00109 const std::string& transition) 00110 { 00111 if(stateTransitionParameterTable_[from].find(transition) != 00112 stateTransitionParameterTable_[from].end()) 00113 { 00114 return stateTransitionParameterTable_[from][transition]; 00115 } 00116 return ""; 00117 } 00118 00119 //======================================================================================================================== 00120 std::string FiniteStateMachine::getTransitionFinalStateName(const std::string& transition) 00121 { 00122 return getStateName(getTransitionFinalState(transition)); 00123 } 00124 00125 //======================================================================================================================== 00126 bool FiniteStateMachine::execTransition(const std::string& transition) 00127 { 00128 const xoap::MessageReference message; 00129 return execTransition(transition, message); 00130 } 00131 00132 //======================================================================================================================== 00133 // execTransition 00134 // 00135 // Returns true if transition is successfully executed 00136 // else false if this exec did not complete a transition. 00137 // 00138 // Note: For iteration handling, there is iterationIndex_ and iterationWorkFlag_. 00139 // These are different (higher level) than the members of VStateMachine. 00140 bool FiniteStateMachine::execTransition(const std::string& transition, 00141 const xoap::MessageReference& message) 00142 { 00143 __COUTV__(transition); 00144 00145 if(transition == "fail") 00146 { 00147 __COUT_INFO__ << "Failing now!!" << __E__; 00148 00149 while(inTransition_) 00150 { 00151 __COUT__ << "Currently in a transition executed from current state " 00152 << getProvenanceStateName() 00153 << ". Attempting to wait for the transition to complete." << __E__; 00154 sleep(1); 00155 } 00156 sleep(1); 00157 00158 // find any valid transition and take it.. 00159 // all transition functions must check for a failure 00160 // flag, and throw an exception to go to Fail state 00161 00162 std::map<std::string, toolbox::fsm::State> transitions = 00163 getTransitions(getCurrentState()); 00164 for(const auto& transitionPair : transitions) 00165 { 00166 __COUT__ << "Taking transition to indirect failure: " << transitionPair.first 00167 << __E__; 00168 toolbox::Event::Reference event( 00169 new toolbox::Event(transitionPair.first, this)); 00170 00171 try 00172 { 00173 this->fireEvent(event); 00174 } 00175 catch(toolbox::fsm::exception::Exception& e) 00176 { 00177 std::ostringstream error; 00178 error << "Transition " << transition 00179 << " was not executed from current state " 00180 << getStateName(getCurrentState()) 00181 << ". There was an error: " << e.what(); 00182 __COUT_ERR__ << error.str() << std::endl; 00183 } 00184 inTransition_ = false; 00185 stateEntranceTime_ = time(0); 00186 return true; 00187 } 00188 // //XCEPT_RAISE (toolbox::fsm::exception::Exception, transition); 00189 // theMessage_ = message; 00190 // toolbox::Event::Reference event(new toolbox::Event(, this)); 00191 // 00192 } 00193 00194 if(inTransition_) 00195 { 00196 __COUT_WARN__ << "In transition, and received another transition: " << transition 00197 << ". Ignoring..." << __E__; 00198 00199 return false; 00200 } 00201 inTransition_ = true; 00202 bool transitionSuccessful = true; 00203 provenanceState_ = getCurrentState(); 00204 00205 std::map<std::string, toolbox::fsm::State> transitions = 00206 getTransitions(getCurrentState()); 00207 if(transitions.find(transition) == transitions.end()) 00208 { 00209 inTransition_ = false; 00210 std::ostringstream error; 00211 error << transition 00212 << " is not in the list of the transitions from current state " 00213 << getStateName(getCurrentState()); 00214 __COUT_ERR__ << error.str() << std::endl; 00215 XCEPT_RAISE(toolbox::fsm::exception::Exception, error.str()); 00216 //__COUT__ << error << std::endl; 00217 // __COUT__ << "Transition?" << inTransition_ << std::endl; 00218 return false; 00219 } 00220 00221 // fire FSM event by calling mapped function 00222 // (e.g. mapped by RunControlStateMachine and function implemented by 00223 // CoreSupervisorBase class inheriting from RunControlStateMachine) 00224 try 00225 { 00226 toolbox::Event::Reference event(new toolbox::Event(transition, this)); 00227 theMessage_ = 00228 message; // Even if it is bad, there can only be 1 transition at a time 00229 // so this parameter should not change during all transition 00230 00231 this->fireEvent(event); 00232 } 00233 catch(toolbox::fsm::exception::Exception& e) 00234 { 00235 inTransition_ = false; 00236 transitionSuccessful = false; 00237 std::ostringstream error; 00238 __SS__ << "Transition " << transition << " was not executed from current state " 00239 << getStateName(getCurrentState()) << ". There was an error: " << e.what(); 00240 __COUT_ERR__ << ss.str() << std::endl; 00241 // diagService_->reportError(err.str(),DIAGERROR); 00242 00243 // send state machine to error 00244 XCEPT_RAISE(toolbox::fsm::exception::Exception, ss.str()); 00245 } 00246 catch(...) 00247 { 00248 inTransition_ = false; 00249 transitionSuccessful = false; 00250 __SS__ << "Transition " << transition << " was not executed from current state " 00251 << getStateName(getCurrentState()) << ". There was an unknown error."; 00252 __COUT_ERR__ << ss.str() << std::endl; 00253 // diagService_->reportError(err.str(),DIAGERROR); 00254 00255 // send state machine to error 00256 XCEPT_RAISE(toolbox::fsm::exception::Exception, ss.str()); 00257 } 00258 00259 inTransition_ = false; 00260 stateEntranceTime_ = time(0); 00261 return transitionSuccessful; 00262 } 00263 00264 //======================================================================================================================== 00265 bool FiniteStateMachine::isInTransition(void) { return inTransition_; } 00266 00267 //======================================================================================================================== 00268 void FiniteStateMachine::setErrorMessage(const std::string& errMessage, bool append) 00269 { 00270 if(append) 00271 theErrorMessage_ += errMessage; 00272 else 00273 theErrorMessage_ = errMessage; 00274 } 00275 00276 //======================================================================================================================== 00277 const std::string& FiniteStateMachine::getErrorMessage() const 00278 { 00279 return theErrorMessage_; 00280 } 00281 00282 //======================================================================================================================== 00283 void FiniteStateMachine::setInitialState(toolbox::fsm::State state) 00284 { 00285 toolbox::fsm::FiniteStateMachine::setInitialState(state); 00286 provenanceState_ = state; 00287 stateEntranceTime_ = time(0); 00288 } 00289 00290 //======================================================================================================================== 00291 const xoap::MessageReference& FiniteStateMachine::getCurrentMessage(void) 00292 { 00293 return theMessage_; 00294 }