source: trunk/FACT++/src/timecheck.cc@ 13995

Last change on this file since 13995 was 13991, checked in by tbretz, 13 years ago
Exchanged the number of the states.
File size: 6.0 KB
Line 
1#include "StateMachineDim.h"
2
3#include "tools.h"
4#include "Time.h"
5#include "Configuration.h"
6#include "LocalControl.h"
7
8using namespace std;
9
10// ------------------------------------------------------------------------
11
12#include "DimDescriptionService.h"
13
14// ========================================================================
15// ========================================================================
16// ========================================================================
17
18class StateMachineTimeCheck : public StateMachineDim
19{
20private:
21 Time fLastUpdate;
22
23 string fServer;
24 uint16_t fInterval;
25
26 DimDescribedService fService;
27
28 enum
29 {
30 kStateOutOfRange = 1
31 kStateRunning = 2,
32 };
33
34 // ------------- Initialize variables before the Dim stuff ------------
35
36 int Execute()
37 {
38 Time now;
39 if (now-fLastUpdate<boost::posix_time::minutes(fInterval))
40 return kStateRunning;
41
42 fLastUpdate=now;
43
44 const string cmd = "ntpdate -q "+fServer;
45
46 Info("Calling '"+cmd+"'");
47
48 FILE *pipe = popen(cmd.c_str(), "r");
49 if (!pipe)
50 {
51 const string err = strerror(errno);
52 Error("Could not create pipe '"+cmd+"': "+err);
53 return 0x100;
54 }
55
56 vector<string> args;
57
58 string line;
59 while (1)
60 {
61 const int rc = fgetc(pipe);
62 if (rc==EOF || rc=='\n')
63 {
64 args.push_back(Tools::Trim(line));
65 break;
66 }
67
68 if (rc==',')
69 {
70 args.push_back(Tools::Trim(line));
71 line = "";
72 continue;
73 }
74
75 line += static_cast<unsigned char>(rc);
76 }
77 pclose(pipe);
78
79 if (args.size()!=4)
80 {
81 Error("First returned line contains other than four arguments (separated by commas)");
82 return 0x100;
83 }
84
85 if (args[2].substr(0, 7)!="offset ")
86 {
87 Error("Argument 3 '"+args[2]+"' is not what it ought to be.");
88 return 0x100;
89 }
90
91 try
92 {
93 const float offset = stof(args[2].substr(7));
94 fService.Update(offset);
95
96 const string msg = "NTP: "+fServer+" returned: "+args[2]+" ms";
97
98 if (offset>=1000)
99 {
100 Warn(msg);
101 return kStateOutOfRange;
102 }
103
104 Message(msg);
105
106 }
107 catch (const exception &e)
108 {
109 Error("Converting offset '"+args[2]+"' to float failed: "+e.what());
110 return 0x100;
111 }
112
113 return kStateRunning;
114 }
115
116 int Trigger()
117 {
118 fLastUpdate = Time()-boost::posix_time::minutes(fInterval);
119 return GetCurrentState();
120 }
121
122public:
123 StateMachineTimeCheck(ostream &out=cout) : StateMachineDim(out, "TIME_CHECK"),
124 fService("OFFSET", "F:1", "Time offset measured with ntp|offset[ms]:Time offset in milliseconds")
125 {
126 // State names
127 AddStateName(kStateRunning, "Valid", "Last check was valid.");
128 AddStateName(kStateOutOfRange, "OutOfRange", "Last time check exceeded 1s.");
129
130 AddEvent("TRIGGER");
131 (bind(&StateMachineTimeCheck::Trigger, this))
132 ("Trigger update");
133
134 }
135 int EvalOptions(Configuration &conf)
136 {
137 fServer = conf.Get<string>("ntp-server");
138 fInterval = conf.Get<uint16_t>("interval");
139 if (fInterval==0)
140 fInterval=1;
141
142 Trigger();
143
144 return -1;
145 }
146};
147
148// ------------------------------------------------------------------------
149
150#include "Main.h"
151
152template<class T>
153int RunShell(Configuration &conf)
154{
155 return Main::execute<T, StateMachineTimeCheck>(conf);
156}
157
158void SetupConfiguration(Configuration &conf)
159{
160 po::options_description control("Time check");
161 control.add_options()
162 ("ntp-server", var<string>("hora.roa.es"), "The ntp server to be queried")
163 ("interval", var<uint16_t>(15), "Interval in minutes the ntp server should be queried")
164 ;
165
166 conf.AddOptions(control);
167}
168
169/*
170 Extract usage clause(s) [if any] for SYNOPSIS.
171 Translators: "Usage" and "or" here are patterns (regular expressions) which
172 are used to match the usage synopsis in program output. An example from cp
173 (GNU coreutils) which contains both strings:
174 Usage: cp [OPTION]... [-T] SOURCE DEST
175 or: cp [OPTION]... SOURCE... DIRECTORY
176 or: cp [OPTION]... -t DIRECTORY SOURCE...
177 */
178void PrintUsage()
179{
180 /*
181 cout <<
182 "SmartFACT is a tool writing the files needed for the SmartFACT web interface.\n"
183 "\n"
184 "The default is that the program is started without user intercation. "
185 "All actions are supposed to arrive as DimCommands. Using the -c "
186 "option, a local shell can be initialized. With h or help a short "
187 "help message about the usuage can be brought to the screen.\n"
188 "\n"
189 "Usage: smartfact [-c type] [OPTIONS]\n"
190 " or: smartfact [OPTIONS]\n";
191 cout << endl;*/
192}
193
194void PrintHelp()
195{
196 Main::PrintHelp<StateMachineTimeCheck>();
197
198 /* Additional help text which is printed after the configuration
199 options goes here */
200
201 /*
202 cout << "bla bla bla" << endl << endl;
203 cout << endl;
204 cout << "Environment:" << endl;
205 cout << "environment" << endl;
206 cout << endl;
207 cout << "Examples:" << endl;
208 cout << "test exam" << endl;
209 cout << endl;
210 cout << "Files:" << endl;
211 cout << "files" << endl;
212 cout << endl;
213 */
214}
215
216int main(int argc, const char* argv[])
217{
218 Configuration conf(argv[0]);
219 conf.SetPrintUsage(PrintUsage);
220 Main::SetupConfiguration(conf);
221 SetupConfiguration(conf);
222
223 if (!conf.DoParse(argc, argv, PrintHelp))
224 return -1;
225
226 if (!conf.Has("console"))
227 return RunShell<LocalStream>(conf);
228
229 if (conf.Get<int>("console")==0)
230 return RunShell<LocalShell>(conf);
231 else
232 return RunShell<LocalConsole>(conf);
233
234 return 0;
235}
Note: See TracBrowser for help on using the repository browser.