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

Last change on this file since 12650 was 11577, checked in by tbretz, 13 years ago
Moved Dim:Setup to Main::execute
File size: 28.9 KB
Line 
1#include <vector>
2
3#include <boost/regex.hpp>
4
5#include <mysql++/mysql++.h>
6
7#include "Dim.h"
8#include "Time.h"
9#include "Event.h"
10#include "Connection.h"
11#include "Configuration.h"
12#include "StateMachineDim.h"
13
14#include "tools.h"
15
16using namespace std;
17using namespace boost::gregorian;
18using namespace boost::posix_time;
19
20// things to be done/checked/changed
21// * --schedule-database should be required
22// * move definition of config parameters to AutoScheduler class
23// + read in from config
24// * in some (all?) loops iterator over vector can be replaced by counter
25
26// other things to do
27//
28// define what to transmit as info/warn/error
29
30
31// config parameters:
32// mintime
33// runtimec
34// runtimep
35// repostime
36
37// missing:
38//
39// calculate time for std obs
40// calculate sun set/rise
41//
42// return errors and other otherput from sendcommand to webinterface
43
44// in which cases should the scheduler go in error state?
45// when db is unavailable
46// does one also need a 'set scheduler to ready' function then?
47// do we want any error state at all?
48
49
50// =========================================================================
51
52template <class T>
53class AutoScheduler : public T
54{
55 bool fNextIsPreview;
56public:
57 enum states_t
58 {
59 kSM_Scheduling=1,
60 kSM_Comitting,
61 };
62
63 struct ObservationParameters
64 {
65 int obskey;
66 int obsmode;
67 int obstype;
68 int splitflag;
69 int telsetup;
70 float fluxweight;
71 float slope;
72 float flux;
73 float ra;
74 float dec;
75 ptime start;
76 ptime stop;
77 time_duration duration_db;
78 string sourcename;
79 int sourcekey;
80 };
81
82 struct FixedObs
83 {
84 int obskey;
85 int sourcekey;
86 string sourcename;
87 int obsmode;
88 int obstype;
89 int telsetup;
90 float ra;
91 float dec;
92 ptime start;
93 ptime stop;
94 };
95
96 // will need other types of obs
97 // FloatingObs (duration < stop-start + splitflag no)
98 // FloatingSplittedObs (duration < stop-start + splitflag yes)
99 // FixedSlot, i.e. just block a time slot
100
101 struct StdObs
102 {
103 int obskey_std;
104 int sourcekey_std;
105 string sourcename_std;
106 int obsmode_std;
107 int obstype_std;
108 int telsetup_std;
109 float fluxweight_std;
110 float slope_std;
111 float flux_std;
112 float ra_std;
113 float dec_std;
114 ptime obsstdstart;
115 ptime obsstdstop;
116 };
117
118 struct ScheduledObs
119 {
120 int obskey_obs;
121 int sourcekey_obs;
122 string sourcename_obs;
123 int obsmode_obs;
124 int obstype_obs;
125 int telsetup_obs;
126 ptime obsstart;
127 ptime obsstop;
128 };
129
130 struct ScheduledRun
131 {
132 //int runnumber; // to be seen, if runnumber is needed
133 int obskey_run;
134 int runtype;
135 int sourcekey_run;
136 string sourcename_run;//for convenience
137 int obsmode_run;
138 int obstype_run;
139 int telsetup_run;
140 ptime runstart;
141 ptime runstop;
142 };
143
144 string fDatabase;
145 string fDBName;
146 int fDurationCalRun; //unit: minutes
147 int fDurationPedRun; //unit: minutes
148 int fDurationRepos; //unit: minutes
149
150 int Schedule()
151 {
152 bool error = false;
153
154 time_duration runtimec(0, fDurationCalRun, 0);
155 time_duration runtimep(0, fDurationPedRun, 0);
156 time_duration repostime(0, fDurationRepos, 0);
157 time_duration mintime(1, 0, 0);
158
159 const ptime startsched(microsec_clock::local_time());
160 const ptime stopsched=startsched+years(1);
161
162 ostringstream str;
163 str << "Scheduling for the period from " << startsched << " to " << stopsched;
164 T::Message(str);
165
166 static const boost::regex expr("([[:word:].-]+):(.+)@([[:word:].-]+)(:([[:digit:]]+))?/([[:word:].-]+)");
167 // 2: user
168 // 4: pass
169 // 5: server
170 // 7: port
171 // 9: db
172
173 boost::smatch what;
174 if (!boost::regex_match(fDatabase, what, expr, boost::match_extra))
175 {
176 ostringstream msg;
177 msg << "Regex to parse database '" << fDatabase << "' empty.";
178 T::Error(msg);
179 return T::kSM_Error;
180 }
181
182 if (what.size()!=7)
183 {
184 ostringstream msg;
185 msg << "Parsing database name failed: '" << fDatabase << "'";
186 T::Error(msg);
187 return T::kSM_Error;
188 }
189
190 const string user = what[1];
191 const string passwd = what[2];
192 const string server = what[3];
193 const string db = fDBName.empty() ? what[6] : fDBName;
194 const int port = stoi(what[5]);
195
196 ostringstream dbnamemsg;
197 dbnamemsg << "Scheduling started -> using database " << db << ".";
198 T::Message(dbnamemsg);
199
200 str.str("");
201 str << "Connecting to '";
202 if (!user.empty())
203 str << user << "@";
204 str << server;
205 if (port)
206 str << ":" << port;
207 if (!db.empty())
208 str << "/" << db;
209 str << "'";
210 T::Info(str);
211
212 mysqlpp::Connection conn(db.c_str(), server.c_str(), user.c_str(), passwd.c_str(), port);
213 /* throws exceptions
214 if (!conn.connected())
215 {
216 ostringstream msg;
217 msg << "MySQL connection error: " << conn.error();
218 T::Error(msg);
219 return T::kSM_Error;
220 }*/
221
222 // get observation parameters from DB
223 // maybe order by priority?
224 const mysqlpp::StoreQueryResult res =
225 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").store();
226 // FIXME: Maybe we have to check for a successfull
227 // query but an empty result
228 /* thorws exceptions?
229 if (!res)
230 {
231 ostringstream msg;
232 msg << "MySQL query failed: " << query.error();
233 T::Error(msg);
234 return T::kSM_Error;
235 }*/
236
237 str.str("");
238 str << "Found " << res.num_rows() << " Observation Parameter sets.";
239 T::Debug(str);
240
241 ObservationParameters olist[res.num_rows()];
242 vector<FixedObs> obsfixedlist;
243 vector<StdObs> obsstdlist;
244 vector<ScheduledObs> obslist;
245 vector<ScheduledRun> runlist;
246
247 // loop over observation parameters from DB
248 // fill these parameters into FixedObs and StdObs
249 int counter=0;
250 int counter2=0;
251 int counter3=0;
252 cout << "Obs: <obskey> <sourcename>(<sourcekey>, <fluxweight>) from <starttime> to <stoptime>" << endl;
253 for (vector<mysqlpp::Row>::const_iterator v=res.begin(); v<res.end(); v++)
254 {
255 cout << " Obs: " << (*v)[0].c_str() << " " << (*v)[4].c_str() << "(" << (*v)[5].c_str() << flush;
256 cout << ", " << (*v)[7].c_str() << ")" << flush;
257 cout << " from " << (*v)[1].c_str() << " to " << (*v)[2].c_str() << endl;
258
259 //0: obskey
260 //1: startime
261 //2: stoptime
262 //3: duration
263 //4: sourcename
264 //5: sourcekey
265 //6: splitflag
266 //7: fluxweight
267 //8: slope
268 //9: flux
269 //10: ra
270 //11: dec
271 //12: obsmode
272 //13: obstype
273 //14: telsetup
274 stringstream t1;
275 stringstream t2;
276 stringstream t3;
277 t1 << (*v)[1].c_str();
278 t2 << (*v)[2].c_str();
279 t3 << (*v)[3].c_str();
280
281 //boost::posix_time::time_duration mintime(0,conf.Get<int>("mintime"), 0);
282 t1 >> Time::sql >> olist[counter].start;
283 t2 >> Time::sql >> olist[counter].stop;
284 t3 >> olist[counter].duration_db;
285 const time_period period(olist[counter].start, olist[counter].stop);
286
287 olist[counter].sourcename=(*v)[4].c_str();
288 olist[counter].sourcekey=(*v)[5];
289
290 if (!(*v)[0].is_null())
291 olist[counter].obskey=(*v)[0];
292 if (!(*v)[12].is_null())
293 olist[counter].obsmode=(*v)[12];
294 if (!(*v)[13].is_null())
295 olist[counter].obstype=(*v)[13];
296 if (!(*v)[14].is_null())
297 olist[counter].telsetup=(*v)[14];
298 if (!(*v)[6].is_null())
299 olist[counter].splitflag=(*v)[6];
300 if (!(*v)[7].is_null())
301 olist[counter].fluxweight=(*v)[7];
302 else
303 olist[counter].fluxweight=0;//set fluxweight to 0 for check below
304 if (!(*v)[8].is_null())
305 olist[counter].slope=(*v)[8];
306 if (!(*v)[9].is_null())
307 olist[counter].flux=(*v)[9];
308 if (!(*v)[10].is_null())
309 olist[counter].ra=(*v)[10];
310 if (!(*v)[11].is_null())
311 olist[counter].dec=(*v)[11];
312
313 // time_duration cannot be used, as only up to 99 hours are handeled
314 const time_duration duration = period.length();
315
316 /*
317 if (olist[counter].stoptime < olist[counter].starttime+mintime)
318 cout << " ====> WARN: Observation too short. " << endl;
319
320 if (olist[counter].starttime.is_not_a_date_time())
321 cout << " WARN: starttime not a date_time. " << endl;
322 else
323 cout << " start: " << Time::sql << olist[counter].starttime << endl;
324 if (olist[counter].stoptime.is_not_a_date_time())
325 cout << " WARN: stoptime not a date_time. " << endl;
326 else
327 cout << " stop: " << Time::sql << olist[counter].stoptime << endl;
328 if (!(olist[counter].starttime.is_not_a_date_time() || olist[counter].stoptime.is_not_a_date_time()))
329 cout << " diff: " << period << endl;
330 if (olist[counter].stoptime < olist[counter].starttime)
331 cout << " ====> WARN: stop time (" << olist[counter].stoptime << ") < start time (" << olist[counter].starttime << "). " << endl;
332 cout << "diff: " << duration << flush;
333 cout << "dur_db: " << olist[counter].duration_db << endl;
334 */
335
336 // always filled: obstype
337 //
338 // fixed observations:
339 // filled: starttime, stoptime
340 // not filled: fluxweight
341 // maybe filled: obsmode, telsetup, source (not filled for FixedSlotObs)
342 // maybe filled: duration (filled for FloatingObs and FloatingSplittedObs)
343 // maybe filled: splitflag (filled for FloatingSplittedObs)
344 //
345 // std observations:
346 // filled: fluxweight, telsetup, obsmore, source
347 // not filled: starttime, stoptime, duration
348
349 // fixed observations
350 if (!(olist[counter].stop.is_not_a_date_time()
351 && olist[counter].start.is_not_a_date_time())
352 && olist[counter].fluxweight==0
353 )
354 {
355 obsfixedlist.resize(counter2+1);
356 obsfixedlist[counter2].start=olist[counter].start;
357 obsfixedlist[counter2].stop=olist[counter].stop;
358 obsfixedlist[counter2].sourcename=olist[counter].sourcename;
359 obsfixedlist[counter2].obskey=olist[counter].obskey;
360 obsfixedlist[counter2].obstype=olist[counter].obstype;
361 obsfixedlist[counter2].obsmode=olist[counter].obsmode;
362 obsfixedlist[counter2].telsetup=olist[counter].telsetup;
363 obsfixedlist[counter2].sourcekey=olist[counter].sourcekey;
364 obsfixedlist[counter2].ra=olist[counter].ra;
365 obsfixedlist[counter2].dec=olist[counter].dec;
366 counter2++;
367 }
368
369 // std obs
370 if (olist[counter].stop.is_not_a_date_time()
371 && olist[counter].start.is_not_a_date_time()
372 && olist[counter].fluxweight>0
373 )
374 {
375 obsstdlist.resize(counter3+1);
376 obsstdlist[counter3].sourcename_std=olist[counter].sourcename;
377 obsstdlist[counter3].obskey_std=olist[counter].obskey;
378 obsstdlist[counter3].obsmode_std=olist[counter].obsmode;
379 obsstdlist[counter3].obstype_std=olist[counter].obstype;
380 obsstdlist[counter3].telsetup_std=olist[counter].telsetup;
381 obsstdlist[counter3].sourcekey_std=olist[counter].sourcekey;
382 obsstdlist[counter3].fluxweight_std=olist[counter].fluxweight;
383 obsstdlist[counter3].flux_std=olist[counter].flux;
384 obsstdlist[counter3].slope_std=olist[counter].slope;
385 obsstdlist[counter3].ra_std=olist[counter].ra;
386 obsstdlist[counter3].dec_std=olist[counter].dec;
387 counter3++;
388 }
389
390 counter++;
391 }
392 ostringstream fixedobsmsg;
393 fixedobsmsg << obsfixedlist.size() << " fixed observations found. ";
394 T::Message(fixedobsmsg);
395 cout << obsfixedlist.size() << " fixed observations found. " << endl;
396
397 ostringstream stdobsmsg;
398 stdobsmsg << obsstdlist.size() << " standard observations found. ";
399 T::Message(stdobsmsg);
400 cout << obsstdlist.size() << " standard observations found. " << endl;
401
402 // loop to add the fixed observations to the ScheduledObs list
403 // performed checks:
404 // * overlap of fixed observations: the overlap is split half-half
405 // * check for scheduling time range: only take into account fixed obs within the range
406 // missing checks and evaluation
407 // * check for mintime (pb with overlap checks)
408 // * check for sun
409 // * check for moon
410 counter2=0;
411 int skipcounter=0;
412 ptime finalobsfixedstart;
413 ptime finalobsfixedstop;
414 time_duration delta0(0,0,0);
415
416 cout << "Fixed Observations: " << endl;
417 for (struct vector<FixedObs>::const_iterator vobs=obsfixedlist.begin(); vobs!=obsfixedlist.end(); vobs++)
418 {
419 if (obsfixedlist[counter2].start < startsched
420 || obsfixedlist[counter2].stop > stopsched)
421 {
422 ostringstream skipfixedobsmsg;
423 skipfixedobsmsg << "Skip 1 fixed observation (obskey ";
424 skipfixedobsmsg << obsfixedlist[counter2].obskey;
425 skipfixedobsmsg << ") as it is out of scheduling time range.";
426 T::Message(skipfixedobsmsg);
427
428 counter2++;
429 skipcounter++;
430 continue;
431 }
432 counter3=0;
433
434 time_duration delta1=delta0;
435 time_duration delta2=delta0;
436
437 finalobsfixedstart=obsfixedlist[counter2].start;
438 finalobsfixedstop=obsfixedlist[counter2].stop;
439
440 for (struct vector<FixedObs>::const_iterator vobs5=obsfixedlist.begin(); vobs5!=obsfixedlist.end(); vobs5++)
441 {
442 if (vobs5->start < obsfixedlist[counter2].stop
443 && obsfixedlist[counter2].stop <= vobs5->stop
444 && obsfixedlist[counter2].start <= vobs5->start
445 && counter2!=counter3)
446 {
447 delta1=(obsfixedlist[counter2].stop-vobs5->start)/2;
448 finalobsfixedstop=obsfixedlist[counter2].stop-delta1;
449
450 ostringstream warndelta1;
451 warndelta1 << "Overlap between two fixed observations (";
452 warndelta1 << obsfixedlist[counter2].obskey << " ";
453 warndelta1 << vobs5->obskey << "). The stoptime of ";
454 warndelta1 << obsfixedlist[counter2].obskey << " has been changed.";
455 T::Warn(warndelta1);
456 }
457 if (vobs5->start <= obsfixedlist[counter2].start
458 && obsfixedlist[counter2].start < vobs5->stop
459 && obsfixedlist[counter2].stop >= vobs5->stop
460 && counter2!=counter3)
461 {
462 delta2=(vobs5->stop-obsfixedlist[counter2].start)/2;
463 finalobsfixedstart=obsfixedlist[counter2].start+delta2;
464
465 ostringstream warndelta2;
466 warndelta2 << "Overlap between two fixed observations (";
467 warndelta2 << obsfixedlist[counter2].obskey << " ";
468 warndelta2 << vobs5->obskey << "). The starttime of ";
469 warndelta2 << obsfixedlist[counter2].obskey << " has been changed.";
470
471 T::Warn(warndelta2);
472 }
473 counter3++;
474 }
475
476 const int num=counter2-skipcounter;
477 obslist.resize(num+1);
478 obslist[num].obsstart=finalobsfixedstart;
479 obslist[num].obsstop=finalobsfixedstop;
480 obslist[num].sourcename_obs=obsfixedlist[counter2].sourcename;
481 obslist[num].obsmode_obs=obsfixedlist[counter2].obsmode;
482 obslist[num].obstype_obs=obsfixedlist[counter2].obstype;
483 obslist[num].telsetup_obs=obsfixedlist[counter2].telsetup;
484 obslist[num].sourcekey_obs=obsfixedlist[counter2].sourcekey;
485 obslist[num].obskey_obs=obsfixedlist[counter2].obskey;
486 counter2++;
487
488 cout << " " << vobs->sourcename << " " << vobs->start;
489 cout << " - " << vobs->stop << endl;
490 }
491 ostringstream obsmsg;
492 obsmsg << "Added " << obslist.size() << " fixed observations to ScheduledObs. ";
493 T::Message(obsmsg);
494 cout << "Added " << obslist.size() << " fixed observations to ScheduledObs. " << endl;
495
496 for (int i=0; i<(int)obsstdlist.size(); i++)
497 {
498 for (int j=0; j<(int)obsstdlist.size(); j++)
499 {
500 if (obsstdlist[i].sourcekey_std == obsstdlist[j].sourcekey_std && i!=j)
501 {
502 cout << "One double sourcekey in std observations: " << obsstdlist[j].sourcekey_std << endl;
503 ostringstream errdoublestd;
504 errdoublestd << "One double sourcekey in std observations: " << obsstdlist[j].sourcekey_std << " (" << obsstdlist[j].sourcename_std << ").";
505 T::Error(errdoublestd);
506 T::Message("Scheduling stopped.");
507 return error ? T::kSM_Error : T::kSM_Ready;
508 }
509 }
510 }
511
512 // loop over nights
513 // calculate sunset and sunrise
514 // check if there is already scheduled obs in that night
515 //
516
517 // in this loop the standard observations shall be
518 // checked, evaluated
519 // the observation times shall be calculated
520 // and the observations added to the ScheduledObs list
521 cout << "Standard Observations: " << endl;
522 for (struct vector<StdObs>::const_iterator vobs2=obsstdlist.begin(); vobs2!=obsstdlist.end(); vobs2++)
523 {
524 cout << " " << vobs2->sourcename_std << endl;
525 }
526
527 // in this loop the ScheduledRuns are filled
528 // (only data runs -> no runtype yet)
529 // might be merged with next loop
530 counter2=0;
531 for (struct vector<ScheduledObs>::const_iterator vobs3=obslist.begin(); vobs3!=obslist.end(); vobs3++)
532 {
533 runlist.resize(counter2+1);
534 runlist[counter2].runstart=obslist[counter2].obsstart;
535 runlist[counter2].runstop=obslist[counter2].obsstop;
536 runlist[counter2].sourcename_run=obslist[counter2].sourcename_obs;
537 runlist[counter2].obsmode_run=obslist[counter2].obsmode_obs;
538 runlist[counter2].obstype_run=obslist[counter2].obstype_obs;
539 runlist[counter2].telsetup_run=obslist[counter2].telsetup_obs;
540 runlist[counter2].sourcekey_run=obslist[counter2].sourcekey_obs;
541 runlist[counter2].obskey_run=obslist[counter2].obskey_obs;
542 counter2++;
543 //cout << (*vobs3).sourcename_obs << endl;
544 }
545
546 //delete old scheduled runs from the DB
547 const mysqlpp::SimpleResult res0 =
548 conn.query("DELETE FROM ScheduledRun").execute();
549 // FIXME: Maybe we have to check for a successfull
550 // query but an empty result
551 /* throws exceptions
552 if (!res0)
553 {
554 ostringstream msg;
555 msg << "MySQL query failed: " << query0.error();
556 T::Error(msg);
557 return T::kSM_Error;
558 }*/
559
560 // in this loop the ScheduledRuns are inserted to the DB
561 // before the runtimes are adapted according to
562 // duration of P-Run, C-Run and repositioning
563 counter3=0;
564 int insertcount=0;
565 ptime finalstarttime;
566 ptime finalstoptime;
567 for (struct vector<ScheduledRun>::const_iterator vobs4=runlist.begin(); vobs4!=runlist.end(); vobs4++)
568 {
569 for (int i=2; i<5; i++)
570 {
571 switch(i)
572 {
573 case 2:
574 finalstarttime=runlist[counter3].runstart+repostime+runtimec+runtimep;
575 finalstoptime=runlist[counter3].runstop;
576 break;
577 case 3:
578 finalstarttime=runlist[counter3].runstart+repostime;
579 finalstoptime=runlist[counter3].runstart+runtimep+repostime;
580 break;
581 case 4:
582 finalstarttime=runlist[counter3].runstart+runtimep+repostime;
583 finalstoptime=runlist[counter3].runstart+repostime+runtimep+runtimec;
584 break;
585 }
586 ostringstream q1;
587 //cout << (*vobs4).sourcename_run << endl;
588 q1 << "INSERT ScheduledRun set fStartTime='" << Time::sql << finalstarttime;
589 q1 << "', fStopTime='" << Time::sql << finalstoptime;
590 q1 << "', fSourceKEY='" << (*vobs4).sourcekey_run;
591 q1 << "', fObservationKEY='" << (*vobs4).obskey_run;
592 q1 << "', fRunTypeKEY='" << i;
593 q1 << "', fTelescopeSetupKEY='" << (*vobs4).telsetup_run;
594 q1 << "', fObservationTypeKEY='" << (*vobs4).obstype_run;
595 q1 << "', fObservationModeKEY='" << (*vobs4).obsmode_run;
596 q1 << "'";
597
598 //cout << "executing query: " << q1.str() << endl;
599
600 const mysqlpp::SimpleResult res1 = conn.query(q1.str()).execute();
601 // FIXME: Maybe we have to check for a successfull
602 // query but an empty result
603 /* throws exceptions
604 if (!res1)
605 {
606 ostringstream msg;
607 msg << "MySQL query failed: " << query1.error();
608 T::Error(str);
609 return T::kSM_Error;
610 }*/
611 insertcount++;
612 }
613 counter3++;
614 }
615 ostringstream insertmsg;
616 insertmsg << "Inserted " << insertcount << " runs into the DB.";
617 T::Message(insertmsg);
618 //usleep(3000000);
619 T::Message("Scheduling done.");
620
621 return error;
622 }
623
624 /*
625 // commit probably done by webinterface
626 int Commit()
627 {
628 ostringstream str;
629 str << "Comitting preview (id=" << fSessionId << ")";
630 T::Message(str);
631
632 usleep(3000000);
633 T::Message("Comitted.");
634
635 fSessionId = -1;
636
637 bool error = false;
638 return error ? T::kSM_Error : T::kSM_Ready;
639 }
640 */
641
642 AutoScheduler(ostream &out=cout) : T(out, "SCHEDULER"), fNextIsPreview(true), fDBName("")
643 {
644 AddStateName(kSM_Scheduling, "Scheduling", "Scheduling in progress.");
645
646 AddEvent(kSM_Scheduling, "SCHEDULE", "C", T::kSM_Ready)
647 ("FIXME FIXME FIXME (explanation for the command)"
648 "|database[string]:FIXME FIXME FIMXE (meaning and format)");
649
650 AddEvent(T::kSM_Ready, "RESET", T::kSM_Error)
651 ("Reset command to get out of the error state");
652
653 //AddEvent(kSM_Comitting, "COMMIT", T::kSM_Ready);
654
655 T::PrintListOfEvents();
656 }
657
658 int Execute()
659 {
660 switch (T::GetCurrentState())
661 {
662 case kSM_Scheduling:
663 try
664 {
665 return Schedule() ? T::kSM_Error : T::kSM_Ready;
666 }
667 catch (const mysqlpp::Exception &e)
668 {
669 T::Error(string("MySQL: ")+e.what());
670 return T::kSM_Error;
671 }
672
673 // This does an autmatic reset (FOR TESTING ONLY)
674 case T::kSM_Error:
675 return T::kSM_Ready;
676 }
677 return T::GetCurrentState();
678 }
679
680 int Transition(const Event &evt)
681 {
682 switch (evt.GetTargetState())
683 {
684 case kSM_Scheduling:
685 if (evt.GetSize()>0)
686 fDBName = evt.GetText();
687 break;
688 }
689
690 return evt.GetTargetState();
691 }
692
693 int EvalOptions(Configuration &conf)
694 {
695 fDatabase = conf.Get<string>("schedule-database");
696 fDurationCalRun = conf.Get<int>("duration-cal-run");
697 fDurationPedRun = conf.Get<int>("duration-ped-run");
698 fDurationRepos = conf.Get<int>("duration-repos");
699
700 if (!conf.Has("schedule"))
701 return -1;
702
703 fDBName = conf.Get<string>("schedule");
704 return Schedule();
705 }
706
707};
708
709
710// ------------------------------------------------------------------------
711#include "Main.h"
712
713template<class T, class S>
714int RunShell(Configuration &conf)
715{
716 return Main::execute<T, AutoScheduler<S>>(conf);
717}
718
719void SetupConfiguration(Configuration &conf)
720{
721 po::options_description control("Scheduler options");
722 control.add_options()
723 ("no-dim", po_switch(), "Disable dim services")
724 ("schedule-database", var<string>()
725#if BOOST_VERSION >= 104200
726 ->required()
727#endif
728 , "Database link as in\n\tuser:password@server[:port]/database\nOverwrites options from the default configuration file.")
729 ("schedule", var<string>(), "")
730 ("mintime", var<int>(), "minimum observation time")
731 ("duration-cal-run", var<int>()
732#if BOOST_VERSION >= 104200
733 ->required()
734#endif
735 , "duration of calibration run [min]")
736 ("duration-ped-run", var<int>()
737#if BOOST_VERSION >= 104200
738 ->required()
739#endif
740 , "duration of pedestal run [min]")
741 ("duration-repos", var<int>()
742#if BOOST_VERSION >= 104200
743 ->required()
744#endif
745 , "duration of repositioning [min]")
746 ;
747
748 po::positional_options_description p;
749 p.add("schedule", 1); // The first positional options
750
751 conf.AddOptions(control);
752 conf.SetArgumentPositions(p);
753}
754
755void PrintUsage()
756{
757 cout <<
758 "The scheduler... TEXT MISSING\n"
759 "\n"
760 "The default is that the program is started without user intercation. "
761 "All actions are supposed to arrive as DimCommands. Using the -c "
762 "option, a local shell can be initialized. With h or help a short "
763 "help message about the usuage can be brought to the screen.\n"
764 "\n"
765 "Usage: scheduler [-c type] [OPTIONS] <schedule-database>\n"
766 " or: scheduler [OPTIONS] <schedule-database>\n";
767 cout << endl;
768}
769
770void PrintHelp()
771{
772 /* Additional help text which is printed after the configuration
773 options goes here */
774}
775
776int main(int argc, const char* argv[])
777{
778 Configuration conf(argv[0]);
779 conf.SetPrintUsage(PrintUsage);
780 Main::SetupConfiguration(conf);
781 SetupConfiguration(conf);
782
783 po::variables_map vm;
784 try
785 {
786 vm = conf.Parse(argc, argv);
787 }
788#if BOOST_VERSION > 104000
789 catch (po::multiple_occurrences &e)
790 {
791 cerr << "Program options invalid due to: " << e.what() << " of '" << e.get_option_name() << "'." << endl;
792 return -1;
793 }
794#endif
795 catch (exception& e)
796 {
797 cerr << "Program options invalid due to: " << e.what() << endl;
798 return -1;
799 }
800
801// try
802 {
803 // No console access at all
804 if (!conf.Has("console"))
805 {
806 if (conf.Get<bool>("no-dim"))
807 return RunShell<LocalStream, StateMachine>(conf);
808 else
809 return RunShell<LocalStream, StateMachineDim>(conf);
810 }
811 // Cosole access w/ and w/o Dim
812 if (conf.Get<bool>("no-dim"))
813 {
814 if (conf.Get<int>("console")==0)
815 return RunShell<LocalShell, StateMachine>(conf);
816 else
817 return RunShell<LocalConsole, StateMachine>(conf);
818 }
819 else
820 {
821 if (conf.Get<int>("console")==0)
822 return RunShell<LocalShell, StateMachineDim>(conf);
823 else
824 return RunShell<LocalConsole, StateMachineDim>(conf);
825 }
826 }
827/* catch (std::exception& e)
828 {
829 std::cerr << "Exception: " << e.what() << "\n";
830 }*/
831
832 return 0;
833}
Note: See TracBrowser for help on using the repository browser.