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

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