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

Last change on this file since 10365 was 10183, checked in by tbretz, 10 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.