source: trunk/FACT++/src/StateMachineDim.cc @ 10484

Last change on this file since 10484 was 10484, checked in by tbretz, 9 years ago
Exchanged the order of the STATE and the STATE_LIST for logical reasons.
File size: 7.2 KB
Line 
1// **************************************************************************
2/** @class StateMachineDim
3
4@brief Class for a state machine implementation within a DIM network
5
6This class implements a StateMachine within a Dim network. It redirects
7all output posted via MessageImp to a service called "NAME/MESSAGE"
8while name is the name of the machine given in the constructor. In
9addition two services are offered: NAME/STATE and NAME/VERSION.
10NAME/STATE propagates any state change to the netork.
11
12When constructing the Dim network is started and while dstruction it is
13stopped.
14
15@todo
16    Proper support for versioning
17
18*/
19// **************************************************************************
20#include "StateMachineDim.h"
21
22#include <boost/lexical_cast.hpp>
23
24#include "tools.h"
25
26#include "Time.h"
27#include "EventDim.h"
28
29using namespace std;
30using boost::lexical_cast;
31
32const int StateMachineDim::fVersion = 42;
33
34// --------------------------------------------------------------------------
35//
36//! The constrcutor first initialized DimStart with the given machine name.
37//! DimStart is just a wrapper which constructor calls DimServer::start()
38//! to ensure that initializing the Dim sub-system, is the first what is
39//! done.
40//!
41//! The second objet instantiated is the MessageDim class which offers
42//! the MESSAGE service used to broadcast logging messages to other
43//! Dim clients.
44//!
45//! After this the services STATE and VERSION are setup. STATE will
46//! be used to broadcast the state of the machine. Version broadcasts
47//! the global version number of the StateMachineDim implementation
48//!
49//! After redirecting the handler which handels dim's EXIT command
50//! to ourself (it will then call StateMachineDim::exitHandler) and
51//! adding human readable state names for the default states
52//! implemented by StateMachingImp the state is set to kSM_Initializing.
53//! Warning: The EXIT handler is global!
54//!
55//! @param name
56//!    The name with which the dim-services should be prefixed, e.g.
57//!    "DRIVE" will lead to "DRIVE/SERVICE". It is also propagated
58//!    to DimServer::start()
59//!
60//! @param out
61//!    A refrence to an ostream which allows to redirect the log-output
62//!    to something else than cout. The default is cout. The reference
63//!    is propagated to fLog
64//!
65//! @todo
66//!    - Shell the VERSION be set from the derived class?
67//
68StateMachineDim::StateMachineDim(ostream &out, const std::string &name)
69    : StateMachine(out, name), DimStart(name, *this), fLog(name, out),
70    fDescriptionStates((name+"/STATE_LIST").c_str(), const_cast<char*>(""),
71                       "Provides a list with descriptions for each service."
72                       "|StateList[string]:A \\n separated list of the form id:name=description"),
73    fSrvState((name+"/STATE").c_str(), const_cast<char*>(""),
74              "Provides the state of the state machine as quality of service."
75              "|Text[string]:A human readable string sent by the last state change.")
76    //    fSrvVersion((name+"/VERSION").c_str(), const_cast<int&>(fVersion)),
77{
78    // WARNING: This exit handler is GLOBAL!
79    DimServer::addExitHandler(this);
80    SetDefaultStateNames();
81}
82
83// --------------------------------------------------------------------------
84//
85//! Overwrite StateMachineImp::AddTransition to create a EventDim
86//! instead of an Event object. The event name propagated to the EventDim
87//! is fName+"/"+name.
88//!
89//! For parameter description see StateMachineImp.
90//!
91EventImp *StateMachineDim::CreateEvent(int targetstate, const char *name, const char *fmt)
92{
93    return new EventDim(targetstate, GetName()+"/"+name, fmt, this);
94}
95
96// --------------------------------------------------------------------------
97//
98//! Overwrite StateMachineImp::AddStateName. In addition to storing the
99//! state locally it is also propagated through Dim in the STATE_LIST
100//! service.
101//!
102//! @param state
103//!    Number of the state to which a name should be assigned
104//!
105//! @param name
106//!    A name which should be assigned to the state, e.g. "Tracking"
107//!
108//! @param doc
109//!    A explanatory text describing the state
110//!
111void StateMachineDim::AddStateName(const int state, const std::string &name, const std::string &doc)
112{
113    StateMachineImp::AddStateName(state, name, doc);
114
115    const string str0 = reinterpret_cast<char*>(fDescriptionStates.itsData);
116    const string str1 = lexical_cast<string>(state)+':'+name+'=';
117
118    if (str0.find(str1)!=string::npos)
119        return;
120
121    fDescriptionStates.setData(const_cast<char*>((str0+str1+doc+'\n').c_str()));
122    fDescriptionStates.updateService();
123}
124
125// --------------------------------------------------------------------------
126//
127//! Overwrite StateMachineImp::SetCurrentState. In addition to
128//! calling StateMachineImo::SetCurrentState the new state is also
129//! distributed via the DimService STATE.
130//!
131//! For parameter description see StateMachineImp.
132//!
133string StateMachineDim::SetCurrentState(int state, const char *txt, const std::string &cmd)
134{
135    const string msg = StateMachineImp::SetCurrentState(state, txt, cmd);
136    if (msg.empty())
137        return "";
138
139    fSrvState.setQuality(state);
140    fSrvState.setData(const_cast<char*>(msg.c_str()));
141    fSrvState.updateService();
142
143    return msg;
144}
145
146// --------------------------------------------------------------------------
147//
148//! Overwritten DimCommand::commandHandler()
149//!
150//! If fCurrentState is smaller than 0 or we are in kSM_FatalError state,
151//! all incoming commands are ignored.
152//!
153//! The commandHandler will go through the list of available commands
154//! (fListOfEventss). If the received command was recognized, it is added
155//! via PushCommand into the fifo.
156//!
157//! @todo
158//!    - Fix the exit when cmd is not of type EventImp
159//!    - Fix docu
160//!    - Do we need a possibility to suppress a call to "HandleEvent"
161//!      or is a state<0 enough?
162//
163void StateMachineDim::commandHandler()
164{
165    DimCommand *cmd = getCommand();
166    if (!cmd)
167        return;
168
169    const EventImp *evt = dynamic_cast<EventImp*>(cmd);
170
171    // FIXME: In the case of HandleEvent there is no need to copy the data
172    // FIMXE: Currentyl the time is not copied
173    // FIXME: Handle Event is not thread safe (Dim + Console)
174    if (HasEvent(evt))
175        PostEvent(*evt);
176}
177
178// --------------------------------------------------------------------------
179//
180//! Overwrites MessageImp::Update. This redirects output issued via
181//! MessageImp to MessageDim object.
182//
183int StateMachineDim::Write(const Time &time, const string &txt, int qos)
184{
185    return fLog.Write(time, txt, qos);
186}
187
188// --------------------------------------------------------------------------
189//
190//! exitHandler of the DimServer. The EXIT command is implemented by each
191//! DimServer automatically. exitHandler calls Stop(code) and exit(-1)
192//! in case the received exit-value is a special number (42). abort()
193//! is called if 0x42 is received.
194//!
195//! @param code
196//!    value which is passed to Stop(code)
197//
198void StateMachineDim::exitHandler(int code)
199{
200    Out() << " -- " << Time().GetAsStr() << ": EXIT(" << code << ") command received." << endl;
201    if (code<0) // negative values reserved for internal use
202    {
203        Out() << " -- " << Time().GetAsStr() << ": ignored." << endl;
204        return;
205    }
206
207    Stop(code);
208    if (code==42)
209        exit(-1);
210    if (code==0x42)
211        abort();
212}
Note: See TracBrowser for help on using the repository browser.