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

Last change on this file since 12009 was 11837, checked in by tbretz, 13 years ago
Changed Dim services to ensure they send the time.
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 "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.Update(str0+str1+doc+'\n');
115}
116
117// --------------------------------------------------------------------------
118//
119//! Overwrite StateMachineImp::SetCurrentState. In addition to
120//! calling StateMachineImo::SetCurrentState the new state is also
121//! distributed via the DimService STATE.
122//!
123//! For parameter description see StateMachineImp.
124//!
125string StateMachineDim::SetCurrentState(int state, const char *txt, const std::string &cmd)
126{
127 const string msg = StateMachineImp::SetCurrentState(state, txt, cmd);
128 if (msg.empty())
129 return "";
130
131 fSrvState.setQuality(state);
132 fSrvState.Update(msg);
133
134 return msg;
135}
136
137// --------------------------------------------------------------------------
138//
139//! In the case of dim this secures HandleEvent against dim's commandHandler
140//!
141void StateMachineDim::Lock()
142{
143 dim_lock();
144}
145
146// --------------------------------------------------------------------------
147//
148//! In the case of dim this secures HandleEvent against dim's commandHandler
149//!
150void StateMachineDim::UnLock()
151{
152 dim_unlock();
153}
154
155// --------------------------------------------------------------------------
156//
157//! Overwritten DimCommand::commandHandler()
158//!
159//! If fCurrentState is smaller than 0 or we are in kSM_FatalError state,
160//! all incoming commands are ignored.
161//!
162//! The commandHandler will go through the list of available commands
163//! (fListOfEventss). If the received command was recognized, it is added
164//! via PushCommand into the fifo.
165//!
166//! @todo
167//! - Fix the exit when cmd is not of type EventImp
168//! - Fix docu
169//! - Do we need a possibility to suppress a call to "HandleEvent"
170//! or is a state<0 enough?
171//
172void StateMachineDim::commandHandler()
173{
174 DimCommand *cmd = getCommand();
175 if (!cmd)
176 return;
177
178 const EventImp *evt = dynamic_cast<EventImp*>(cmd);
179
180 if (HasEvent(evt))
181 PostEvent(*evt);
182}
183
184// --------------------------------------------------------------------------
185//
186//! Overwrites MessageImp::Update. This redirects output issued via
187//! MessageImp to MessageDim object.
188//
189int StateMachineDim::Write(const Time &time, const string &txt, int qos)
190{
191 return DimLog::fLog.Write(time, txt, qos);
192}
193
194// --------------------------------------------------------------------------
195//
196//! exitHandler of the DimServer. The EXIT command is implemented by each
197//! DimServer automatically. exitHandler calls Stop(code) and exit(-1)
198//! in case the received exit-value is a special number (42). abort()
199//! is called if 0x42 is received.
200//!
201//! @param code
202//! value which is passed to Stop(code)
203//
204void StateMachineDim::exitHandler(int code)
205{
206 Out() << " -- " << Time().GetAsStr() << " - EXIT(" << code << ") command received." << endl;
207 if (code<0) // negative values reserved for internal use
208 {
209 Out() << " -- " << Time().GetAsStr() << ": ignored." << endl;
210 return;
211 }
212
213 Stop(code);
214 if (code==42)
215 exit(-1);
216 if (code==0x42)
217 abort();
218}
Note: See TracBrowser for help on using the repository browser.