source: trunk/FACT++/src/scheduler.cc@ 10606

Last change on this file since 10606 was 10600, checked in by tbretz, 14 years ago
Added fix because gcc 4.5 is not supported by boost 1.42 which are both part of natty.
File size: 28.9 KB
Line 
1#include <boost/bind.hpp>
2#if BOOST_VERSION<1440
3#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 4))
4#undef BOOST_HAS_RVALUE_REFS
5#error test
6#endif
7#endif
8#include <boost/thread.hpp>
9#include <boost/regex.hpp>
10#include <boost/asio/deadline_timer.hpp>
11
12#include "Time.h"
13#include "Event.h"
14#include "Shell.h"
15#include "StateMachineDim.h"
16#include "Connection.h"
17#include "Configuration.h"
18#include "Timers.h"
19#include "Console.h"
20#include "Converter.h"
21
22#include "tools.h"
23
24#include <vector>
25
26namespace ba = boost::asio;
27namespace bs = boost::system;
28
29using ba::deadline_timer;
30using ba::ip::tcp;
31
32using namespace std;
33
34
35#include "LocalControl.h"
36#include <boost/date_time/posix_time/posix_time.hpp>
37#include <mysql++/mysql++.h>
38
39// string containing database information
40string database;
41
42// things to be done/checked/changed
43// * do not use --database, but sth like --database-scheduler
44// to be independent of the configuration database
45// * check if the following include is really needed
46// #include <boost/date_time/posix_time/posix_time.hpp>
47// * string database not as global variable
48// pass reference to conf and the string as a member of the class
49// (see chat of 4.5.2011)
50// * move definition of config parameters to AutoScheduler class
51// + read in from config
52
53// other things to do
54//
55// define what is error and warning
56
57
58// config parameters
59// mintime
60// runtimec
61// runtimep
62// repostime
63
64// missing:
65// from / to for the time range for which the scheduling shall be done
66//
67// calculate time for std obs
68// calculate sun set/rise
69//
70// check for double std sources
71//
72// return errors
73// get input from sendcommand
74
75// =========================================================================
76
77template <class T>
78class AutoScheduler : public T
79{
80 bool fNextIsPreview;
81public:
82 enum states_t
83 {
84 kSM_Scheduling=1,
85 kSM_Comitting,
86 };
87
88 struct ObservationParameters
89 {
90 int obskey;
91 int obsmode;
92 int obstype;
93 int splitflag;
94 int telsetup;
95 float fluxweight;
96 float slope;
97 float flux;
98 float ra;
99 float dec;
100 boost::posix_time::ptime starttime;
101 boost::posix_time::ptime stoptime;
102 boost::posix_time::time_duration duration_db;
103 string sourcename;
104 int sourcekey;
105 };
106
107 struct FixedObs
108 {
109 int obskey_fixed;
110 int sourcekey_fixed;
111 string sourcename_fixed;
112 int obsmode_fixed;
113 int obstype_fixed;
114 int telsetup_fixed;
115 float ra_fixed;
116 float dec_fixed;
117 boost::posix_time::ptime obsfixedstart;
118 boost::posix_time::ptime obsfixedstop;
119 };
120
121 // will need other types of obs
122 // FloatingObs (duration < stop-start + splitflag no)
123 // FloatingSplittedObs (duration < stop-start + splitflag yes)
124 // FixedSlot, i.e. just block a time slot
125
126 struct StdObs
127 {
128 int obskey_std;
129 int sourcekey_std;
130 string sourcename_std;
131 int obsmode_std;
132 int obstype_std;
133 int telsetup_std;
134 float fluxweight_std;
135 float slope_std;
136 float flux_std;
137 float ra_std;
138 float dec_std;
139 boost::posix_time::ptime obsstdstart;
140 boost::posix_time::ptime obsstdstop;
141 };
142
143 struct ScheduledObs
144 {
145 int sourcekey_obs;
146 string sourcename_obs;
147 int obsmode_obs;
148 int obstype_obs;
149 int telsetup_obs;
150 boost::posix_time::ptime obsstart;
151 boost::posix_time::ptime obsstop;
152 };
153
154 struct ScheduledRun
155 {
156 //int runnumber; // to be seen, if runnumber is needed
157 int runtype;
158 int sourcekey_run;
159 string sourcename_run;//for convenience
160 int obsmode_run;
161 int obstype_run;
162 int telsetup_run;
163 boost::posix_time::ptime runstart;
164 boost::posix_time::ptime runstop;
165 };
166
167 int fSessionId;
168
169
170
171 int Schedule()
172 {
173 boost::posix_time::time_duration runtimec(0, 3, 0);
174 boost::posix_time::time_duration runtimep(0, 3, 0);
175 boost::posix_time::time_duration mintime(1, 0, 0);
176 boost::posix_time::time_duration repostime(0, 5, 0);
177
178 stringstream str;
179 str << "Scheduling started -> Preview (id=" << fSessionId << ")";
180 T::Message(str);
181
182 static const boost::regex expr("(([[:word:].-]+)(:(.+))?@)?([[:word:].-]+)(:([[:digit:]]+))?(/([[:word:].-]+))");
183 // 2: user
184 // 4: pass
185 // 5: server
186 // 7: port
187 // 9: db
188
189 boost::smatch what;
190 if (!boost::regex_match(database, what, expr, boost::match_extra))
191 {
192 cout << "Couldn't parse '" << database << "'." << endl;
193 throw;
194 }
195
196 if (what.size()!=10)
197 {
198 cout << "Error parsing '" << database << "'." << endl;
199 throw;
200 }
201
202 const string user = what[2];
203 const string passwd = what[4];
204 const string server = what[5];
205 const string db = what[9];
206 const int port = atoi(string(what[7]).c_str());
207
208 cout << "Connecting to '";
209 if (!user.empty())
210 cout << user << "@";
211 cout << server;
212 if (port)
213 cout << ":" << port;
214 if (!db.empty())
215 cout << "/" << db;
216 cout << "'" << endl;
217
218 mysqlpp::Connection conn(db.c_str(), server.c_str(), user.c_str(), passwd.c_str(), port);
219 if (!conn.connected())
220 {
221 cout << "MySQL connection error: " << conn.error() << endl;
222 throw;
223 }
224
225 // get observation parameters from DB
226 // maybe order by priority?
227 mysqlpp::Query query = conn.query("SELECT fObservationKEY, fStartTime, fStopTime, fDuration, fSourceName, fSourceKEY, fSplitFlag, fFluxWeight, fSlope, fFlux, fRightAscension, fDeclination, fObservationModeKEY, fObservationTypeKEY , fTelescopeSetupKEY FROM ObservationParameters LEFT JOIN Source USING(fSourceKEY) ORDER BY fStartTime");
228
229 mysqlpp::StoreQueryResult res = query.store();
230 if (!res)
231 {
232 cout << "MySQL query failed: " << query.error() << endl;
233 throw;
234 }
235
236 cout << "Found " << res.num_rows() << " Observation Parameter sets." << endl;
237
238 ObservationParameters olist[res.num_rows()];
239 std::vector<FixedObs> obsfixedlist;
240 std::vector<StdObs> obsstdlist;
241 std::vector<ScheduledObs> obslist;
242 std::vector<ScheduledRun> runlist;
243
244 // loop over observation parameters from DB
245 // fill these parameters into FixedObs and StdObs
246 int counter=0;
247 int counter2=0;
248 int counter3=0;
249 for (vector<mysqlpp::Row>::iterator v=res.begin(); v<res.end(); v++)
250 {
251 cout << "Obskey: " << (*v)[0].c_str() << " source: " << (*v)[4].c_str() << "(" << (*v)[5].c_str() << ")" << flush;
252 cout << " T1 " << (*v)[1].c_str() << " T2: " << (*v)[2].c_str() << " (c " << counter << " " << counter2 << ")" << endl;
253
254 /*
255 cout << " 0 " << (*v)[0].c_str() << endl;
256 cout << " 1 " << (*v)[1].c_str() << endl;
257 cout << " 2 " << (*v)[2].c_str() << endl;
258 cout << " 3 " << (*v)[3].c_str() << endl;
259 cout << " 4 " << (*v)[4].c_str() << endl;
260 cout << " 5 " << (*v)[5].c_str() << endl;
261 cout << " 6 " << (*v)[6].c_str() << endl;
262 cout << " 7 " << (*v)[7].c_str() << endl;
263 cout << " 8 " << (*v)[8].c_str() << endl;
264 cout << " 9 " << (*v)[9].c_str() << endl;
265 cout << " 10 " << (*v)[10].c_str() << endl;
266 cout << " 11 " << (*v)[11].c_str() << endl;
267 cout << " 12 " << (*v)[12].c_str() << endl;
268 cout << " 13 " << (*v)[13].c_str() << endl;
269 cout << " 14 " << (*v)[14].c_str() << endl;
270 */
271 //0: obskey
272 //1: startime
273 //2: stoptime
274 //3: duration
275 //4: sourcename
276 //5: sourcekey
277 //6: splitflag
278 //7: fluxweight
279 //8: slope
280 //9: flux
281 //10: ra
282 //11: dec
283 //12: obsmode
284 //13: obstype
285 //14: telsetup
286 stringstream t1;
287 stringstream t2;
288 stringstream t3;
289 t1 << (*v)[1].c_str();
290 t2 << (*v)[2].c_str();
291 t3 << (*v)[3].c_str();
292
293 //boost::posix_time::time_duration mintime(0,conf.Get<int>("mintime"), 0);
294 t1 >> Time::sql >> olist[counter].starttime;
295 t2 >> Time::sql >> olist[counter].stoptime;
296 t3 >> olist[counter].duration_db;
297 boost::posix_time::time_period period(olist[counter].starttime, olist[counter].stoptime);
298 olist[counter].sourcename=(*v)[4].c_str();
299 olist[counter].sourcekey=(*v)[5];
300
301 if (!(*v)[0].is_null())
302 olist[counter].obskey=(*v)[0];
303 //else
304 // cout << "no obskey" << endl;
305 if (!(*v)[12].is_null())
306 olist[counter].obsmode=(*v)[12];
307 //else
308 // cout << "no obsmode" << endl;
309 if (!(*v)[13].is_null())
310 olist[counter].obstype=(*v)[13];
311 //else
312 // cout << "no obstype" << endl;
313 if (!(*v)[14].is_null())
314 olist[counter].telsetup=(*v)[14];
315 //else
316 // cout << "no telsetup" << endl;
317 if (!(*v)[6].is_null())
318 olist[counter].splitflag=(*v)[6];
319 //else
320 //{
321 // cout << "no splitflag" << endl;
322 ////stringstream str;
323 ////str << "no splitflag";
324 //T::Message("no splitflag");
325 //T::Error("---> no splitflag");
326 //T::Warn("+++ no splitflag");
327 //}
328 if (!(*v)[7].is_null())
329 olist[counter].fluxweight=(*v)[7];
330 else
331 {
332 olist[counter].fluxweight=0;
333 // cout << "no fluxweight" << endl;
334 }
335 if (!(*v)[8].is_null())
336 olist[counter].slope=(*v)[8];
337 //else
338 // cout << "no slope" << endl;
339 if (!(*v)[9].is_null())
340 olist[counter].flux=(*v)[9];
341 //else
342 // cout << "no flux" << endl;
343 if (!(*v)[10].is_null())
344 olist[counter].ra=(*v)[10];
345 //else
346 // cout << "no ra" << endl;
347 if (!(*v)[11].is_null())
348 olist[counter].dec=(*v)[11];
349 //else
350 // cout << "no dec" << endl;
351
352 // time_duration cannot be used, as only up to 99 hours are handeled
353 boost::posix_time::time_duration duration = period.length();
354
355 /*
356 if (olist[counter].stoptime < olist[counter].starttime+mintime)
357 cout << " ====> WARN: Observation too short. " << endl;
358
359 if (olist[counter].starttime.is_not_a_date_time())
360 cout << " WARN: starttime not a date_time. " << endl;
361 else
362 cout << " start: " << Time::sql << olist[counter].starttime << endl;
363 if (olist[counter].stoptime.is_not_a_date_time())
364 cout << " WARN: stoptime not a date_time. " << endl;
365 else
366 cout << " stop: " << Time::sql << olist[counter].stoptime << endl;
367 if (!(olist[counter].starttime.is_not_a_date_time() || olist[counter].stoptime.is_not_a_date_time()))
368 cout << " diff: " << period << endl;
369 if (olist[counter].stoptime < olist[counter].starttime)
370 cout << " ====> WARN: stop time (" << olist[counter].stoptime << ") < start time (" << olist[counter].starttime << "). " << endl;
371 cout << "diff: " << duration << flush;
372 cout << "dur_db: " << olist[counter].duration_db << endl;
373 */
374
375 // always filled: obstype
376 //
377 // fixed observations:
378 // filled: starttime, stoptime
379 // not filled: fluxweight
380 // maybe filled: obsmode, telsetup, source (not filled for FixedSlotObs)
381 // maybe filled: duration (filled for FloatingObs and FloatingSplittedObs)
382 // maybe filled: splitflag (filled for FloatingSplittedObs)
383 //
384 // std observations:
385 // filled: fluxweight, telsetup, obsmore, source
386 // not filled: starttime, stoptime, duration
387
388 // fixed observations
389 if (!(olist[counter].stoptime.is_not_a_date_time()
390 && olist[counter].starttime.is_not_a_date_time())
391 && olist[counter].fluxweight==0
392 )
393 {
394 obsfixedlist.resize(counter2+1);
395 obsfixedlist[counter2].obsfixedstart=olist[counter].starttime;
396 obsfixedlist[counter2].obsfixedstop=olist[counter].stoptime;
397 obsfixedlist[counter2].sourcename_fixed=olist[counter].sourcename;
398 obsfixedlist[counter2].obskey_fixed=olist[counter].obskey;
399 obsfixedlist[counter2].obstype_fixed=olist[counter].obstype;
400 obsfixedlist[counter2].obsmode_fixed=olist[counter].obsmode;
401 obsfixedlist[counter2].telsetup_fixed=olist[counter].telsetup;
402 obsfixedlist[counter2].sourcekey_fixed=olist[counter].sourcekey;
403 obsfixedlist[counter2].ra_fixed=olist[counter].ra;
404 obsfixedlist[counter2].dec_fixed=olist[counter].dec;
405 counter2++;
406 }
407
408 // std obs
409 if (olist[counter].stoptime.is_not_a_date_time()
410 && olist[counter].starttime.is_not_a_date_time()
411 && olist[counter].fluxweight>0
412 )
413 {
414 obsstdlist.resize(counter3+1);
415 obsstdlist[counter3].sourcename_std=olist[counter].sourcename;
416 obsstdlist[counter3].obskey_std=olist[counter].obskey;
417 obsstdlist[counter3].obsmode_std=olist[counter].obsmode;
418 obsstdlist[counter3].obstype_std=olist[counter].obstype;
419 obsstdlist[counter3].telsetup_std=olist[counter].telsetup;
420 obsstdlist[counter3].sourcekey_std=olist[counter].sourcekey;
421 obsstdlist[counter3].fluxweight_std=olist[counter].fluxweight;
422 obsstdlist[counter3].flux_std=olist[counter].flux;
423 obsstdlist[counter3].slope_std=olist[counter].slope;
424 obsstdlist[counter3].ra_std=olist[counter].ra;
425 obsstdlist[counter3].dec_std=olist[counter].dec;
426 counter3++;
427 }
428
429 counter++;
430 }
431 cout << obsfixedlist.size() << " fixed observations found. " << endl;
432 cout << obsstdlist.size() << " standard observations found. " << endl;
433
434 // loop to add the fixed observations to the ScheduledObs list
435 // missing: checks and evaluation
436 // * check for sun
437 // * check for moon
438 counter2=0;
439 boost::posix_time::ptime finalobsfixedstart;
440 boost::posix_time::ptime finalobsfixedstop;
441 boost::posix_time::time_duration delta1;
442 boost::posix_time::time_duration delta2;
443 boost::posix_time::time_duration delta0(0,0,0);
444 struct vector<FixedObs>::iterator vobs;
445 struct vector<FixedObs>::iterator vobs5;
446 cout << "Fixed Observations: " << endl;
447 for (vobs=obsfixedlist.begin(); vobs!=obsfixedlist.end(); vobs++)
448 {
449 counter3=0;
450 delta1=delta0;
451 delta2=delta0;
452 finalobsfixedstart=obsfixedlist[counter2].obsfixedstart;
453 finalobsfixedstop=obsfixedlist[counter2].obsfixedstop;
454 //cout << "final: " << finalobsfixedstart << " - " << finalobsfixedstop << endl;
455
456 for (vobs5=obsfixedlist.begin(); vobs5!=obsfixedlist.end(); vobs5++)
457 {
458 //cout << "startc" << obsfixedlist[counter2].obsfixedstart << " -- " << flush;
459 //cout << "stopc" << obsfixedlist[counter2].obsfixedstop << " -- " << flush;
460 //cout << "start" << (*vobs5).obsfixedstart << " -- " << flush;
461 //cout << "stop" << (*vobs5).obsfixedstop << " -- " << flush;
462
463 //if (obsfixedlist[counter2].obsfixedstart < (*vobs5).obsfixedstop
464 // && (*vobs5).obsfixedstop < obsfixedlist[counter2].obsfixedstop
465 // && counter2!=counter3)
466 if ((*vobs5).obsfixedstart < obsfixedlist[counter2].obsfixedstop
467 && obsfixedlist[counter2].obsfixedstop <= (*vobs5).obsfixedstop
468 && obsfixedlist[counter2].obsfixedstart <= (*vobs5).obsfixedstart
469 && counter2!=counter3)
470 {
471 //delta1=((*vobs5).obsfixedstop-obsfixedlist[counter2].obsfixedstart)/2;
472 delta1=(obsfixedlist[counter2].obsfixedstop-(*vobs5).obsfixedstart)/2;
473 finalobsfixedstop=obsfixedlist[counter2].obsfixedstop-delta1;
474 //cout << "delta1 " << delta1 << endl;
475 stringstream warndelta1;
476 warndelta1 << "Overlap between two fixed observations (" << obsfixedlist[counter2].obskey_fixed << " " << (*vobs5).obskey_fixed << "). The stoptime of " << obsfixedlist[counter2].obskey_fixed << " has been changed.";
477 T::Warn(warndelta1);
478 }
479 //if (obsfixedlist[counter2].obsfixedstart < (*vobs5).obsfixedstart
480 // && (*vobs5).obsfixedstart < obsfixedlist[counter2].obsfixedstop
481 // && counter2!=counter3)
482 if ((*vobs5).obsfixedstart <= obsfixedlist[counter2].obsfixedstart
483 && obsfixedlist[counter2].obsfixedstart < (*vobs5).obsfixedstop
484 && obsfixedlist[counter2].obsfixedstop >= (*vobs5).obsfixedstop
485 && counter2!=counter3)
486 {
487 delta2=((*vobs5).obsfixedstop-obsfixedlist[counter2].obsfixedstart)/2;
488 finalobsfixedstart=obsfixedlist[counter2].obsfixedstart+delta2;
489 //cout << "delta2 " << delta2 << endl;
490 stringstream warndelta2;
491 warndelta2 << "Overlap between two fixed observations (" << obsfixedlist[counter2].obskey_fixed << " " << (*vobs5).obskey_fixed << "). The starttime of " << obsfixedlist[counter2].obskey_fixed << " has been changed.";
492 T::Warn(warndelta2);
493 }
494 counter3++;
495 //cout << endl;
496 }
497
498 //cout << "-> final: " << finalobsfixedstart << " - " << finalobsfixedstop << endl;
499 obslist.resize(counter2+1);
500 //obslist[counter2].obsstart=obsfixedlist[counter2].obsfixedstart;
501 obslist[counter2].obsstart=finalobsfixedstart;
502 //obslist[counter2].obsstop=obsfixedlist[counter2].obsfixedstop;
503 obslist[counter2].obsstop=finalobsfixedstop;
504 obslist[counter2].sourcename_obs=obsfixedlist[counter2].sourcename_fixed;
505 obslist[counter2].obsmode_obs=obsfixedlist[counter2].obsmode_fixed;
506 obslist[counter2].obstype_obs=obsfixedlist[counter2].obstype_fixed;
507 obslist[counter2].telsetup_obs=obsfixedlist[counter2].telsetup_fixed;
508 obslist[counter2].sourcekey_obs=obsfixedlist[counter2].sourcekey_fixed;
509 counter2++;
510 //cout << " " << (*vobs).sourcename_fixed << " " << (*vobs).obsfixedstart << flush;
511 //cout << " - " << (*vobs).obsfixedstop << endl;
512 }
513
514 // in this loop the standard observations shall be
515 // checked, evaluated
516 // the observation times shall be calculated
517 // and the observations added to the ScheduledObs list
518 struct vector<StdObs>::iterator vobs2;
519 cout << "Standard Observations: " << endl;
520 for (vobs2=obsstdlist.begin(); vobs2!=obsstdlist.end(); vobs2++)
521 {
522 cout << " " << (*vobs2).sourcename_std << endl;
523 }
524
525 // in this loop from the scheduled observations the list
526 // of scheduled runs shall be calculated
527 counter2=0;
528 struct vector<ScheduledObs>::iterator vobs3;
529 for (vobs3=obslist.begin(); vobs3!=obslist.end(); vobs3++)
530 {
531 // add runtype and runtime calculations
532 runlist.resize(counter2+1);
533 runlist[counter2].runstart=obslist[counter2].obsstart;
534 runlist[counter2].runstop=obslist[counter2].obsstop;
535 runlist[counter2].sourcename_run=obslist[counter2].sourcename_obs;
536 runlist[counter2].obsmode_run=obslist[counter2].obsmode_obs;
537 runlist[counter2].obstype_run=obslist[counter2].obstype_obs;
538 runlist[counter2].telsetup_run=obslist[counter2].telsetup_obs;
539 runlist[counter2].sourcekey_run=obslist[counter2].sourcekey_obs;
540 counter2++;
541 cout << (*vobs3).sourcename_obs << endl;
542 }
543
544 //delete old scheduled runs from the DB
545 mysqlpp::Query query0 = conn.query("DELETE FROM ScheduledRun");
546
547 mysqlpp::SimpleResult res0 = query0.execute();
548 if (!res0)
549 {
550 cout << "MySQL query failed: " << query0.error() << endl;
551 throw;
552 }
553
554 counter3=0;
555 boost::posix_time::ptime finalstarttime;
556 boost::posix_time::ptime finalstoptime;
557 struct vector<ScheduledRun>::iterator vobs4;
558 for (vobs4=runlist.begin(); vobs4!=runlist.end(); vobs4++)
559 {
560 for (int i=2; i<5; i++)
561 {
562 switch(i)
563 {
564 case 2:
565 finalstarttime=runlist[counter3].runstart+repostime+runtimec+runtimep;
566 finalstoptime=runlist[counter3].runstop;
567 break;
568 case 3:
569 finalstarttime=runlist[counter3].runstart+repostime;
570 finalstoptime=runlist[counter3].runstart+runtimep+repostime;
571 break;
572 case 4:
573 finalstarttime=runlist[counter3].runstart+runtimep+repostime;
574 finalstoptime=runlist[counter3].runstart+repostime+runtimep+runtimec;
575 break;
576 }
577 stringstream q1;
578 //cout << (*vobs4).sourcename_run << endl;
579 q1 << "INSERT ScheduledRun set fStartTime='" << Time::sql << finalstarttime;
580 q1 << "', fStopTime='" << Time::sql << finalstoptime;
581 q1 << "', fSourceKEY='" << (*vobs4).sourcekey_run;
582 q1 << "', fRunTypeKEY='" << i;
583 q1 << "', fTelescopeSetupKEY='" << (*vobs4).telsetup_run;
584 q1 << "', fObservationTypeKEY='" << (*vobs4).obstype_run;
585 q1 << "', fObservationModeKEY='" << (*vobs4).obsmode_run;
586 q1 << "'";
587
588 //cout << "executing query: " << q1.str() << endl;
589
590 mysqlpp::Query query1 = conn.query(q1.str());
591
592 mysqlpp::SimpleResult res1 = query1.execute();
593 if (!res1)
594 {
595 cout << "MySQL query failed: " << query1.error() << endl;
596 throw;
597 }
598 }
599 counter3++;
600 }
601 //usleep(3000000);
602 T::Message("Scheduling done.");
603
604 fSessionId = -1;
605
606 bool error = false;
607 return error ? T::kSM_Error : T::kSM_Ready;
608 }
609
610 /*
611 // commit probably done by webinterface
612 int Commit()
613 {
614 stringstream str;
615 str << "Comitting preview (id=" << fSessionId << ")";
616 T::Message(str);
617
618 usleep(3000000);
619 T::Message("Comitted.");
620
621 fSessionId = -1;
622
623 bool error = false;
624 return error ? T::kSM_Error : T::kSM_Ready;
625 }
626 */
627
628 AutoScheduler(ostream &out=cout) : T(out, "SCHEDULER"), fNextIsPreview(true), fSessionId(-1)
629 {
630 AddStateName(kSM_Scheduling, "Scheduling");
631 //AddStateName(kSM_Comitting, "Comitting");
632
633 AddTransition(kSM_Scheduling, "SCHEDULE", T::kSM_Ready);
634 //AddTransition(kSM_Comitting, "COMMIT", T::kSM_Ready);
635
636 T::PrintListOfEvents();
637 }
638
639 int Execute()
640 {
641 switch (T::GetCurrentState())
642 {
643 case kSM_Scheduling:
644 return Schedule();
645
646 //case kSM_Comitting:
647 // return Commit();
648 }
649 return T::GetCurrentState();
650 }
651
652 int Transition(const Event &evt)
653 {
654 switch (evt.GetTargetState())
655 {
656 case kSM_Scheduling:
657 //case kSM_Comitting:
658 //fSessionId = evt.GetInt();
659 break;
660 }
661
662 return evt.GetTargetState();
663 }
664 int Configure(const Event &)
665 {
666 return T::GetCurrentState();
667 }
668};
669
670// ------------------------------------------------------------------------
671
672template<class S>
673int RunDim(Configuration &conf)
674{
675 WindowLog wout;
676
677 //log.SetWindow(stdscr);
678 if (conf.Has("log"))
679 if (!wout.OpenLogFile(conf.Get<string>("log")))
680 wout << kRed << "ERROR - Couldn't open log-file " << conf.Get<string>("log") << ": " << strerror(errno) << endl;
681
682 // Start io_service.Run to use the StateMachineImp::Run() loop
683 // Start io_service.run to only use the commandHandler command detaching
684 AutoScheduler<S> io_service(wout);
685 io_service.Run();
686
687 return 0;
688}
689
690template<class T, class S>
691int RunShell(Configuration &conf)
692{
693 static T shell(conf.GetName().c_str(), conf.Get<int>("console")!=1);
694
695 WindowLog &win = shell.GetStreamIn();
696 WindowLog &wout = shell.GetStreamOut();
697
698 if (conf.Has("log"))
699 if (!wout.OpenLogFile(conf.Get<string>("log")))
700 win << kRed << "ERROR - Couldn't open log-file " << conf.Get<string>("log") << ": " << strerror(errno) << endl;
701
702 AutoScheduler<S> io_service(wout);
703 shell.SetReceiver(io_service);
704
705 boost::thread t(boost::bind(&AutoScheduler<S>::Run, &io_service));
706
707 //io_service.SetReady();
708
709 shell.Run(); // Run the shell
710 io_service.Stop(); // Signal Loop-thread to stop
711 // io_service.Close(); // Obsolete, done by the destructor
712 // wout << "join: " << t.timed_join(boost::posix_time::milliseconds(0)) << endl;
713
714 // Wait until the StateMachine has finished its thread
715 // before returning and destroying the dim objects which might
716 // still be in use.
717 t.join();
718
719 return 0;
720}
721
722void SetupConfiguration(Configuration &conf)
723{
724 const string n = conf.GetName()+".log";
725
726 //po::options_description config("Program options");
727 po::options_description config("Configuration");
728 config.add_options()
729 ("dns", var<string>("localhost"), "Dim nameserver host name (Overwites DIM_DNS_NODE environment variable)")
730 ("log,l", var<string>(n), "Write log-file")
731 ("no-dim,d", po_switch(), "Disable dim services")
732 ("console,c", var<int>(), "Use console (0=shell, 1=simple buffered, X=simple unbuffered)")
733 ("mintime", var<int>(), "minimum observation time")
734 ;
735
736 conf.AddEnv("dns", "DIM_DNS_NODE");
737
738 conf.AddOptions(config);
739 conf.AddOptionsDatabase(config);
740}
741
742int main(int argc, const char* argv[])
743{
744 Configuration conf(argv[0]);
745 SetupConfiguration(conf);
746
747 po::variables_map vm;
748 try
749 {
750 vm = conf.Parse(argc, argv);
751 }
752 catch (std::exception &e)
753 {
754#if BOOST_VERSION > 104000
755 po::multiple_occurrences *MO = dynamic_cast<po::multiple_occurrences*>(&e);
756 if (MO)
757 cout << "Error: " << e.what() << " of '" << MO->get_option_name() << "' option." << endl;
758 else
759#endif
760 cout << "Error: " << e.what() << endl;
761 cout << endl;
762
763 return -1;
764 }
765
766 //if (conf.Has("mintime"))
767 // cout << "has mintime --------------------+" << conf.Get<int>("mintime")<< "+------------" << endl;
768
769 if (conf.Has("database"))
770 database = conf.Get<string>("database").c_str();
771 else
772 {
773 cout << "Please provide which database you want to use for scheduling." << endl;
774 return -1;
775 }
776
777
778 if (conf.HasHelp() || conf.HasPrint())
779 return -1;
780
781 // To allow overwriting of DIM_DNS_NODE set 0 to 1
782 setenv("DIM_DNS_NODE", conf.Get<string>("dns").c_str(), 1);
783
784 try
785 {
786 // No console access at all
787 if (!conf.Has("console"))
788 {
789 if (conf.Get<bool>("no-dim"))
790 return RunDim<StateMachine>(conf);
791 else
792 return RunDim<StateMachineDim>(conf);
793 }
794 // Cosole access w/ and w/o Dim
795 if (conf.Get<bool>("no-dim"))
796 {
797 if (conf.Get<int>("console")==0)
798 return RunShell<LocalShell, StateMachine>(conf);
799 else
800 return RunShell<LocalConsole, StateMachine>(conf);
801 }
802 else
803 {
804 if (conf.Get<int>("console")==0)
805 return RunShell<LocalShell, StateMachineDim>(conf);
806 else
807 return RunShell<LocalConsole, StateMachineDim>(conf);
808 }
809 }
810 catch (std::exception& e)
811 {
812 std::cerr << "Exception: " << e.what() << "\n";
813 }
814
815 return 0;
816}
Note: See TracBrowser for help on using the repository browser.