Changeset 14128


Ignore:
Timestamp:
06/08/12 18:06:52 (12 years ago)
Author:
tbretz
Message:
Replaced old code with the new use of a full state machine implementation.
File:
1 edited

Legend:

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

    r14052 r14128  
    1 #ifndef FACT_DimCtrl
    2 #define FACT_DimCtrl
    3 
    4 #include "Main.h"
    5 #include "tools.h"
    6 #include "MessageDim.h"
     1#include "StateMachineDimControl.h"
    72#include "RemoteControl.h"
    8 
    9 #include "InterpreterV8.h"
    103
    114using namespace std;
    125
    13 // ========================================================================
     6// ------------------------------------------------------------------------
    147
     8#include "Main.h"
     9
     10template<class T>
     11int RunShell(Configuration &conf)
     12{
     13    StateMachineDimControl::fIsServer = conf.Get<bool>("server");
     14    return Main::execute<T, StateMachineDimControl>(conf);
     15}
     16
     17void SetupConfiguration(Configuration &conf)
     18{
     19    po::options_description control("Dim control options");
     20    control.add_options()
     21        ("server",       po_bool(false),  "Start dimctrl as a dim server")
     22        // ("verbosity,v",  var<uint32_t>()->implicit_value(0), "Set a new verbosity level (see MessageImp)")
     23        // ("quiet,q",      po_bool(false),  "Suppress all output except comments (log-level>=90)")
     24        ("debug",        po_bool(false),  "Print the labels for debugging purpose")
     25        ("start",        var<string>(),   "Start a java script with the given name")
     26        ("batch",        var<string>(),   "Start a batch script with the given name at the given label (script.dim[:N])")
     27        ("stop",         po_switch(),     "Stop a currently running script")
     28        ("user,u",       var<string>(""), "A user name - just for logging purposes (default is ${USER})")
     29        ;
     30
     31    conf.AddEnv("user", "USER");
     32
     33    conf.AddOptions(control);
     34}
    1535
    1636/*
     
    2545void PrintUsage()
    2646{
    27     cout << "\n"
    28         "The console connects to all available Dim Servers and allows to "
    29         "easily access all of their commands.\n"
     47    cout <<
     48        "The feedback control the BIAS voltages based on the calibration signal.\n"
    3049        "\n"
    31         "Usage: dimctrl [-c type] [OPTIONS]\n"
    32         "  or:  dimctrl [OPTIONS]\n\n";
     50        "The default is that the program is started without user intercation. "
     51        "All actions are supposed to arrive as DimCommands. Using the -c "
     52        "option, a local shell can be initialized. With h or help a short "
     53        "help message about the usuage can be brought to the screen.\n"
     54        "\n"
     55        "Usage: feedback [-c type] [OPTIONS]\n"
     56        "  or:  feedback [OPTIONS]\n";
    3357    cout << endl;
    3458}
     
    3660void PrintHelp()
    3761{
    38     Main::PrintUsage();
     62    Main::PrintHelp<StateMachineDimControl>();
     63
     64    /* Additional help text which is printed after the configuration
     65     options goes here */
     66
     67    /*
     68     cout << "bla bla bla" << endl << endl;
     69     cout << endl;
     70     cout << "Environment:" << endl;
     71     cout << "environment" << endl;
     72     cout << endl;
     73     cout << "Examples:" << endl;
     74     cout << "test exam" << endl;
     75     cout << endl;
     76     cout << "Files:" << endl;
     77     cout << "files" << endl;
     78     cout << endl;
     79     */
    3980}
    4081
    41 // A simple dummy state machine
    42 class DimCtrl : public MainImp, public DimCommandHandler, public MessageDimTX
    43 {
    44     int    fLabel;
    45     int    fStop;
    46     int    fVerbosity;
    47     bool   fDebug;
    48     bool   fIsServer;
    49     string fUser;
    50 
    51     DimDescribedService fSrvState;
    52     DimCommand          fDimStart;
    53     DimCommand          fDimStop;
    54 
    55     map<string,string> fData;
    56     string fScript;
    57     string fScriptUser;
    58 
    59     void ProcessStart()
    60     {
    61         if (!fScript.empty() || fLabel>-3)
    62         {
    63             Error("Script execution still in progress.");
    64             return;
    65         }
    66 
    67         string opt(fDimStart.getString());
    68 
    69         fData = Tools::Split(opt);
    70 
    71         if (opt.size()>0)
    72             Debug("Start '"+opt+"' received.");
    73 
    74         if (fDebug)
    75             Debug("Received data: "+string(fDimStart.getString()));
    76 
    77         if (opt.size()==0)
    78         {
    79             if (fData.size()==0)
    80                 Error("File name missing in DIM_CONTROL/START");
    81             else
    82                 Error("Equal sign missing in argument '"+fData.begin()->first+"'");
    83 
    84             return;
    85         }
    86 
    87         const auto user = fData.find("user");
    88         if (user!=fData.end())
    89             fScriptUser = user->second;
    90 
    91         if (fDebug)
    92         {
    93             for (auto it=fData.begin(); it!=fData.end(); it++)
    94                 Debug("   Arg: "+it->first+" = "+it->second);
    95         }
    96 
    97         fScript = opt;
    98     }
    99 
    100     void StopScript()
    101     {
    102         Readline::StopScript();
    103         InterpreterV8::JsStop();
    104     }
    105 
    106     void commandHandler()
    107     {
    108         if (getCommand()==&fDimStop)
    109         {
    110             const string user = fDimStop.getSize()>0 ? fDimStop.getString() : "";
    111 
    112             string msg = "Stop received";
    113             if (!user.empty())
    114                 msg += " from user '"+user+"'";
    115 
    116             Debug(msg);
    117             StopScript();
    118         }
    119 
    120         if (getCommand()==&fDimStart)
    121             ProcessStart();
    122     }
    123 
    124 public:
    125     DimCtrl(ostream &out=cout) : MessageDimTX("DIM_CONTROL", out),
    126         fLabel(-3), fStop(-1), fVerbosity(0), fDebug(false), fIsServer(false),
    127         fSrvState("DIM_CONTROL/STATE", "C",
    128                   "Provides the state of the state machine as quality of service."
    129                   "|Text[string]:A human readable string sent by the last state change."),
    130         fDimStart("DIM_CONTROL/START", "C", this),
    131         fDimStop("DIM_CONTROL/STOP", "C", this)
    132     {
    133     }
    134     ~DimCtrl()
    135     {
    136         DimServer::stop();
    137     }
    138 
    139     bool check(string &str)
    140     {
    141         for (auto c=str.begin(); c<str.end(); c++)
    142         {
    143             if ((*c>='A' && *c<='Z') || *c=='_')
    144                 continue;
    145 
    146             if (*c++!=':')
    147                 return false;
    148 
    149             if (c==str.end())
    150                 return false;
    151 
    152             if (*c!=' ')
    153                 return false;
    154 
    155             str = string(c+1, str.end());
    156             return true;
    157         }
    158 
    159         return false;
    160     }
    161 
    162     string Line(const string &txt, char fill)
    163     {
    164         const int n = (55-txt.length())/2;
    165 
    166         ostringstream out;
    167         out << setfill(fill);
    168         out << setw(n) << fill << ' ';
    169         out << txt;
    170         out << ' ' << setw(n) << fill;
    171 
    172         if (2*n+txt.length()+2 != 57)
    173             out << fill;
    174 
    175         return out.str();
    176     }
    177 
    178     int ChangeState(int qos, const Time &time=Time())
    179     {
    180         ostringstream pid;
    181         pid << getpid();
    182 
    183         fLabel = qos;
    184 
    185         string msg;
    186         switch (fLabel)
    187         {
    188         case -4: msg = "Boot";  break;
    189         case -3: msg = "End";   break;
    190         case -2: msg = "Load";  break;
    191         case -1: msg = "Start"; break;
    192         default:
    193             {
    194                 ostringstream out;
    195                 out << "Label " << fLabel;
    196                 msg = out.str();
    197             }
    198         }
    199 
    200         if (fLabel<0)
    201             msg += "-"+to_string(Readline::GetScriptDepth());
    202 
    203         msg += ": "+Readline::GetScript()+" [";
    204         if (!fScriptUser.empty())
    205             msg += fScriptUser+":"+pid.str();
    206         msg += "]";
    207 
    208         if (fDebug)
    209             MessageDimTX::Write(time, Line(msg, fLabel<-1 ? '=' :'-'), 90);
    210 
    211         fSrvState.setQuality(fLabel);
    212         return fSrvState.Update(msg);
    213     }
    214 
    215     int Write(const Time &time, const std::string &txt, int qos=kMessage)
    216     {
    217         if (txt=="")
    218             return ChangeState(qos, time);
    219 
    220         if (qos<fVerbosity)
    221             return 0;
    222 
    223         // Avoid recursions
    224         if (fIsServer && txt.substr(0, 13)=="DIM_CONTROL: ")
    225             return 0;
    226 
    227         // Don't send received messages via dim
    228         string cpy(txt);
    229         if (fIsServer && check(cpy))
    230             return MessageImp::Write(time, cpy, qos);
    231 
    232         // Send all of our own messages via dim
    233         return MessageDimTX::Write(time, txt, qos);
    234     }
    235 
    236     int EvalOptions(Configuration &conf)
    237     {
    238         fVerbosity = 90;
    239 
    240         fUser = conf.Get<string>("user");
    241         fScriptUser = fUser;
    242 
    243         if (conf.Get<bool>("stop"))
    244             return Dim::SendCommand("DIM_CONTROL/STOP", fUser) + 1;
    245 
    246         if (conf.Has("start"))
    247             return Dim::SendCommand("DIM_CONTROL/START", conf.Get<string>("start")+" user="+fUser) + 1;
    248 
    249         fVerbosity = 40;
    250 
    251         if (conf.Has("verbosity"))
    252             fVerbosity = conf.Get<uint32_t>("verbosity");
    253 
    254         if (conf.Get<bool>("quiet"))
    255             fVerbosity = 90;
    256 
    257         fIsServer = conf.Get<bool>("server");
    258         fDebug    = conf.Get<bool>("debug");
    259 
    260         if (fIsServer)
    261         {
    262             // Sleep needed to ensure that the server can send
    263             // an EXIT if another instance is already running
    264             DimServer::start("DIM_CONTROL");
    265             //sleep(1);
    266             ChangeState(-4);
    267         }
    268 
    269         return -1;
    270     }
    271 
    272     void Stop(int stop=0) { fStop = stop; StopScript(); }
    273     int Run(bool)
    274     {
    275         while (fStop<0)
    276         {
    277             const string s = fScript;
    278             if (!s.empty())
    279             {
    280                 Readline::Instance()->Execute(s, fData);
    281                 fScript = "";
    282                 fScriptUser = fUser;
    283             }
    284 
    285             usleep(1000);
    286         }
    287 
    288         return fStop;
    289     }
    290 
    291 };
    292 
    293 void SetupConfiguration(Configuration &conf)
    294 {
    295     po::options_description control("Dim Control");
    296     control.add_options()
    297         ("server",      po_bool(false),  "Start dimctrl as a dim server")
    298         ("verbosity,v", var<uint32_t>()->implicit_value(0), "Set a new verbosity level (see MessageImp)")
    299         ("quiet,q",     po_bool(false),  "Suppress all output except comments (log-level>=90)")
    300         ("debug",       po_bool(false),  "Print the labels for debugging purpose")
    301         ("start",       var<string>(),   "Start a script with the given name at the given label (script.dim[:N])")
    302         ("stop",        po_switch(),     "Stop a currently running script")
    303         ("user,u",      var<string>(""), "A user name - just for logging purposes (default is ${USER})")
    304         ;
    305 
    306     conf.AddEnv("user", "USER");
    307 
    308     conf.AddOptions(control);
    309 }
    310 
    311 int main(int argc, const char *argv[])
     82int main(int argc, const char* argv[])
    31283{
    31384    Configuration conf(argv[0]);
     
    31990        return 127;
    32091
     92    //return RunShell<LocalStream>(conf);
     93
    32194    if (!conf.Has("console"))
    322         return Main::execute<RemoteStream, DimCtrl>(conf);
     95        return RunShell<RemoteStream>(conf);
    32396
    32497    if (conf.Get<int>("console")==0)
    325         return Main::execute<RemoteShell, DimCtrl>(conf);
     98        return RunShell<RemoteShell>(conf);
    32699    else
    327         return Main::execute<RemoteConsole, DimCtrl>(conf);
    328 
    329     return 0;
     100        return RunShell<RemoteConsole>(conf);
    330101}
    331 #endif
Note: See TracChangeset for help on using the changeset viewer.