source: trunk/FACT++/src/Main.h@ 12105

Last change on this file since 12105 was 12087, checked in by tbretz, 13 years ago
Added the PrintHelp function which is supposed to print state and command informations of a state machine.
File size: 6.8 KB
Line 
1#ifndef FACT_MAIN
2#define FACT_MAIN
3
4#include <map>
5#include <thread>
6#include <functional>
7
8#include "LocalControl.h"
9#include "Configuration.h"
10
11namespace Main
12{
13 void SetupConfiguration(Configuration &conf)
14 {
15 const string n = conf.GetName()+".log";
16
17 po::options_description config("Program options");
18 config.add_options()
19 ("dns", var<string>("localhost"), "Dim nameserver (overwites DIM_DNS_NODE environment variable)")
20 ("host", var<string>(""), "Address with which the Dim nameserver can connect to this host (overwites DIM_HOST_NODE environment variable)")
21 ("log,l", var<string>(n), "Name of local log-file")
22 ("append-log", po_bool(), "Append log information to local log-file")
23 ("null", po_switch(), "Suppresses almost all console output - including errors (only available without --console option)")
24 ("console,c", var<int>(), "Use console (0=shell, 1=simple buffered, X=simple unbuffered)")
25 ("cmd", vars<string>(), "Execute one or more commands at startup")
26 ("exec,e", vars<string>(), "Execute one or more scrips at startup")
27 ("quit", po_switch(), "Quit after startup");
28 ;
29
30 conf.AddEnv("dns", "DIM_DNS_NODE");
31 conf.AddEnv("host", "DIM_HOST_NODE");
32
33 conf.AddOptions(config);
34 }
35
36 template<class T>
37 void PrintHelp()
38 {
39 Dim::Setup();
40
41 ofstream fout("/dev/null");
42
43 T io_service(fout);
44
45 io_service.PrintListOfStates(cout);
46 cout << "\nList of available commands:\n\n";
47 io_service.PrintListOfEvents(cout);
48 cout << "\n";
49 }
50
51 void Thread(StateMachineImp *io_service, bool dummy)
52 {
53 // This is necessary so that the StateMachien Thread can signal the
54 // Readline to exit
55 io_service->Run(dummy);
56 Readline::Stop();
57 }
58
59 template<class T, class S>
60 int execute(Configuration &conf, bool dummy=false)
61 {
62 Dim::Setup(conf.Get<string>("dns"), conf.Get<string>("host"));
63
64 // -----------------------------------------------------------------
65
66 static T shell(conf.GetName().c_str(),
67 conf.Has("console") ? conf.Get<int>("console")!=1 : conf.Get<bool>("null"));
68
69 WindowLog &win = shell.GetStreamIn();
70 WindowLog &wout = shell.GetStreamOut();
71
72 // Switching off buffering is not strictly necessary, since
73 // the destructor of shell should flush everything still buffered,
74 // nevertheless it helps to debug problems in the initialization
75 // sequence.
76 const bool backlog = wout.GetBacklog();
77 const bool null = wout.GetNullOutput();
78 if (conf.Has("console") || !conf.Get<bool>("null"))
79 {
80 wout.SetBacklog(false);
81 wout.SetNullOutput(false);
82 wout.Display(true);
83 }
84
85 if (conf.Has("log"))
86 if (!wout.OpenLogFile(conf.Get<string>("log"), conf.Get<bool>("append-log")))
87 win << kRed << "ERROR - Couldn't open log-file " << conf.Get<string>("log") << ": " << strerror(errno) << endl;
88
89 S io_service(wout);
90
91 const boost::filesystem::path path(conf.GetName());
92
93 const string pname = path.parent_path().string();
94 const string fname = path.filename();
95
96 const Time now;
97 io_service.Write(now, "/----------------------- Program ------------------------");
98 io_service.Write(now, "| Program: "PACKAGE_STRING" ("+fname+")");
99 io_service.Write(now, "| CallPath: "+pname);
100 io_service.Write(now, "| Compiled: "__DATE__" "__TIME__);
101 io_service.Write(now, "| Revision: "REVISION);
102 io_service.Write(now, "| Contact: "PACKAGE_BUGREPORT);
103 io_service.Write(now, "| URL: "PACKAGE_URL);
104 io_service.Write(now, "| Start: "+now.GetAsStr("%c"));
105 io_service.Write(now, "\\----------------------- Options ------------------------");
106 const multimap<string,string> mmap = conf.GetOptions();
107 for (multimap<string,string>::const_iterator it=mmap.begin(); it!=mmap.end(); it++)
108 io_service.Write(now, ": "+it->first+(it->second.empty()?"":" = ")+it->second);
109 io_service.Write(now, "\\------------------- Evaluating options -----------------");
110 const int rc = io_service.EvalOptions(conf);
111 if (rc>=0)
112 {
113 ostringstream str;
114 str << "Exit triggered by EvalOptions with rc=" << rc;
115 io_service.Write(now, str.str(), MessageImp::kError);
116 return rc;
117 }
118
119 const map<string,string> &wco = conf.GetWildcardOptions();
120 if (wco.size()>0)
121 {
122 io_service.Write(now, "------------- Unrecognized wildcard options -------------", MessageImp::kWarn);
123
124 size_t max = 0;
125 for (map<string,string>::const_iterator it=wco.begin(); it!=wco.end(); it++)
126 if (it->second.length()>max)
127 max = it->second.length();
128
129 for (map<string,string>::const_iterator it=wco.begin(); it!=wco.end(); it++)
130 {
131 ostringstream str;
132 str.setf(ios_base::left);
133 str << setw(max+1) << it->second << " : " << it->first;
134 io_service.Write(now, str.str(), MessageImp::kWarn);
135 }
136 io_service.Write(now, "Unrecognized options found, will exit with rc=127", MessageImp::kError);
137 return 127;
138 }
139
140 io_service.Message("==================== Starting main loop =================");
141
142 if (conf.Has("console") || !conf.Get<bool>("null"))
143 {
144 wout.SetNullOutput(null);
145 wout.SetBacklog(backlog);
146 }
147
148 shell.SetReceiver(io_service);
149
150 // boost::thread t(boost::bind(&AutoScheduler<S>::Run, &io_service));
151 thread t(bind(Main::Thread, &io_service, dummy));
152
153 const vector<string> v1 = conf.Vec<string>("cmd");
154 for (vector<string>::const_iterator it=v1.begin(); it!=v1.end(); it++)
155 shell.ProcessLine(*it);
156
157 const vector<string> v2 = conf.Vec<string>("exec");
158 for (vector<string>::const_iterator it=v2.begin(); it!=v2.end(); it++)
159 shell.Execute(*it);
160
161 if (conf.Get<bool>("quit"))
162 shell.Stop();
163
164 shell.Run(); // Run the shell
165 io_service.Stop(); // Signal Loop-thread to stop
166 // io_service.Close(); // Obsolete, done by the destructor
167 // wout << "join: " << t.timed_join(boost::posix_time::milliseconds(0)) << endl;
168
169 // Wait until the StateMachine has finished its thread
170 // before returning and destroying the dim objects which might
171 // still be in use.
172 t.join();
173
174 return 0;
175 }
176}
177
178#endif
Note: See TracBrowser for help on using the repository browser.