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

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