Changeset 13671 for trunk


Ignore:
Timestamp:
05/12/12 12:41:13 (12 years ago)
Author:
tbretz
Message:
Added the possibility to remote control the DIM_CONTROL, i.e. start and stop scripts
File:
1 edited

Legend:

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

    r13006 r13671  
     1#ifndef FACT_DimCtrl
     2#define FACT_DimCtrl
     3
     4#include "Main.h"
     5#include "tools.h"
     6#include "MessageDim.h"
    17#include "RemoteControl.h"
    2 #include "Main.h"
    38
    49using namespace std;
     
    3338
    3439// A simple dummy state machine
    35 class DimCtrl : public MainImp, public MessageImp
    36 {
    37     bool fStop;
     40class DimCtrl : public MainImp, public DimCommandHandler, public MessageDimTX
     41{
     42    int  fLabel;
     43    int  fStop;
     44    int  fVerbosity;
     45    bool fDebug;
     46    bool fIsServer;
     47
     48    DimDescribedService fSrvState;
     49    DimCommand          fDimStart;
     50    DimCommand          fDimStop;
     51
     52    map<string,string> fData;
     53    string fScript;
     54
     55    void ProcessStart()
     56    {
     57        if (!fScript.empty() || fLabel>=0)
     58        {
     59            Error("Script execution still in progress.");
     60            return;
     61        }
     62
     63        string opt(fDimStart.getString());
     64
     65        fData = Tools::Split(opt);
     66
     67        if (opt.size()==0)
     68        {
     69            if (fData.size()==0)
     70                Error("File name missing in DIM_CONTROL/START");
     71            else
     72                Error("Equal sign missing in argument '"+fData.begin()->first+"'");
     73
     74            return;
     75        }
     76
     77        Debug("Start '"+opt+"' received.");
     78        if (fDebug)
     79        {
     80            string d(fDimStart.getString());
     81            if (d.length()>opt.length())
     82                Debug("Received data: "+string(fDimStart.getString()).substr(opt.length()+1));
     83        }
     84
     85        if (fDebug)
     86        {
     87            for (auto it=fData.begin(); it!=fData.end(); it++)
     88                Debug("   Arg: "+it->first+" = "+it->second);
     89        }
     90
     91        fScript = opt;
     92    }
     93
     94    void commandHandler()
     95    {
     96        if (getCommand()==&fDimStop)
     97        {
     98            Debug("Stop received");
     99            Readline::SetLabel(0);
     100        }
     101
     102        if (getCommand()==&fDimStart)
     103            ProcessStart();
     104    }
    38105
    39106public:
    40     DimCtrl(ostream &out=cout) : MessageImp(out), fStop(false)
    41     {
    42     }
    43 
    44     int EvalOptions(Configuration &) { return -1; }
    45     void Stop() { fStop = true; }
    46     int Run(bool) { while (!fStop) usleep(1000); return 0; }
     107    DimCtrl(ostream &out=cout) : MessageDimTX("DIM_CONTROL", out),
     108        fLabel(-3), fStop(false), fVerbosity(0), fDebug(false), fIsServer(false),
     109        fSrvState("DIM_CONTROL/STATE", "C",
     110                  "Provides the state of the state machine as quality of service."
     111                  "|Text[string]:A human readable string sent by the last state change."),
     112        fDimStart("DIM_CONTROL/START", "C", this),
     113        fDimStop("DIM_CONTROL/STOP", "", this)
     114    {
     115    }
     116    ~DimCtrl()
     117    {
     118        DimServer::stop();
     119    }
     120
     121    bool check(string &str)
     122    {
     123        for (auto c=str.begin(); c<str.end(); c++)
     124        {
     125            if ((*c>='A' && *c<='Z') || *c=='_')
     126                continue;
     127
     128            if (*c++!=':')
     129                return false;
     130
     131            if (c==str.end())
     132                return false;
     133
     134            if (*c!=' ')
     135                return false;
     136
     137            str = string(c+1, str.end());
     138            return true;
     139        }
     140
     141        return false;
     142    }
     143
     144    int Write(const Time &time, const std::string &txt, int qos=kMessage)
     145    {
     146        if (txt=="")
     147        {
     148            fLabel = qos;
     149
     150            if (fDebug)
     151            {
     152                ostringstream out;
     153                if (fLabel<0)
     154                {
     155                    if (fLabel==-1)
     156                        out << "========================== Begin ========================";
     157                    else
     158                        out << "=========================== End =========================";
     159                }
     160                else
     161                    out << "------------------------ Label " << setfill('0') << setw(3) << fLabel << " ----------------------";
     162
     163                MessageDimTX::Write(time, out.str(), 90);
     164            }
     165
     166            fSrvState.setQuality(fLabel);
     167            switch (fLabel)
     168            {
     169            case -2: return fSrvState.Update("End of script execution");
     170            case -1: return fSrvState.Update("Start of script execution");
     171            default: return fSrvState.Update("New label");
     172            }
     173        }
     174
     175        if (qos<fVerbosity)
     176            return 0;
     177
     178        // Avoid recursions
     179        if (fIsServer && txt.substr(0, 13)=="DIM_CONTROL: ")
     180            return 0;
     181
     182        // Don't send received messages via dim
     183        string cpy(txt);
     184        if (fIsServer && check(cpy))
     185            return MessageImp::Write(time, cpy, qos);
     186
     187        // Send all of our own messages via dim
     188        return MessageDimTX::Write(time, txt, qos);
     189    }
     190
     191    int EvalOptions(Configuration &conf)
     192    {
     193        fVerbosity = 90;
     194
     195        if (conf.Get<bool>("stop"))
     196            return Dim::SendCommand("DIM_CONTROL/STOP") + 1;
     197
     198        if (conf.Has("start"))
     199            return Dim::SendCommand("DIM_CONTROL/START", conf.Get<string>("start")) + 1;
     200
     201        fVerbosity = 40;
     202
     203        fIsServer = conf.Get<bool>("server");
     204        if (fIsServer)
     205        {
     206            // Sleep needed to ensure that the server can send
     207            // an EXIT if another instance is already running
     208            DimServer::start("DIM_CONTROL");
     209            sleep(1);
     210        }
     211
     212        if (conf.Has("verbosity"))
     213            fVerbosity = conf.Get<uint32_t>("verbosity");
     214
     215        if (conf.Get<bool>("quiet"))
     216            fVerbosity = 90;
     217
     218        fDebug = conf.Get<bool>("debug");
     219
     220        return -1;
     221    }
     222
     223    void Stop(int stop=1) { fStop = stop; Readline::SetLabel(0); }
     224    int Run(bool)
     225    {
     226        while (!fStop)
     227        {
     228            const string s = fScript;
     229            if (!s.empty())
     230            {
     231                Readline::Instance()->Execute(s, fData);
     232                fScript = "";
     233            }
     234
     235            usleep(1000);
     236        }
     237        return fStop-1; }
    47238};
     239
     240void SetupConfiguration(Configuration &conf)
     241{
     242    po::options_description control("Dim Control");
     243    control.add_options()
     244        ("server",      po_bool(false),  "Start dimctrl as a dim server")
     245        ("verbosity,v", var<uint32_t>()->implicit_value(0), "Set a new verbosity level (see MessageImp)")
     246        ("quiet,q",     po_bool(false),  "Suppress all output except comments (log-level>=90)")
     247        ("debug",       po_bool(false),  "Print the labels for debugging purpose")
     248        ("start",       var<string>(),  "")
     249        ("stop",        po_switch(),  "")
     250        ;
     251
     252    conf.AddOptions(control);
     253}
    48254
    49255int main(int argc, const char *argv[])
     
    52258    conf.SetPrintUsage(PrintUsage);
    53259    Main::SetupConfiguration(conf);
     260    SetupConfiguration(conf);
    54261
    55262    if (!conf.DoParse(argc, argv, PrintHelp))
    56263        return -1;
    57264
    58     if (!conf.Has("console") || conf.Get<int>("console")==0)
     265    if (!conf.Has("console"))
     266        return Main::execute<RemoteStream, DimCtrl>(conf);
     267
     268    if (conf.Get<int>("console")==0)
    59269        return Main::execute<RemoteShell, DimCtrl>(conf);
    60270    else
     
    63273    return 0;
    64274}
     275#endif
Note: See TracChangeset for help on using the changeset viewer.