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

Last change on this file since 10596 was 10596, checked in by dorner, 9 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.