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

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