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