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

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