source: trunk/FACT++/src/DimState.h@ 14974

Last change on this file since 14974 was 14552, checked in by tbretz, 12 years ago
Make sure that one server is never subscribed twice.
File size: 10.4 KB
Line 
1#ifndef FACT_DimState
2#define FACT_DimState
3
4#include <set>
5#include <string>
6#include <functional>
7
8#include "State.h"
9#include "EventImp.h"
10#include "WindowLog.h"
11#include "Description.h"
12#include "StateMachineImp.h"
13#include<iostream>
14class DimState
15{
16public:
17 enum
18 {
19 kOffline = -256,
20 kNotAvailable = -257,
21 };
22
23protected:
24 typedef std::function<int(const EventImp &)> callback;
25
26 callback fCallback;
27
28 void HandlerImp(const EventImp &evt)
29 {
30 const bool disconnected = evt.GetSize()==0;
31
32 last = cur;
33 cur = std::make_pair(evt.GetTime(), disconnected ? kOffline : evt.GetQoS());
34
35 msg = disconnected ? "" : evt.GetString();
36 }
37
38 int Callback(const EventImp &evt)
39 {
40 return fCallback ? fCallback(evt) : StateMachineImp::kSM_KeepState;
41 }
42
43 virtual int Handler(const EventImp &evt)
44 {
45 HandlerImp(evt);
46 return Callback(evt);
47 }
48
49public:
50 DimState() { }
51 DimState(const std::string &n, const std::string s="STATE") : server(n),
52 service(n+"/"+s),
53 last(std::make_pair(Time(), kOffline)), cur(std::make_pair(Time(), kOffline))
54 {
55 }
56 virtual ~DimState()
57 {
58 }
59
60 /*const*/ std::string server;
61 /*const*/ std::string service;
62
63 std::pair<Time, int32_t> last;
64 std::pair<Time, int32_t> cur;
65 std::string msg;
66
67 virtual void Subscribe(StateMachineImp &imp)
68 {
69 imp.Subscribe(service)
70 (imp.Wrap(std::bind(&DimState::Handler, this, std::placeholders::_1)));
71 }
72
73 void SetCallback(const callback &cb)
74 {
75 fCallback = cb;
76 }
77
78 const Time &time() const { return cur.first; }
79 const int32_t &state() const { return cur.second; }
80
81 bool online() const { return state()>kOffline; }
82
83 virtual State description() const { return State(kNotAvailable, ""); }
84};
85
86inline std::ostream &operator<<(std::ostream& out, const DimState &s)
87{
88 const State rc = s.description();
89
90 out << s.time().GetAsStr("%H:%M:%S.%f").substr(0, 12) << " - ";
91 out << kBold << s.server;
92
93 if (s.state()==DimState::kOffline)
94 return out << ": Offline";
95
96 if (rc.index==DimState::kNotAvailable)
97 return out;
98
99 out << ": ";
100
101// if (rc.index==-2)
102// out << s.state();
103// else
104 out << rc.name << "[" << rc.index << "]";
105
106 if (!rc.comment.empty())
107 out << " - " << kBlue << rc.comment;
108
109 return out;
110}
111
112
113class DimDescribedState : public DimState
114{
115 typedef std::function<void()> callback_desc;
116
117 callback_desc fCallbackStates;
118
119 virtual void CallbackStates()
120 {
121 if (fCallbackStates)
122 fCallbackStates();
123 }
124
125
126public:
127 DimDescribedState(const std::string &n) : DimState(n)
128 {
129 }
130
131 std::vector<State> states;
132
133 virtual void Subscribe(StateMachineImp &imp)
134 {
135 imp.Subscribe(server+"/STATE_LIST")
136 (imp.Wrap(std::bind(&DimDescribedState::HandleDesc, this, std::placeholders::_1)));
137
138 DimState::Subscribe(imp);
139 }
140
141 void SetCallbackStates(const callback_desc &cb)
142 {
143 fCallbackStates = cb;
144 }
145
146 int HandleDesc(const EventImp &evt)
147 {
148 if (evt.GetSize()>0)
149 {
150 states = State::SplitStates(evt.GetString());
151 states.push_back(State(kOffline, "Offline"));
152
153 CallbackStates();
154 }
155
156 return StateMachineImp::kSM_KeepState;
157 }
158
159 State description() const
160 {
161 for (auto it=states.begin(); it!=states.end(); it++)
162 if (it->index==state())
163 return State(it->index, it->name, it->comment, time());
164
165 return State(kNotAvailable, "n/a");
166 }
167};
168
169class DimDescriptions : public DimDescribedState
170{
171 typedef std::function<void()> callback_desc;
172
173 callback_desc fCallbackDescriptions;
174
175 virtual void CallbackDescriptions()
176 {
177 if (fCallbackDescriptions)
178 fCallbackDescriptions();
179 }
180
181public:
182 DimDescriptions(const std::string &n) : DimDescribedState(n)
183 {
184 }
185
186 std::vector<std::vector<Description>> descriptions;
187
188 virtual void Subscribe(StateMachineImp &imp)
189 {
190 imp.Subscribe(server+"/SERVICE_DESC")
191 (imp.Wrap(std::bind(&DimDescriptions::HandleServiceDesc, this, std::placeholders::_1)));
192
193 DimDescribedState::Subscribe(imp);
194 }
195
196 void SetCallbackDescriptions(const callback_desc &cb)
197 {
198 fCallbackDescriptions = cb;
199 }
200
201
202 int HandleServiceDesc(const EventImp &evt)
203 {
204 descriptions.clear();
205 if (evt.GetSize()>0)
206 {
207 std::string buf;
208 std::stringstream stream(evt.GetString());
209 while (getline(stream, buf, '\n'))
210 descriptions.push_back(Description::SplitDescription(buf));
211 }
212
213 CallbackDescriptions();
214
215 return StateMachineImp::kSM_KeepState;
216 }
217};
218
219class DimVersion : public DimState
220{
221 int Handler(const EventImp &evt)
222 {
223 HandlerImp(evt);
224
225 cur.second = evt.GetSize()==4 ? evt.GetInt() : kOffline;
226 if (cur.second==0)
227 cur.second=kOffline;
228
229 return Callback(evt);
230 }
231
232public:
233 DimVersion() : DimState("DIS_DNS", "VERSION_NUMBER") { }
234
235 std::string version() const
236 {
237 if (!online())
238 return "Offline";
239
240 std::ostringstream out;
241 out << "V" << state()/100 << 'r' << state()%100;
242 return out.str();
243 }
244
245 State description() const
246 {
247 return State(state(), version(), "", time());
248 }
249};
250
251class DimControl : public DimState
252{
253 std::map<std::string, callback> fCallbacks;
254
255 int Handler(const EventImp &evt)
256 {
257 HandlerImp(evt);
258
259 shortmsg = msg;
260 file = "";
261 scriptdepth = -1;
262
263 // Find begining of descriptor
264 const size_t p0 = msg.find_first_of(' ');
265 if (p0==std::string::npos)
266 return StateMachineImp::kSM_KeepState;
267
268 // Find begining of filename
269 const size_t p1 = msg.find_first_of(':');
270 if (p1==std::string::npos)
271 return StateMachineImp::kSM_KeepState;
272
273 // Find end of filename
274 const size_t p2 = msg.find_last_of('[');
275 if (p2==std::string::npos)
276 return StateMachineImp::kSM_KeepState;
277
278 scriptdepth = atoi(msg.c_str()+p0+1);
279 file = msg.substr(p1+1, p2-p1-1);
280
281 shortmsg.insert(0, msg.substr(p0+1, p1-p0));
282 shortmsg.erase(p1+1,p2-p0-1);
283
284 const int rc = Callback(evt);
285
286 const auto func = fCallbacks.find(file);
287 if (func==fCallbacks.end())
288 return rc;
289
290 // Call callback
291 return func->second(evt);
292 }
293
294
295public:
296 DimControl() : DimState("DIM_CONTROL") { }
297
298 std::string file;
299 std::string shortmsg;
300 int scriptdepth;
301
302 void AddCallback(const std::string &script, const callback &cb)
303 {
304 fCallbacks[script] = cb;
305 }
306
307 State description() const
308 {
309 return State(state(), "Current label", "", time());
310 }
311};
312
313class DimDnsServerList
314{
315protected:
316 typedef std::function<void(const std::string &)> callback_srv;
317 typedef std::function<void(const EventImp &)> callback_evt;
318
319 callback_srv fCallbackServerAdd;
320 callback_srv fCallbackServerRemove;
321 callback_evt fCallbackServerEvent;
322
323 std::set<std::string> fServerList;
324
325 void HandlerServerImp(const EventImp &evt);
326
327 virtual void CallbackServerAdd(const std::string &str)
328 {
329 if (fCallbackServerAdd)
330 fCallbackServerAdd(str);
331 }
332 virtual void CallbackServerRemove(const std::string &str)
333 {
334 if (fCallbackServerRemove)
335 fCallbackServerRemove(str);
336 }
337 virtual void CallbackServerEvent(const EventImp &evt)
338 {
339 if (fCallbackServerEvent)
340 fCallbackServerEvent(evt);
341 }
342 virtual int HandlerServer(const EventImp &evt)
343 {
344 HandlerServerImp(evt);
345 CallbackServerEvent(evt);
346
347 return StateMachineImp::kSM_KeepState;
348 }
349
350public:
351 DimDnsServerList()
352 {
353 }
354 virtual ~DimDnsServerList()
355 {
356 }
357
358 Time time;
359 std::string msg;
360
361 virtual void Subscribe(StateMachineImp &imp)
362 {
363 imp.Subscribe("DIS_DNS/SERVER_LIST")
364 (imp.Wrap(std::bind(&DimDnsServerList::HandlerServer, this, std::placeholders::_1)));
365 }
366
367 void SetCallbackServerAdd(const callback_srv &cb)
368 {
369 fCallbackServerAdd = cb;
370 }
371
372 void SetCallbackServerRemove(const callback_srv &cb)
373 {
374 fCallbackServerRemove = cb;
375 }
376
377 void SetCallbackServerEvent(const callback_evt &cb)
378 {
379 fCallbackServerEvent = cb;
380 }
381
382 //const Time &time() const { return time; }
383 //const std::string &msg() const { return msg; }
384};
385
386struct Service
387{
388 std::string name;
389 std::string server;
390 std::string service;
391 std::string format;
392 bool iscmd;
393};
394
395inline bool operator<(const Service& left, const Service& right)
396{
397 return left.name < right.name;
398}
399
400class DimDnsServiceList : public DimDnsServerList
401{
402 StateMachineImp *fStateMachine;
403
404 typedef std::function<void(const Service &)> callback_svc;
405
406 callback_svc fCallbackServiceAdd;
407 //callback_evt fCallbackServiceEvt;
408
409 std::vector<std::string> fServiceList;
410
411 std::set<std::string> fServers;
412
413 void CallbackServerAdd(const std::string &server)
414 {
415 DimDnsServerList::CallbackServerAdd(server);
416
417 if (fServers.find(server)!=fServers.end())
418 return;
419
420 fStateMachine->Subscribe(server+"/SERVICE_LIST")
421 (fStateMachine->Wrap(std::bind(&DimDnsServiceList::HandlerServiceList, this, std::placeholders::_1)));
422
423 fServers.insert(server);
424 }
425
426 void HandlerServiceListImp(const EventImp &evt);
427
428/*
429 virtual void CallbackServiceEvt(const EventImp &evt)
430 {
431 if (fCallbackServiceEvt)
432 fCallbackServiceEvt(evt);
433 }
434*/
435 virtual int HandlerServiceList(const EventImp &evt)
436 {
437 HandlerServiceListImp(evt);
438 //CallbackServiceEvent(evt);
439
440 return StateMachineImp::kSM_KeepState;
441 }
442
443
444 virtual void CallbackServiceAdd(const Service &service)
445 {
446 if (fCallbackServiceAdd)
447 fCallbackServiceAdd(service);
448 }
449
450public:
451 DimDnsServiceList() : fStateMachine(0)
452 {
453 }
454
455 void Subscribe(StateMachineImp &imp)
456 {
457 fStateMachine = &imp;
458 DimDnsServerList::Subscribe(imp);
459 }
460
461 void SetCallbackServiceAdd(const callback_svc &cb)
462 {
463 fCallbackServiceAdd = cb;
464 }
465/*
466 void SetCallbackServiceEvt(const callback_svc &cb)
467 {
468 fCallbackServiceEvt = cb;
469 }
470*/
471};
472
473#endif
Note: See TracBrowser for help on using the repository browser.