source: trunk/FACT++/src/sched.cc@ 10395

Last change on this file since 10395 was 10183, checked in by tbretz, 14 years ago
New import.
File size: 10.0 KB
Line 
1//
2// chat_client.cpp
3// ~~~~~~~~~~~~~~~
4//
5// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
6//
7// Distributed under the Boost Software License, Version 1.0. (See accompanying
8// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9//
10
11#include <iostream>
12#include <deque>
13#include <boost/filesystem.hpp>
14#include <boost/thread.hpp>
15#include <boost/asio.hpp>
16#include <boost/bind.hpp>
17#include <boost/lexical_cast.hpp>
18#include <boost/asio/deadline_timer.hpp>
19#include <boost/date_time/posix_time/posix_time.hpp>
20
21#include "StateMachineDim.h"
22#include "Configuration.h"
23
24#include "StateMachineConsole.h"
25#include "Shell.h"
26
27namespace ba = boost::asio;
28namespace bs = boost::system;
29namespace fs = boost::filesystem;
30namespace dummy = ba::placeholders;
31
32using boost::lexical_cast;
33using ba::deadline_timer;
34using ba::ip::tcp;
35
36using namespace std;
37
38#include "MessageDim.h"
39#include "Connection.h"
40#include "Time.h"
41#include "Event.h"
42#include "WindowLog.h"
43
44#include "tools.h" // CheckDim
45
46
47// ------------------------------------------------------------------------
48
49template <class T>
50class LocalTemplate : public T
51{
52public:
53 StateMachine *fImp;
54 string fName;
55
56 ostream &wout;
57
58 LocalTemplate(const char *name, ostream &out) : T(name), fImp(0),
59 fName(fs::path(name).filename()), wout(out) { }
60
61 void SetCommands(StateMachineConsole &imp)
62 {
63 fImp = &imp;
64 }
65
66 char *Complete(const char *text, int state)
67 {
68 static vector<EventImp*>::const_iterator pos;
69 if (state==0)
70 pos = fImp->GetListOfEvents().begin();
71
72 while (pos!=fImp->GetListOfEvents().end())
73 {
74 char *rc = Readline::Compare((*(pos++))->GetName(), text);
75 if (rc)
76 return rc;
77 }
78 return 0;
79 }
80
81 //bool PrintGeneralHelp()
82 //bool PrintKeyBindings()
83 bool PrintCommands()
84 {
85 wout << endl << kBold << "List of commands:" << endl;
86 fImp->PrintListOfEvents(wout);
87 wout << endl;
88
89 return true;
90 }
91
92 bool Process(const std::string &str)
93 {
94 if (T::Process(str))
95 return true;
96
97 if (str=="test")
98 {
99 wout << "Test" << endl;
100 return false;
101 }
102
103 Event evt(str);
104 evt.SetInt(7);
105
106 if (!fImp->ProcessCommand(evt))
107 {
108 wout << kRed << "Unknown command '" << str << "' " << kReset << " (type l for a list of commands)." << endl;
109 return true;
110 }
111
112 return false;
113 }
114};
115
116class LocalShell : public LocalTemplate<Shell>
117{
118public:
119 LocalShell(const char *name, bool = false) : LocalTemplate<Shell>(name, win) { }
120
121 string GetUpdatePrompt() const
122 {
123 int s = Shell::wout.GetSizeBacklog()/1000;
124 char u = 'k';
125 if (s>999)
126 {
127 s/=1000;
128 u = 'M';
129 }
130 return Form("[%d:%d%c] %s:%s> ", GetLine(), s, u, fName.c_str(),
131 fImp->GetStateName().c_str());
132 }
133
134 void Run(const char * = 0)
135 {
136 win << kBlue << kBold << "You are on the " << fName << " terminal of the MCP -" << endl;
137 win << kBlue << kBold << "the Master Control Program." << endl;
138 win << endl;
139 win << kBlue << kBold << "Hello Flynn..." << endl;
140 win << endl;
141
142 Shell::Run();
143 }
144};
145
146class LocalConsole : public LocalTemplate<Readline>
147{
148 WindowLog fLog;
149
150 bool fContinous;
151
152public:
153 LocalConsole(const char *name, bool continous=false)
154 : LocalTemplate<Readline>(name, fLog), fContinous(continous)
155 {
156 fLog.SetNullOutput();
157 }
158
159 string GetUpdatePrompt() const
160 {
161
162 if (fContinous)
163 return Form("\n[%d] \033[34m%s\033[0m:\033[32m\033[1m%s\033[0m> ",
164 GetLine(), fName.c_str(), fImp->GetStateName().c_str());
165
166
167 int s = fLog.GetSizeBacklog()/1000;
168 char u = 'k';
169 if (s>999)
170 {
171 s/=1000;
172 u = 'M';
173 }
174 return Form("\n[%d:%d%c] \033[34m%s\033[0m:\033[32m\033[1m%s\033[0m> ",
175 GetLine(), s, u, fName.c_str(), fImp->GetStateName().c_str());
176 }
177
178 WindowLog &GetStreamOut() { return fLog; }
179 WindowLog &GetStreamIn() { return fLog; }
180
181 void EventHook()
182 {
183 if (fContinous)
184 {
185 if (fLog.GetSizeBacklog()>0)
186 cout << "\r";
187 fLog.Display(true);
188 }
189 Readline::EventHook();
190 }
191
192 void Shutdown(const char * =0)
193 {
194 fLog.Display(true);
195 cout << endl;
196 }
197
198 void Run(const char * = 0)
199 {
200 cout << endl;
201 cout << "\033[34mYou are on the " << fName << " terminal of the MCP -" << endl;
202 cout << "the Master Control Program." << endl;
203 cout << endl;
204 cout << "Hello Flynn...\033[0m" << endl;
205 cout << endl;
206
207 Shutdown();
208
209 Readline::Run();
210
211 fLog.Display();
212 fLog.SetNullOutput(false);
213 fLog.SetBacklog(false);
214 }
215};
216
217// =========================================================================
218
219template <class T>
220class AutoScheduler : public T
221{
222 bool fNextIsPreview;
223public:
224 enum states_t
225 {
226 kSM_Scheduling=1,
227 kSM_Comitting,
228 };
229
230 int fSessionId;
231
232 int Schedule()
233 {
234 stringstream str;
235 str << "Scheduling started -> Preview (id=" << fSessionId << ")";
236 T::Message(str);
237
238 usleep(3000000);
239 T::Message("Scheduling done.");
240
241 fSessionId = -1;
242
243 bool error = false;
244 return error ? T::kSM_Error : T::kSM_Ready;
245 }
246
247 int Commit()
248 {
249 stringstream str;
250 str << "Comitting preview (id=" << fSessionId << ")";
251 T::Message(str);
252
253 usleep(3000000);
254 T::Message("Comitted.");
255
256 fSessionId = -1;
257
258 bool error = false;
259 return error ? T::kSM_Error : T::kSM_Ready;
260 }
261
262 AutoScheduler(ostream &out=cout) : T(out, "SCHEDULER"), fNextIsPreview(true), fSessionId(-1)
263 {
264 AddStateName(kSM_Scheduling, "Scheduling");
265 AddStateName(kSM_Comitting, "Comitting");
266
267 AddTransition(kSM_Scheduling, "SCHEDULE", T::kSM_Ready);
268 AddTransition(kSM_Comitting, "COMMIT", T::kSM_Ready);
269
270 T::PrintListOfEvents();
271 }
272
273 int Execute()
274 {
275 switch (T::GetCurrentState())
276 {
277 case kSM_Scheduling:
278 return Schedule();
279 case kSM_Comitting:
280 return Commit();
281 }
282 return T::GetCurrentState();
283 }
284
285 int Transition(const Event &evt)
286 {
287 switch (evt.GetTargetState())
288 {
289 case kSM_Scheduling:
290 case kSM_Comitting:
291 fSessionId = evt.GetInt();
292 break;
293 }
294
295 return evt.GetTargetState();
296 }
297 int Configure(const Event &)
298 {
299 return T::GetCurrentState();
300 }
301};
302
303// ------------------------------------------------------------------------
304
305int RunDim(const char *prgname)
306{
307 if (!CheckDim())
308 return -1;
309
310 WindowLog wout;
311 if (!wout.OpenLogFile(string(prgname)+".log"))
312 wout << kRed << "ERROR - Couldn't open log-file: " << strerror(errno) << endl;
313
314 // Start io_service.Run to use the StateMachineImp::Run() loop
315 // Start io_service.run to only use the commandHandler command detaching
316 AutoScheduler<StateMachineDim> io_service(wout);
317 io_service.Run();
318
319 return 0;
320}
321
322template<class T>
323int RunShell(const char *prgname, bool cont=false)
324{
325 static T shell(prgname, cont);
326
327 WindowLog &win = shell.GetStreamIn();
328 WindowLog &wout = shell.GetStreamOut();
329
330 if (!wout.OpenLogFile(string(prgname)+".log"))
331 win << kRed << "ERROR - Couldn't open log-file: " << strerror(errno) << endl;
332
333 AutoScheduler<StateMachineConsole> io_service(wout);
334 shell.SetCommands(io_service);
335
336 boost::thread t(boost::bind(&AutoScheduler<StateMachineConsole>::Run, &io_service));
337
338 shell.Run(); // Run the shell
339 io_service.Stop(); // Signal Loop-thread to stop
340 // io_service.Close(); // Obsolete, done by the destructor
341 t.join();
342
343 return 0;
344}
345
346void SetupConfiguration(Configuration &conf)
347{
348 po::options_description config("Configuration");
349 config.add_options()
350 ("console,c", po_int(), "Use console (0=shell, 1=simple buffered, X=simple unbuffered)")
351 ;
352
353 conf.AddOptionsCommandline(config);
354}
355
356int main(int argc, char* argv[])
357{
358 Configuration conf(argv[0]);
359 SetupConfiguration(conf);
360
361 po::variables_map vm;
362 try
363 {
364 vm = conf.Parse(argc, argv);
365 }
366 catch (std::exception &e)
367 {
368 po::multiple_occurrences *MO = dynamic_cast<po::multiple_occurrences*>(&e);
369 if (MO)
370 cout << "Error: " << e.what() << " of '" << MO->get_option_name() << "' option." << endl;
371 else
372 cout << "Error: " << e.what() << endl;
373 cout << endl;
374
375 return -1;
376 }
377
378 if (conf.HasHelp() || conf.HasPrint())
379 return -1;
380
381 const bool dim = !conf.Has("console");
382 try
383 {
384 if (dim)
385 return RunDim(argv[0]);
386 else
387 if (conf.GetInt("console")==0)
388 return RunShell<LocalShell>(argv[0]);
389 else
390 return RunShell<LocalConsole>(argv[0], conf.GetInt("console")!=1);
391
392 // Now shutdown everything....
393 // io_service.Close(); // Is this needed at all?
394 // io_service.Run();
395
396 }
397 catch (std::exception& e)
398 {
399 std::cerr << "Exception: " << e.what() << "\n";
400 }
401
402 return 0;
403}
404
405/*
406class FADctrlDim : public StateMachineFAD<StateMachineDim>
407{
408public:
409FADctrlDim(const std::string &name="DATA_LOGGER", std::ostream &out=std::cout)
410: StateMachineFAD<StateMachineDim>(out, name) { }
411};
412
413 class FADctrlLocalShell : public StateMachineFAD<StateMachineConsole>
414{
415public:
416 ostream &win;
417
418 FADctrlLocalShell(std::ostream &out, std::ostream &out2)
419 : StateMachineFAD<StateMachineConsole>(out), win(out2) { }
420
421 FADctrlLocalShell(std::ostream &out=std::cout)
422 : StateMachineFAD<StateMachineConsole>(out), win(out) { }
423
424};
425*/
Note: See TracBrowser for help on using the repository browser.