CMS 3D CMS Logo

/data/git/CMSSW_5_3_11_patch5/src/EventFilter/ResourceBroker/interface/RBStateMachine.h

Go to the documentation of this file.
00001 
00002 //
00003 // RBStateMachine.h
00004 // -------
00005 //
00006 // Finite state machine for the Resource Broker.
00007 //
00008 //  Created on: Dec 9, 2011
00009 //                                                                              Andrei Spataru : aspataru@cern.ch
00011 
00012 #ifndef RBBOOSTSTATEMACHINE_H_
00013 #define RBBOOSTSTATEMACHINE_H_
00014 
00015 #include "EventFilter/Utilities/interface/Exception.h"
00016 #include "EventFilter/ResourceBroker/interface/FUTypes.h"
00017 
00018 #include "xdaq2rc/RcmsStateNotifier.h"
00019 #include "xdata/String.h"
00020 #include "xdata/Bag.h"
00021 #include "xdaq/Application.h"
00022 
00023 #include <boost/statechart/event.hpp>
00024 #include <boost/statechart/in_state_reaction.hpp>
00025 #include <boost/statechart/state_machine.hpp>
00026 #include <boost/statechart/state.hpp>
00027 #include <boost/statechart/transition.hpp>
00028 #include <boost/mpl/list.hpp>
00029 #include <boost/shared_ptr.hpp>
00030 
00031 #include "toolbox/task/Action.h"
00032 #include "toolbox/task/WorkLoop.h"
00033 #include "toolbox/task/WorkLoopFactory.h"
00034 
00035 #include <iostream>
00036 #include <string>
00037 #include <vector>
00038 #include <semaphore.h>
00039 
00040 namespace bsc = boost::statechart;
00041 
00042 namespace evf {
00043 
00044 namespace rb_statemachine {
00045 
00046 enum States {
00047         HALTED,
00048         CONFIGURING,
00049         READY,
00050         STOPPED,
00051         ENABLING,
00052         ENABLED,
00053         RUNNING,
00054         STOPPING,
00055         HALTING,
00056         NORMAL,
00057         FAILED
00058 };
00059 
00060 class SharedResources;
00061 typedef boost::shared_ptr<SharedResources> SharedResourcesPtr_t;
00062 
00066 
00067 // Outer states:
00068 class Failed;
00069 class Normal;
00070 
00071 // Inner states of Normal:
00072 class Halted;
00073 class Halting;
00074 class Configuring;
00075 class Ready;
00076 
00077 // Inner states of Ready:
00078 class Stopped;
00079 class Enabled;
00080 class Enabling;
00081 // state hidden from RCMS
00082 class Stopping;
00083 
00084 // Inner states of Enabled:
00085 // state hidden from RCMS
00086 class Running;
00087 
00091 
00092 class Configure: public bsc::event<Configure> {
00093 };
00094 class ConfigureDone: public bsc::event<ConfigureDone> {
00095 };
00096 class Enable: public bsc::event<Enable> {
00097 };
00098 class EnableDone: public bsc::event<EnableDone> {
00099 };
00100 class Stop: public bsc::event<Stop> {
00101 };
00102 class StopDone: public bsc::event<StopDone> {
00103 };
00104 class Halt: public bsc::event<Halt> {
00105 };
00106 class HaltDone: public bsc::event<HaltDone> {
00107 };
00108 class Fail: public bsc::event<Fail> {
00109 };
00110 
00111 //______________________________________________________________________________
00119 class BaseState {
00120 
00121 public:
00122 
00123         BaseState();
00124         virtual ~BaseState() = 0;
00125         std::string stateName() const;
00126         void moveToFailedState(xcept::Exception& exception) const;
00127 
00128         /*
00129          * I2O message handling capability of states.
00130          * All states with special behavior must override these functions.
00131          */
00135         virtual bool discardDataEvent(MemRef_t* bufRef) const {
00136                 std::cout
00137                                 << "RBStateMachine: current state does not support operation >>discardDataEvent<<"
00138                                 << std::endl;
00139                 // bool value doesn't matter... return value ignored by caller: FUResourceBroker
00140                 return false;
00141         }
00142 
00146         virtual bool discardDqmEvent(MemRef_t* bufRef) const {
00147                 std::cout
00148                                 << "RBStateMachine: current state does not support operation >>discardDqmEvent<<"
00149                                 << std::endl;
00150                 // bool value doesn't matter... return value ignored by caller: FUResourceBroker
00151                 return false;
00152         }
00153 
00154         /*
00155          * DEFAULT implementations of state-dependent actions.
00156          * All states with special behavior must override these functions.
00157          */
00158 
00162         virtual void do_stateNotify() = 0;
00163 
00167         virtual int stateID() const = 0;
00168 
00172         virtual void do_stateAction() const {
00173                 // do nothing if state does not override this function
00174                 /*
00175                  std::cout << "RBStateMachine: no >>STATE ACTION<< defined for state: "
00176                  << stateName() << std::endl;
00177                  */
00178         }
00179 
00180 protected:
00181 
00182         virtual std::string do_stateName() const = 0;
00183 
00184         virtual void do_moveToFailedState(xcept::Exception& exception) const = 0;
00185         void fail();
00186 
00187         void safeEntryAction();
00188         virtual void do_entryActionWork() = 0;
00189 
00190         void safeExitAction();
00191         virtual void do_exitActionWork() = 0;
00192 
00193 };
00194 
00195 //______________________________________________________________________________
00201 class RBStateMachine: public bsc::state_machine<RBStateMachine, Normal> {
00202 
00203 public:
00204 
00205         RBStateMachine(xdaq::Application* app, SharedResourcesPtr_t sr);
00206         ~RBStateMachine();
00207 
00212         BaseState const& getCurrentState() const throw (std::bad_cast);
00213 
00214         BaseState & getCurrentStateNC() const throw (std::bad_cast);
00215 
00216         inline SharedResourcesPtr_t getSharedResources() const {
00217                 return sharedResources_;
00218         }
00219         inline std::string getExternallyVisibleState() {
00220                 return visibleStateName_.value_;
00221         }
00222         inline xdata::String* getExternallyVisibleStatePtr() {
00223                 return &visibleStateName_;
00224         }
00225         inline std::string getInternalStateName() {
00226                 return internalStateName_;
00227         }
00228         inline xdaq::Application* getApp() const {
00229                 return app_;
00230         }
00231         void setExternallyVisibleState(const std::string& s);
00232         void setInternalStateName(const std::string& s);
00236         inline bool firstTimeInHalted() const {
00237                 return firstTimeInHalted_;
00238         }
00239         inline void setFirstTimeInHaltedFalse() {
00240                 firstTimeInHalted_ = false;
00241         }
00242 
00246         xdata::Bag<xdaq2rc::ClassnameAndInstance>* rcmsStateListener();
00250         xdata::Boolean* foundRcmsStateListener();
00251         void findRcmsStateListener(xdaq::Application* app);
00255         void rcmsStateChangeNotify();
00256 
00257         // state-transition safety
00261         void transitionWriteLock() {
00262                 pthread_rwlock_wrlock(&transitionLock_);
00263         }
00267         void transitionReadLock() {
00268                 pthread_rwlock_rdlock(&transitionLock_);
00269         }
00273         void transitionUnlock() {
00274                 pthread_rwlock_unlock(&transitionLock_);
00275         }
00276 
00277 private:
00278         void updateWebGUIExternalState(std::string newStateName) const;
00279         void updateWebGUIInternalState(std::string newStateName) const;
00280 
00281 private:
00282 
00283         xdaq::Application* app_;
00284         SharedResourcesPtr_t sharedResources_;
00285         xdaq2rc::RcmsStateNotifier rcmsStateNotifier_;
00286         xdata::String visibleStateName_;
00287         std::string internalStateName_;
00288         bool firstTimeInHalted_;
00289 
00290         pthread_rwlock_t transitionLock_;
00291 };
00292 
00296 
00297 //______________________________________________________________________________
00302 class Failed: public bsc::state<Failed, RBStateMachine>, public BaseState {
00303 
00304 public:
00305 
00306         Failed( my_context);
00307         virtual ~Failed();
00308 
00309         // state-dependent actions
00310         virtual void do_stateNotify();
00311 
00312         virtual int stateID() const {
00313                 return rb_statemachine::FAILED;
00314         }
00315 
00316 private:
00317 
00318         virtual std::string do_stateName() const;
00319         virtual void do_entryActionWork();
00320         virtual void do_exitActionWork();
00321         virtual void do_moveToFailedState(xcept::Exception& exception) const;
00322 
00323 };
00324 
00325 //______________________________________________________________________________
00331 class Normal: public bsc::state<Normal, RBStateMachine, Halted>,
00332                 public BaseState {
00333 
00334 public:
00335 
00336         typedef bsc::transition<Fail, Failed> FT;
00337         typedef boost::mpl::list<FT> reactions;
00338 
00339         // state-dependent actions
00340         virtual void do_stateNotify();
00341 
00342         virtual int stateID() const {
00343                 return rb_statemachine::NORMAL;
00344         }
00345 
00346         Normal( my_context);
00347         virtual ~Normal();
00348 
00349 private:
00350 
00351         virtual std::string do_stateName() const;
00352         virtual void do_entryActionWork();
00353         virtual void do_exitActionWork();
00354         virtual void do_moveToFailedState(xcept::Exception& exception) const;
00355 };
00356 
00357 //______________________________________________________________________________
00363 class Halted: public bsc::state<Halted, Normal>, public BaseState {
00364 
00365 public:
00366 
00367         typedef bsc::transition<Configure, Configuring> RT;
00368         typedef boost::mpl::list<RT> reactions;
00369 
00370         // state-dependent actions
00371         virtual void do_stateNotify();
00372 
00373         virtual int stateID() const {
00374                 return rb_statemachine::HALTED;
00375         }
00376 
00377         Halted( my_context);
00378         virtual ~Halted();
00379 
00380 private:
00381 
00382         virtual std::string do_stateName() const;
00383         virtual void do_entryActionWork();
00384         virtual void do_exitActionWork();
00385         virtual void do_moveToFailedState(xcept::Exception& exception) const;
00386 
00387 };
00388 
00389 //______________________________________________________________________________
00395 class Configuring: public bsc::state<Configuring, Normal>, public BaseState {
00396 
00397 public:
00398 
00399         typedef bsc::transition<ConfigureDone, Ready> CR;
00400         typedef boost::mpl::list<CR> reactions;
00401 
00402         Configuring( my_context);
00403         virtual ~Configuring();
00404 
00405         // state-dependent actions
00406         virtual void do_stateNotify();
00407         virtual int stateID() const {
00408                 return rb_statemachine::CONFIGURING;
00409         }
00410         virtual void do_stateAction() const;
00411 
00412 private:
00413 
00417         void connectToBUandSM() const throw (evf::Exception);
00418 
00419 private:
00420 
00421         virtual std::string do_stateName() const;
00422         virtual void do_entryActionWork();
00423         virtual void do_exitActionWork();
00424         virtual void do_moveToFailedState(xcept::Exception& exception) const;
00425 
00426 };
00427 
00428 //______________________________________________________________________________
00434 class Ready: public bsc::state<Ready, Normal, Stopped>, public BaseState {
00435 
00436 public:
00437 
00438         typedef bsc::transition<Halt, Halting> HT;
00439         typedef boost::mpl::list<HT> reactions;
00440 
00441         // state-dependent actions
00442         virtual void do_stateNotify();
00443 
00444         virtual int stateID() const {
00445                 return rb_statemachine::READY;
00446         }
00447 
00448         Ready( my_context);
00449         virtual ~Ready();
00450 
00451 private:
00452 
00453         virtual std::string do_stateName() const;
00454         virtual void do_entryActionWork();
00455         virtual void do_exitActionWork();
00456         virtual void do_moveToFailedState(xcept::Exception& exception) const;
00457 
00458 };
00459 
00460 //______________________________________________________________________________
00466 class Stopped: public bsc::state<Stopped, Ready>, public BaseState {
00467 
00468 public:
00469 
00470         typedef bsc::transition<Enable, Enabling> ET;
00471         typedef boost::mpl::list<ET> reactions;
00472 
00473         // state-dependent actions
00474         virtual void do_stateNotify();
00475 
00476         virtual int stateID() const {
00477                 return rb_statemachine::STOPPED;
00478         }
00479 
00480         Stopped( my_context);
00481         virtual ~Stopped();
00482 
00483 private:
00484 
00485         virtual std::string do_stateName() const;
00486         virtual void do_entryActionWork();
00487         virtual void do_exitActionWork();
00488         virtual void do_moveToFailedState(xcept::Exception& exception) const;
00489 
00490 };
00491 
00492 //______________________________________________________________________________
00498 class Enabling: public bsc::state<Enabling, Ready>,
00499                 public BaseState,
00500                 public toolbox::lang::Class {
00501 
00502 public:
00503 
00504         typedef bsc::transition<EnableDone, Enabled> ED;
00505         typedef boost::mpl::list<ED> reactions;
00506 
00507         Enabling( my_context);
00508         virtual ~Enabling();
00509 
00510         // state-dependent actions
00511         virtual void do_stateNotify();
00512         virtual int stateID() const {
00513                 return rb_statemachine::ENABLING;
00514         }
00515         virtual void do_stateAction() const;
00516 
00517 private:
00518 
00519         virtual std::string do_stateName() const;
00520         virtual void do_entryActionWork();
00521         virtual void do_exitActionWork();
00522         virtual void do_moveToFailedState(xcept::Exception& exception) const;
00523 
00524 };
00525 
00526 //______________________________________________________________________________
00532 class Enabled: public bsc::state<Enabled, Ready, Running>, public BaseState {
00533 
00534 public:
00535 
00536         typedef bsc::transition<Stop, Stopping> ST;
00537         typedef boost::mpl::list<ST> reactions;
00538 
00539         // state-dependent actions
00540         virtual void do_stateNotify();
00541 
00542         virtual int stateID() const {
00543                 return rb_statemachine::ENABLED;
00544         }
00545 
00546         Enabled( my_context);
00547         virtual ~Enabled();
00548 
00549 private:
00550 
00551         virtual std::string do_stateName() const;
00552         virtual void do_entryActionWork();
00553         virtual void do_exitActionWork();
00554         virtual void do_moveToFailedState(xcept::Exception& exception) const;
00555 
00556 };
00557 
00558 //______________________________________________________________________________
00564 class Running: public bsc::state<Running, Enabled>,
00565                 public BaseState,
00566                 public toolbox::lang::Class {
00567 
00568 public:
00569 
00570         Running( my_context);
00571         virtual ~Running();
00572 
00573         // I2O message handling capability of state
00574         virtual bool discardDataEvent(MemRef_t* bufRef) const;
00575         virtual bool discardDqmEvent(MemRef_t* bufRef) const;
00576 
00577         // state-dependent actions
00578         virtual void do_stateNotify();
00579         virtual void do_stateAction() const;
00580         virtual int stateID() const {
00581                 return rb_statemachine::RUNNING;
00582         }
00583 
00584 private:
00585 
00586         virtual std::string do_stateName() const;
00587         virtual void do_entryActionWork();
00588         virtual void do_exitActionWork();
00589         virtual void do_moveToFailedState(xcept::Exception& exception) const;
00590 };
00591 
00592 //______________________________________________________________________________
00598 class Stopping: public bsc::state<Stopping, Ready>, public BaseState {
00599 
00600 public:
00601 
00602         typedef bsc::transition<StopDone, Stopped> SD;
00603         typedef boost::mpl::list<SD> reactions;
00604 
00605         Stopping( my_context);
00606         virtual ~Stopping();
00607 
00608         //I2O capability
00609         virtual bool discardDataEvent(MemRef_t* bufRef) const;
00610         virtual bool discardDqmEvent(MemRef_t* bufRef) const;
00611 
00612         // state-dependent actions
00613         virtual void do_stateNotify();
00614         virtual int stateID() const {
00615                 return rb_statemachine::STOPPING;
00616         }
00617         virtual void do_stateAction() const;
00618 
00619 private:
00620 
00621         void emergencyStop() const;
00622 
00623 private:
00624 
00625         virtual std::string do_stateName() const;
00626         virtual void do_entryActionWork();
00627         virtual void do_exitActionWork();
00628         virtual void do_moveToFailedState(xcept::Exception& exception) const;
00629 
00630         bool destructionIsDone() const;
00631 };
00632 
00633 //______________________________________________________________________________
00639 class Halting: public bsc::state<Halting, Normal>, public BaseState {
00640 
00641 public:
00642 
00643         typedef bsc::transition<HaltDone, Halted> HD;
00644         typedef boost::mpl::list<HD> reactions;
00645 
00646         Halting( my_context);
00647         virtual ~Halting();
00648 
00649         //I2O capability
00650         virtual bool discardDataEvent(MemRef_t* bufRef) const;
00651         virtual bool discardDqmEvent(MemRef_t* bufRef) const;
00652 
00653         // state-dependent actions
00654         virtual void do_stateNotify();
00655         virtual int stateID() const {
00656                 return rb_statemachine::HALTING;
00657         }
00658         virtual void do_stateAction() const;
00659 
00660 private:
00661 
00662         virtual std::string do_stateName() const;
00663         virtual void do_entryActionWork();
00664         virtual void do_exitActionWork();
00665         virtual void do_moveToFailedState(xcept::Exception& exception) const;
00666 
00667         bool destructionIsDone() const;
00668 
00669         void doAsync() const;
00670 
00671 };
00672 
00673 typedef boost::shared_ptr<RBStateMachine> RBStateMachinePtr;
00674 
00675 } // end namespace rb_statemachine
00676 
00677 } // end namespace evf
00678 
00679 #endif /* RBBOOSTSTATEMACHINE_H_ */