00001 #include "otsdaq-core/FiniteStateMachine/RunControlStateMachine.h"
00002 #include "otsdaq-core/MessageFacility/MessageFacility.h"
00003 #include "otsdaq-core/Macros/CoutMacros.h"
00004 #include "otsdaq-core/SOAPUtilities/SOAPUtilities.h"
00005 #include "otsdaq-core/SOAPUtilities/SOAPCommand.h"
00006
00007 #include <toolbox/fsm/FailedEvent.h>
00008 #include <xoap/Method.h>
00009 #include <xdaq/NamespaceURI.h>
00010
00011 #include <iostream>
00012
00013 #undef __MF_SUBJECT__
00014 #define __MF_SUBJECT__ std::string("FSM-") + stateMachineName_
00015
00016
00017 using namespace ots;
00018
00019 const std::string RunControlStateMachine::FAILED_STATE_NAME = "Failed";
00020
00021
00022 RunControlStateMachine::RunControlStateMachine(std::string name)
00023 : stateMachineName_(name)
00024 {
00025 INIT_MF("RunControlStateMachine");
00026
00027 theStateMachine_.addState('I', "Initial", this, &RunControlStateMachine::stateInitial);
00028 theStateMachine_.addState('H', "Halted", this, &RunControlStateMachine::stateHalted);
00029 theStateMachine_.addState('C', "Configured", this, &RunControlStateMachine::stateConfigured);
00030 theStateMachine_.addState('R', "Running", this, &RunControlStateMachine::stateRunning);
00031 theStateMachine_.addState('P', "Paused", this, &RunControlStateMachine::statePaused);
00032 theStateMachine_.addState('X', "Shutdown", this, &RunControlStateMachine::stateShutdown);
00033
00034
00035
00036
00037
00038
00039
00040 theStateMachine_.setStateName('F',RunControlStateMachine::FAILED_STATE_NAME);
00041 theStateMachine_.setFailedStateTransitionAction (this, &RunControlStateMachine::enteringError);
00042 theStateMachine_.setFailedStateTransitionChanged(this, &RunControlStateMachine::inError);
00043
00044
00045 theStateMachine_.addStateTransition('F', 'H', "Halt" , "Halting" , this, &RunControlStateMachine::transitionHalting);
00046
00047
00048
00049 theStateMachine_.addStateTransition('H', 'C', "Configure" , "Configuring" , "ConfigurationAlias", this, &RunControlStateMachine::transitionConfiguring);
00050 theStateMachine_.addStateTransition('H', 'X', "Shutdown" , "Shutting Down", this, &RunControlStateMachine::transitionShuttingDown);
00051 theStateMachine_.addStateTransition('X', 'I', "Startup" , "Starting Up" , this, &RunControlStateMachine::transitionStartingUp);
00052
00053
00054 theStateMachine_.addStateTransition('I', 'H', "Initialize", "Initializing" , this, &RunControlStateMachine::transitionInitializing);
00055 theStateMachine_.addStateTransition('H', 'H', "Halt" , "Halting" , this, &RunControlStateMachine::transitionHalting);
00056 theStateMachine_.addStateTransition('C', 'H', "Halt" , "Halting" , this, &RunControlStateMachine::transitionHalting);
00057 theStateMachine_.addStateTransition('R', 'H', "Abort" , "Aborting" , this, &RunControlStateMachine::transitionHalting);
00058 theStateMachine_.addStateTransition('P', 'H', "Abort" , "Aborting" , this, &RunControlStateMachine::transitionHalting);
00059
00060 theStateMachine_.addStateTransition('R', 'P', "Pause" , "Pausing" , this, &RunControlStateMachine::transitionPausing);
00061 theStateMachine_.addStateTransition('P', 'R', "Resume" , "Resuming" , this, &RunControlStateMachine::transitionResuming);
00062 theStateMachine_.addStateTransition('C', 'R', "Start" , "Starting" , this, &RunControlStateMachine::transitionStarting);
00063 theStateMachine_.addStateTransition('R', 'C', "Stop" , "Stopping" , this, &RunControlStateMachine::transitionStopping);
00064 theStateMachine_.addStateTransition('P', 'C', "Stop" , "Stopping" , this, &RunControlStateMachine::transitionStopping);
00065
00066
00067
00068 xoap::bind(this, &RunControlStateMachine::runControlMessageHandler, "Initialize", XDAQ_NS_URI);
00069 xoap::bind(this, &RunControlStateMachine::runControlMessageHandler, "Configure" , XDAQ_NS_URI);
00070 xoap::bind(this, &RunControlStateMachine::runControlMessageHandler, "Start" , XDAQ_NS_URI);
00071 xoap::bind(this, &RunControlStateMachine::runControlMessageHandler, "Stop" , XDAQ_NS_URI);
00072 xoap::bind(this, &RunControlStateMachine::runControlMessageHandler, "Pause" , XDAQ_NS_URI);
00073 xoap::bind(this, &RunControlStateMachine::runControlMessageHandler, "Resume" , XDAQ_NS_URI);
00074 xoap::bind(this, &RunControlStateMachine::runControlMessageHandler, "Halt" , XDAQ_NS_URI);
00075 xoap::bind(this, &RunControlStateMachine::runControlMessageHandler, "Abort" , XDAQ_NS_URI);
00076 xoap::bind(this, &RunControlStateMachine::runControlMessageHandler, "Shutdown" , XDAQ_NS_URI);
00077 xoap::bind(this, &RunControlStateMachine::runControlMessageHandler, "Startup" , XDAQ_NS_URI);
00078 xoap::bind(this, &RunControlStateMachine::runControlMessageHandler, "Fail" , XDAQ_NS_URI);
00079 xoap::bind(this, &RunControlStateMachine::runControlMessageHandler, "Error" , XDAQ_NS_URI);
00080
00081
00082 reset();
00083 }
00084
00085
00086 RunControlStateMachine::~RunControlStateMachine(void)
00087 {
00088 }
00089
00090
00091 void RunControlStateMachine::reset(void)
00092 {
00093 __COUT__ << "Resetting RunControlStateMachine with name '" << stateMachineName_ << "'..." << __E__;
00094 theStateMachine_.setInitialState('I');
00095 theStateMachine_.reset();
00096 }
00097
00098
00099 xoap::MessageReference RunControlStateMachine::runControlMessageHandler(
00100 xoap::MessageReference message)
00101
00102 {
00103 __COUT__ << "Starting state for " << stateMachineName_ << " is " <<
00104 theStateMachine_.getCurrentStateName() << std::endl;
00105 __COUT__ << SOAPUtilities::translate(message) << std::endl;
00106
00107 theStateMachine_.setErrorMessage("");
00108
00109 std::string command = SOAPUtilities::translate(message).getCommand();
00110
00111 theProgressBar_.reset(command,stateMachineName_);
00112 RunControlStateMachine::theProgressBar_.step();
00113
00114 std::string result = command + "Done";
00115
00116
00117
00118 if(command == "Error" || command == "Fail")
00119 {
00120 __SS__ << command << " was received! Halting immediately." << std::endl;
00121 __COUT_ERR__ << "\n" << ss.str();
00122
00123 try
00124 {
00125 if(theStateMachine_.getCurrentStateName() == "Configured")
00126 theStateMachine_.execTransition("Halt",message);
00127 else if(theStateMachine_.getCurrentStateName() == "Running" ||
00128 theStateMachine_.getCurrentStateName() == "Paused")
00129 theStateMachine_.execTransition("Abort",message);
00130 }
00131 catch(...)
00132 {
00133 __COUT_ERR__ << "Halting failed in reaction to Error... ignoring." << __E__;
00134 }
00135 return SOAPUtilities::makeSOAPMessageReference(result);
00136 }
00137
00138
00139
00140
00141 if(command == "Initialize" &&
00142 theStateMachine_.getCurrentStateName() == "Halted")
00143 {
00144 __COUT__ << "Already Initialized.. ignoring Initialize command." << std::endl;
00145 return SOAPUtilities::makeSOAPMessageReference(result);
00146 }
00147
00148
00149 try
00150 {
00151 theStateMachine_.execTransition(command,message);
00152
00153
00154 if(theStateMachine_.getCurrentStateName() == RunControlStateMachine::FAILED_STATE_NAME)
00155 {
00156 result = command + " " + RunControlStateMachine::FAILED_STATE_NAME + ": " + theStateMachine_.getErrorMessage();
00157 __COUT_ERR__ << "Unexpected Failure state for " << stateMachineName_ << " is " << theStateMachine_.getCurrentStateName() << std::endl;
00158 __COUT_ERR__ << "Error message was as follows: " << theStateMachine_.getErrorMessage() << std::endl;
00159 }
00160 }
00161 catch (toolbox::fsm::exception::Exception& e)
00162 {
00163 result = command + " " + RunControlStateMachine::FAILED_STATE_NAME + ": " + theStateMachine_.getErrorMessage();
00164 __SS__ << "Run Control Message Handling Failed: " << e.what() << std::endl;
00165 __COUT_ERR__ << "\n" << ss.str();
00166 __COUT_ERR__ << "Error message was as follows: " << theStateMachine_.getErrorMessage() << std::endl;
00167 }
00168
00169 RunControlStateMachine::theProgressBar_.step();
00170 theProgressBar_.complete();
00171
00172 __COUT__ << "Ending state for " << stateMachineName_ << " is " << theStateMachine_.getCurrentStateName() << std::endl;
00173 __COUT__ << "result = " << result << std::endl;
00174 return SOAPUtilities::makeSOAPMessageReference(result);
00175 }
00176