Ignore:
Timestamp:
06/14/11 18:04:59 (13 years ago)
Author:
tbretz
Message:
Many structural updates; catch mysqlpp exceptions outside Scheudle(); added error state; added reset command to get out of the error state
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/FACT++/src/scheduler.cc

    r10997 r11019  
    99#include <boost/thread.hpp>
    1010#include <boost/regex.hpp>
    11 #include <boost/asio/deadline_timer.hpp>
    12 #include <boost/date_time/posix_time/posix_time.hpp>
    1311
    1412#include <mysql++/mysql++.h>
     
    2826#include "tools.h"
    2927
    30 namespace ba    = boost::asio;
    31 namespace bs    = boost::system;
    32 
    33 using ba::deadline_timer;
    34 using ba::ip::tcp;
    35 
    3628using namespace std;
    3729using namespace boost::gregorian;
     
    4133// * do not use --database, but sth like --database-scheduler
    4234//   to be independent of the configuration database
    43 // * check if the following include is really needed
    44 //   #include <boost/date_time/posix_time/posix_time.hpp>
    45 // * string database not as global variable
    46 //   pass reference to conf and the string as a member of the class
    47 //   (see chat of 4.5.2011)
    4835// * move definition of config parameters to AutoScheduler class
    4936//   + read in from config
     
    9885        float ra;
    9986        float dec;
    100         boost::posix_time::ptime starttime;
    101         boost::posix_time::ptime stoptime;
    102         boost::posix_time::time_duration duration_db;
     87        ptime start;
     88        ptime stop;
     89        time_duration duration_db;
    10390        string sourcename;
    10491        int sourcekey;
     
    10794    struct FixedObs
    10895    {
    109         int obskey_fixed;
    110         int sourcekey_fixed;
    111         string sourcename_fixed;
    112         int obsmode_fixed;
    113         int obstype_fixed;
    114         int telsetup_fixed;
    115         float ra_fixed;
    116         float dec_fixed;
    117         boost::posix_time::ptime obsfixedstart;
    118         boost::posix_time::ptime obsfixedstop;
     96        int obskey;
     97        int sourcekey;
     98        string sourcename;
     99        int obsmode;
     100        int obstype;
     101        int telsetup;
     102        float ra;
     103        float dec;
     104        ptime start;
     105        ptime stop;
    119106    };
    120107
     
    137124        float ra_std;
    138125        float dec_std;
    139         boost::posix_time::ptime obsstdstart;
    140         boost::posix_time::ptime obsstdstop;
     126        ptime obsstdstart;
     127        ptime obsstdstop;
    141128    };
    142129
     
    148135        int obstype_obs;
    149136        int telsetup_obs;
    150         boost::posix_time::ptime obsstart;
    151         boost::posix_time::ptime obsstop;
     137        ptime obsstart;
     138        ptime obsstop;
    152139    };
    153140
     
    161148        int obstype_run;
    162149        int telsetup_run;
    163         boost::posix_time::ptime runstart;
    164         boost::posix_time::ptime runstop;
     150        ptime runstart;
     151        ptime runstop;
    165152    };
    166153
     
    175162        bool error = false;
    176163
    177         boost::posix_time::time_duration runtimec(0, 3, 0);
    178         boost::posix_time::time_duration runtimep(0, 3, 0);
    179         boost::posix_time::time_duration mintime(1, 0, 0);
    180         boost::posix_time::time_duration repostime(0, 5, 0);
    181         //boost::posix_time::ptime startsched=microsec_clock::local_time();
    182         boost::posix_time::ptime startsched(microsec_clock::local_time());
    183         boost::posix_time::ptime stopsched=startsched+years(1);
    184         cout << "Scheduling for the period from " << startsched << " to " << stopsched << endl;
     164        time_duration runtimec(0, 3, 0);
     165        time_duration runtimep(0, 3, 0);
     166        time_duration mintime(1, 0, 0);
     167        time_duration repostime(0, 5, 0);
     168        //ptime startsched=microsec_clock::local_time();
     169        ptime startsched(microsec_clock::local_time());
     170        ptime stopsched=startsched+years(1);
     171
     172        ostringstream str;
     173        str << "Scheduling for the period from " << startsched << " to " << stopsched;
     174        T::Message(str);
    185175
    186176        static const boost::regex expr("(([[:word:].-]+)(:(.+))?@)?([[:word:].-]+)(:([[:digit:]]+))?(/([[:word:].-]+))");
     
    194184        if (!boost::regex_match(fDatabase, what, expr, boost::match_extra))
    195185        {
    196             cout << "Couldn't parse '" << fDatabase << "'." << endl;
    197             throw;
     186            ostringstream msg;
     187            msg << "Regex to parse database '" << fDatabase << "' empty.";
     188            T::Error(msg);
     189            return T::kSM_Error;
    198190        }
    199191
    200192        if (what.size()!=10)
    201193        {
    202             cout << "Error parsing '" << fDatabase << "'." << endl;
    203             throw;
     194            ostringstream msg;
     195            msg << "Parsing database name failed: '" << fDatabase << "'";
     196            T::Error(msg);
     197            return T::kSM_Error;
    204198        }
    205199
     
    216210        T::Message(dbnamemsg);
    217211
    218         cout << "Connecting to '";
     212        str.str("");
     213        str << "Connecting to '";
    219214        if (!user.empty())
    220             cout << user << "@";
    221         cout << server;
     215            str << user << "@";
     216        str << server;
    222217        if (port)
    223             cout << ":" << port;
     218            str << ":" << port;
    224219        if (!db.empty())
    225             cout << "/" << db;
    226         cout << "'" << endl;
     220            str << "/" << db;
     221        str << "'";
     222        T::Info(str);
    227223
    228224        mysqlpp::Connection conn(db.c_str(), server.c_str(), user.c_str(), passwd.c_str(), port);
     225        /* throws exceptions
    229226        if (!conn.connected())
    230227        {
    231             cout << "MySQL connection error: " << conn.error() << endl;
    232             throw;
    233         }
     228            ostringstream msg;
     229            msg << "MySQL connection error: " << conn.error();
     230            T::Error(msg);
     231            return T::kSM_Error;
     232        }*/
    234233
    235234        // get observation parameters from DB
    236235        // maybe order by priority?
    237         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");
    238 
    239         mysqlpp::StoreQueryResult res = query.store();
     236        const mysqlpp::StoreQueryResult res =
     237            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();
     238        // FIXME: Maybe we have to check for a successfull
     239        //        query but an empty result
     240        /* thorws exceptions?
    240241        if (!res)
    241242        {
    242             cout << "MySQL query failed: " << query.error() << endl;
    243             throw;
    244         }
    245 
    246         cout << "Found " << res.num_rows() << " Observation Parameter sets." << endl;
     243            ostringstream msg;
     244            msg << "MySQL query failed: " << query.error();
     245            T::Error(msg);
     246            return T::kSM_Error;
     247        }*/
     248
     249        str.str("");
     250        str << "Found " << res.num_rows() << " Observation Parameter sets.";
     251        T::Debug(str);
    247252
    248253        ObservationParameters olist[res.num_rows()];
    249         std::vector<FixedObs> obsfixedlist;
    250         std::vector<StdObs> obsstdlist;
    251         std::vector<ScheduledObs> obslist;
    252         std::vector<ScheduledRun> runlist;
     254        vector<FixedObs> obsfixedlist;
     255        vector<StdObs> obsstdlist;
     256        vector<ScheduledObs> obslist;
     257        vector<ScheduledRun> runlist;
    253258
    254259        // loop over observation parameters from DB
     
    258263        int counter3=0;
    259264        cout << "Obs: <obskey> <sourcename>(<sourcekey>, <fluxweight>) from <starttime> to <stoptime>" << endl;
    260         for (vector<mysqlpp::Row>::iterator v=res.begin(); v<res.end(); v++)
     265        for (vector<mysqlpp::Row>::const_iterator v=res.begin(); v<res.end(); v++)
    261266        {
    262267            cout << "  Obs: " << (*v)[0].c_str() << " " << (*v)[4].c_str() << "(" << (*v)[5].c_str() << flush;
     
    287292
    288293            //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;
     294            t1 >> Time::sql >> olist[counter].start;
     295            t2 >> Time::sql >> olist[counter].stop;
    291296            t3 >> olist[counter].duration_db;
    292             boost::posix_time::time_period period(olist[counter].starttime, olist[counter].stoptime);
     297            const time_period period(olist[counter].start, olist[counter].stop);
     298
    293299            olist[counter].sourcename=(*v)[4].c_str();
    294300            olist[counter].sourcekey=(*v)[5];
     
    318324
    319325            // time_duration cannot be used, as only up to 99 hours are handeled
    320             boost::posix_time::time_duration duration = period.length();
     326            const time_duration duration = period.length();
    321327
    322328            /*
     
    354360
    355361            // fixed observations
    356             if (!(olist[counter].stoptime.is_not_a_date_time()
    357                   && olist[counter].starttime.is_not_a_date_time())
     362            if (!(olist[counter].stop.is_not_a_date_time()
     363                  && olist[counter].start.is_not_a_date_time())
    358364                && olist[counter].fluxweight==0
    359365               )
    360366            {
    361367                obsfixedlist.resize(counter2+1);
    362                 obsfixedlist[counter2].obsfixedstart=olist[counter].starttime;
    363                 obsfixedlist[counter2].obsfixedstop=olist[counter].stoptime;
    364                 obsfixedlist[counter2].sourcename_fixed=olist[counter].sourcename;
    365                 obsfixedlist[counter2].obskey_fixed=olist[counter].obskey;
    366                 obsfixedlist[counter2].obstype_fixed=olist[counter].obstype;
    367                 obsfixedlist[counter2].obsmode_fixed=olist[counter].obsmode;
    368                 obsfixedlist[counter2].telsetup_fixed=olist[counter].telsetup;
    369                 obsfixedlist[counter2].sourcekey_fixed=olist[counter].sourcekey;
    370                 obsfixedlist[counter2].ra_fixed=olist[counter].ra;
    371                 obsfixedlist[counter2].dec_fixed=olist[counter].dec;
     368                obsfixedlist[counter2].start=olist[counter].start;
     369                obsfixedlist[counter2].stop=olist[counter].stop;
     370                obsfixedlist[counter2].sourcename=olist[counter].sourcename;
     371                obsfixedlist[counter2].obskey=olist[counter].obskey;
     372                obsfixedlist[counter2].obstype=olist[counter].obstype;
     373                obsfixedlist[counter2].obsmode=olist[counter].obsmode;
     374                obsfixedlist[counter2].telsetup=olist[counter].telsetup;
     375                obsfixedlist[counter2].sourcekey=olist[counter].sourcekey;
     376                obsfixedlist[counter2].ra=olist[counter].ra;
     377                obsfixedlist[counter2].dec=olist[counter].dec;
    372378                counter2++;
    373379            }
    374380
    375381            // std obs
    376             if (olist[counter].stoptime.is_not_a_date_time()
    377                   && olist[counter].starttime.is_not_a_date_time()
     382            if (olist[counter].stop.is_not_a_date_time()
     383                  && olist[counter].start.is_not_a_date_time()
    378384                && olist[counter].fluxweight>0
    379385               )
     
    416422        counter2=0;
    417423        int skipcounter=0;
    418         boost::posix_time::ptime finalobsfixedstart;
    419         boost::posix_time::ptime finalobsfixedstop;
    420         boost::posix_time::time_duration delta1;
    421         boost::posix_time::time_duration delta2;
    422         boost::posix_time::time_duration delta0(0,0,0);
    423         struct vector<FixedObs>::iterator vobs;
    424         struct vector<FixedObs>::iterator vobs5;
     424        ptime finalobsfixedstart;
     425        ptime finalobsfixedstop;
     426        time_duration delta0(0,0,0);
     427
    425428        cout << "Fixed Observations: " << endl;
    426         for (vobs=obsfixedlist.begin(); vobs!=obsfixedlist.end(); vobs++)
    427         {
    428             if (obsfixedlist[counter2].obsfixedstart < startsched
    429                 || obsfixedlist[counter2].obsfixedstop > stopsched)
     429        for (struct vector<FixedObs>::const_iterator vobs=obsfixedlist.begin(); vobs!=obsfixedlist.end(); vobs++)
     430        {
     431            if (obsfixedlist[counter2].start < startsched
     432                || obsfixedlist[counter2].stop > stopsched)
    430433            {
    431434                ostringstream skipfixedobsmsg;
    432                 skipfixedobsmsg  << "Skip 1 fixed observation (obskey " << obsfixedlist[counter2].obskey_fixed << ") as it is out of scheduling time range.";
     435                skipfixedobsmsg << "Skip 1 fixed observation (obskey ";
     436                skipfixedobsmsg << obsfixedlist[counter2].obskey;
     437                skipfixedobsmsg << ") as it is out of scheduling time range.";
    433438                T::Message(skipfixedobsmsg);
     439
    434440                counter2++;
    435441                skipcounter++;
     
    437443            }
    438444            counter3=0;
    439             delta1=delta0;
    440             delta2=delta0;
    441             finalobsfixedstart=obsfixedlist[counter2].obsfixedstart;
    442             finalobsfixedstop=obsfixedlist[counter2].obsfixedstop;
    443 
    444             for (vobs5=obsfixedlist.begin(); vobs5!=obsfixedlist.end(); vobs5++)
     445
     446            time_duration delta1=delta0;
     447            time_duration delta2=delta0;
     448
     449            finalobsfixedstart=obsfixedlist[counter2].start;
     450            finalobsfixedstop=obsfixedlist[counter2].stop;
     451
     452            for (struct vector<FixedObs>::const_iterator vobs5=obsfixedlist.begin(); vobs5!=obsfixedlist.end(); vobs5++)
    445453            {
    446                 if ((*vobs5).obsfixedstart < obsfixedlist[counter2].obsfixedstop
    447                     && obsfixedlist[counter2].obsfixedstop <= (*vobs5).obsfixedstop
    448                     && obsfixedlist[counter2].obsfixedstart <= (*vobs5).obsfixedstart
     454                if (vobs5->start < obsfixedlist[counter2].stop
     455                    && obsfixedlist[counter2].stop <= vobs5->stop
     456                    && obsfixedlist[counter2].start <= vobs5->start
    449457                    && counter2!=counter3)
    450458                {
    451                     delta1=(obsfixedlist[counter2].obsfixedstop-(*vobs5).obsfixedstart)/2;
    452                     finalobsfixedstop=obsfixedlist[counter2].obsfixedstop-delta1;
     459                    delta1=(obsfixedlist[counter2].stop-vobs5->start)/2;
     460                    finalobsfixedstop=obsfixedlist[counter2].stop-delta1;
     461
    453462                    ostringstream warndelta1;
    454                     warndelta1 << "Overlap between two fixed observations (" << obsfixedlist[counter2].obskey_fixed << " " << (*vobs5).obskey_fixed << "). The stoptime of " << obsfixedlist[counter2].obskey_fixed << " has been changed.";
     463                    warndelta1 << "Overlap between two fixed observations (";
     464                    warndelta1 << obsfixedlist[counter2].obskey << " ";
     465                    warndelta1 << vobs5->obskey << "). The stoptime of ";
     466                    warndelta1 << obsfixedlist[counter2].obskey << " has been changed.";
    455467                    T::Warn(warndelta1);
    456468                }
    457                 if ((*vobs5).obsfixedstart <= obsfixedlist[counter2].obsfixedstart
    458                     && obsfixedlist[counter2].obsfixedstart < (*vobs5).obsfixedstop
    459                     && obsfixedlist[counter2].obsfixedstop >= (*vobs5).obsfixedstop
     469                if (vobs5->start <= obsfixedlist[counter2].start
     470                    && obsfixedlist[counter2].start < vobs5->stop
     471                    && obsfixedlist[counter2].stop >= vobs5->stop
    460472                    && counter2!=counter3)
    461473                {
    462                     delta2=((*vobs5).obsfixedstop-obsfixedlist[counter2].obsfixedstart)/2;
    463                     finalobsfixedstart=obsfixedlist[counter2].obsfixedstart+delta2;
     474                    delta2=(vobs5->stop-obsfixedlist[counter2].start)/2;
     475                    finalobsfixedstart=obsfixedlist[counter2].start+delta2;
     476
    464477                    ostringstream warndelta2;
    465                     warndelta2 << "Overlap between two fixed observations (" << obsfixedlist[counter2].obskey_fixed << " " << (*vobs5).obskey_fixed << "). The starttime of " << obsfixedlist[counter2].obskey_fixed << " has been changed.";
     478                    warndelta2 << "Overlap between two fixed observations (";
     479                    warndelta2 << obsfixedlist[counter2].obskey << " ";
     480                    warndelta2 << vobs5->obskey << "). The starttime of ";
     481                    warndelta2 << obsfixedlist[counter2].obskey << " has been changed.";
     482
    466483                    T::Warn(warndelta2);
    467484                }
     
    469486            }
    470487
    471             int num=counter2-skipcounter;
     488            const int num=counter2-skipcounter;
    472489            obslist.resize(num+1);
    473490            obslist[num].obsstart=finalobsfixedstart;
    474491            obslist[num].obsstop=finalobsfixedstop;
    475             obslist[num].sourcename_obs=obsfixedlist[counter2].sourcename_fixed;
    476             obslist[num].obsmode_obs=obsfixedlist[counter2].obsmode_fixed;
    477             obslist[num].obstype_obs=obsfixedlist[counter2].obstype_fixed;
    478             obslist[num].telsetup_obs=obsfixedlist[counter2].telsetup_fixed;
    479             obslist[num].sourcekey_obs=obsfixedlist[counter2].sourcekey_fixed;
     492            obslist[num].sourcename_obs=obsfixedlist[counter2].sourcename;
     493            obslist[num].obsmode_obs=obsfixedlist[counter2].obsmode;
     494            obslist[num].obstype_obs=obsfixedlist[counter2].obstype;
     495            obslist[num].telsetup_obs=obsfixedlist[counter2].telsetup;
     496            obslist[num].sourcekey_obs=obsfixedlist[counter2].sourcekey;
    480497            counter2++;
    481             cout << "  " << (*vobs).sourcename_fixed <<  " " << (*vobs).obsfixedstart << flush;
    482             cout << " - " << (*vobs).obsfixedstop << endl;
     498
     499            cout << "  " << vobs->sourcename <<  " " << vobs->start;
     500            cout << " - " << vobs->stop << endl;
    483501        }
    484502        ostringstream obsmsg;
     
    512530        // the observation times shall be calculated
    513531        // and the observations added to the ScheduledObs list
    514         struct vector<StdObs>::iterator vobs2;
    515532        cout << "Standard Observations: " << endl;
    516         for (vobs2=obsstdlist.begin(); vobs2!=obsstdlist.end(); vobs2++)
    517         {
    518             cout << "  " << (*vobs2).sourcename_std << endl;
     533        for (struct vector<StdObs>::const_iterator vobs2=obsstdlist.begin(); vobs2!=obsstdlist.end(); vobs2++)
     534        {
     535            cout << "  " << vobs2->sourcename_std << endl;
    519536        }
    520537
     
    523540        // might be merged with next loop
    524541        counter2=0;
    525         struct vector<ScheduledObs>::iterator vobs3;
    526         for (vobs3=obslist.begin(); vobs3!=obslist.end(); vobs3++)
     542        for (struct vector<ScheduledObs>::const_iterator vobs3=obslist.begin(); vobs3!=obslist.end(); vobs3++)
    527543        {
    528544            runlist.resize(counter2+1);
     
    539555
    540556        //delete old scheduled runs from the DB
    541         mysqlpp::Query query0 = conn.query("DELETE FROM ScheduledRun");
    542 
    543         mysqlpp::SimpleResult res0 = query0.execute();
     557        const mysqlpp::SimpleResult res0 =
     558            conn.query("DELETE FROM ScheduledRun").execute();
     559        // FIXME: Maybe we have to check for a successfull
     560        //        query but an empty result
     561        /* throws exceptions
    544562        if (!res0)
    545563        {
    546             cout << "MySQL query failed: " << query0.error() << endl;
    547             throw;
    548         }
     564            ostringstream msg;
     565            msg << "MySQL query failed: " << query0.error();
     566            T::Error(msg);
     567            return T::kSM_Error;
     568        }*/
    549569
    550570        // in this loop the ScheduledRuns are inserted to the DB
     
    553573        counter3=0;
    554574        int insertcount=0;
    555         boost::posix_time::ptime finalstarttime;
    556         boost::posix_time::ptime finalstoptime;
    557         struct vector<ScheduledRun>::iterator vobs4;
    558         for (vobs4=runlist.begin(); vobs4!=runlist.end(); vobs4++)
     575        ptime finalstarttime;
     576        ptime finalstoptime;
     577        for (struct vector<ScheduledRun>::const_iterator vobs4=runlist.begin(); vobs4!=runlist.end(); vobs4++)
    559578        {
    560579            for (int i=2; i<5; i++)
     
    588607                //cout << "executing query: " << q1.str() << endl;
    589608
    590                 mysqlpp::Query query1 = conn.query(q1.str());
    591 
    592                 mysqlpp::SimpleResult res1 = query1.execute();
     609                const mysqlpp::SimpleResult res1 = conn.query(q1.str()).execute();
     610                // FIXME: Maybe we have to check for a successfull
     611                //        query but an empty result
     612                /* throws exceptions
    593613                if (!res1)
    594614                {
    595                     cout << "MySQL query failed: " << query1.error() << endl;
    596                     throw;
    597                 }
     615                    ostringstream msg;
     616                    msg << "MySQL query failed: " << query1.error();
     617                    T::Error(str);
     618                    return T::kSM_Error;
     619                }*/
    598620                insertcount++;
    599621            }
     
    608630        fSessionId = -1;
    609631
    610         //bool error = false;
    611632        return error ? T::kSM_Error : T::kSM_Ready;
    612633    }
     
    632653    AutoScheduler(ostream &out=cout) : T(out, "SCHEDULER"), fNextIsPreview(true), fSessionId(-1), fDBName("")
    633654    {
    634         AddStateName(kSM_Scheduling,  "Scheduling");
    635         //AddStateName(kSM_Comitting,   "Comitting");
    636 
    637         AddEvent(kSM_Scheduling, "SCHEDULE", T::kSM_Ready);
     655        AddStateName(kSM_Scheduling, "Scheduling", "Scheduling in progress.");
     656
     657        AddEvent(kSM_Scheduling, "SCHEDULE", "C", T::kSM_Ready)
     658            ("FIXME FIXME FIXME (explanation for the command)"
     659             "|database[string]:FIXME FIXME FIMXE (meaning and format)");
     660
     661        AddEvent(T::kSM_Ready, "RESET", T::kSM_Error)
     662            ("Reset command to get out of the error state");
     663
    638664        //AddEvent(kSM_Comitting,  "COMMIT",   T::kSM_Ready);
    639665
     
    646672        {
    647673        case kSM_Scheduling:
    648             return Schedule();
     674            try
     675            {
     676                return Schedule();
     677            }
     678            catch (const mysqlpp::Exception &e)
     679            {
     680                T::Error(string("MySQL: ")+e.what());
     681                return T::kSM_Error;
     682            }
     683
     684            // This does an autmatic reset (FOR TESTING ONLY)
     685        case T::kSM_Error:
     686            return T::kSM_Ready;
    649687
    650688        //case kSM_Comitting:
     
    811849        vm = conf.Parse(argc, argv);
    812850    }
    813     catch (std::exception &e)
    814     {
    815851#if BOOST_VERSION > 104000
    816         po::multiple_occurrences *MO = dynamic_cast<po::multiple_occurrences*>(&e);
    817         if (MO)
    818             cout << "Error: " << e.what() << " of '" << MO->get_option_name() << "' option." << endl;
    819         else
     852    catch (po::multiple_occurrences &e)
     853    {
     854        cerr << "Program options invalid due to: " << e.what() << " of '" << e.get_option_name() << "'." << endl;
     855        return -1;
     856    }
    820857#endif
    821             cout << "Error: " << e.what() << endl;
    822         cout << endl;
    823 
     858    catch (exception& e)
     859    {
     860        cerr << "Program options invalid due to: " << e.what() << endl;
    824861        return -1;
    825862    }
Note: See TracChangeset for help on using the changeset viewer.