Changeset 15430


Ignore:
Timestamp:
04/24/13 22:40:45 (12 years ago)
Author:
tbretz
Message:
Implemented the possibility to send an interrupt request (irq) to a runing JavaScript.
Location:
trunk/FACT++/src
Files:
6 edited

Legend:

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

    r15350 r15430  
    14741474}
    14751475
    1476 
    14771476void InterpreterV8::JsHandleState(const std::string &server, const State &state)
    14781477{
     
    15241523    if (!HandleException(exception, "dim.onchange"))
    15251524        V8::TerminateExecution(fThreadId);
     1525}
     1526
     1527Handle<Value> InterpreterV8::FuncSetInterrupt(const Arguments &args)
     1528{
     1529    if (args.Length()!=1)
     1530        return ThrowException(String::New("Number of arguments must be 1."));
     1531
     1532    if (!args[0]->IsNull() && !args[0]->IsUndefined() && !args[0]->IsFunction())
     1533        return ThrowException(String::New("Argument not a function, null or undefined."));
     1534
     1535    if (args[0]->IsNull() || args[0]->IsUndefined())
     1536    {
     1537        fInterruptCallback.Dispose();
     1538        return Undefined();
     1539    }
     1540
     1541    // Returns the value if the setter intercepts the request. Otherwise, returns an empty handle.
     1542    fInterruptCallback = Persistent<Object>::New(args[0]->ToObject());
     1543    return Undefined();
     1544}
     1545
     1546int InterpreterV8::JsHandleInterrupt(const EventImp &evt)
     1547{
     1548    const Locker locker;
     1549
     1550    if (fThreadId<0)
     1551        return -42;
     1552
     1553    if (fInterruptCallback.IsEmpty())
     1554        return -42;
     1555
     1556    const HandleScope handle_scope;
     1557
     1558    fInterruptCallback->CreationContext()->Enter();
     1559
     1560    // -------------------------------------------------------------------
     1561
     1562    TryCatch exception;
     1563
     1564    const string str = evt.GetString();
     1565
     1566    const size_t p = str.find_last_of('\n');
     1567
     1568    const string irq = p==string::npos?str:str.substr(0, p);
     1569    const string usr = p==string::npos?"nobody":str.substr(p+1);
     1570
     1571    Local<Value> irq_str = String::New(irq.c_str());
     1572    Local<Value> usr_str = String::New(usr.c_str());
     1573    Local<Value> date = Date::New(evt.GetJavaDate());
     1574
     1575    int32_t rc = -42;
     1576    if (!date.IsEmpty())
     1577    {
     1578        const int id = V8::GetCurrentThreadId();
     1579        fThreadIds.insert(id);
     1580
     1581        Handle<Value> args[] = { irq_str, date, usr_str };
     1582        Handle<Function> fun = Handle<Function>(Function::Cast(*fInterruptCallback));
     1583
     1584        const Handle<Value> val = fun->Call(fun, 3, args);
     1585
     1586        rc = !val.IsEmpty() && val->IsInt32() ? val->Int32Value() : 0;
     1587
     1588        fThreadIds.erase(id);
     1589    }
     1590
     1591    if (!HandleException(exception, "interrupt"))
     1592        V8::TerminateExecution(fThreadId);
     1593
     1594    return rc<10 || rc>255 ? -42 : rc;
    15261595}
    15271596
     
    23422411    dimctrl->Set(String::New("setState"),    FunctionTemplate::New(WrapSetState),  ReadOnly);
    23432412    dimctrl->Set(String::New("getState"),    FunctionTemplate::New(WrapGetState),  ReadOnly);
     2413    dimctrl->Set(String::New("setInterruptHandler"), FunctionTemplate::New(WrapSetInterrupt), ReadOnly);
    23442414
    23452415    Handle<ObjectTemplate> v8 = ObjectTemplate::New();
     
    25222592    fStateCallbacks.clear();
    25232593
     2594    // Now we can dispose the persistent interrupt handler
     2595    fInterruptCallback.Dispose();
     2596
    25242597    // Now we can dispose all persistent handles from reverse maps
    25252598    for (auto it=fReverseMap.begin(); it!=fReverseMap.end(); it++)
  • trunk/FACT++/src/InterpreterV8.h

    r15172 r15430  
    4646    // List of all states already set
    4747    std::vector<std::pair<int, std::string>> fStates;
     48
     49    // Interrupt handler
     50    v8::Persistent<v8::Object> fInterruptCallback;
    4851
    4952    static v8::Handle<v8::FunctionTemplate> fTemplateLocal;
     
    8689    v8::Handle<v8::Value> FuncGetServices(const v8::Arguments& args);
    8790    v8::Handle<v8::Value> FuncNewState(const v8::Arguments& args);
     91    v8::Handle<v8::Value> FuncSetInterrupt(const v8::Arguments& args);
    8892    //v8::Handle<v8::Value> FuncOpen(const v8::Arguments& args);
    8993    v8::Handle<v8::Value> FuncSubscription(const v8::Arguments& args);
     
    142146    static v8::Handle<v8::Value> WrapGetDescription(const v8::Arguments &args){ if (This) return This->FuncGetDescription(args);else return v8::Undefined(); }
    143147    static v8::Handle<v8::Value> WrapGetServices(const v8::Arguments &args){ if (This) return This->FuncGetServices(args);else return v8::Undefined(); }
     148    static v8::Handle<v8::Value> WrapSetInterrupt(const v8::Arguments &args){ if (This) return This->FuncSetInterrupt(args);else return v8::Undefined(); }
    144149    //static v8::Handle<v8::Value> WrapOpen(const v8::Arguments &args)     { if (This) return This->FuncOpen(args);     else return v8::Undefined(); }
    145150    static v8::Handle<v8::Value> WrapSubscription(const v8::Arguments &args){ if (This) return This->FuncSubscription(args);else return v8::Undefined(); }
     
    204209    virtual std::pair<uint64_t, EventImp *> JsGetEvent(const std::string &) { return std::make_pair(0, (EventImp*)0); };
    205210
     211    int JsHandleInterrupt(const EventImp &);
    206212    void JsHandleEvent(const EventImp &, uint64_t, const std::string &);
    207213    void JsHandleState(const std::string &, const State &);
  • trunk/FACT++/src/RemoteControl.h

    r15128 r15430  
    523523        fImp = &imp;
    524524        fImp->SetStateCallback(bind(&InterpreterV8::JsHandleState, this, placeholders::_1, placeholders::_2));
     525        fImp->SetInterruptHandler(bind(&InterpreterV8::JsHandleInterrupt, this, placeholders::_1));
    525526    }
    526527};
  • trunk/FACT++/src/StateMachineDimControl.cc

    r15295 r15430  
    130130    InterpreterV8::JsStop();
    131131    return GetCurrentState();
     132}
     133
     134int StateMachineDimControl::InterruptScript(const EventImp &evt)
     135{
     136    if (!fInterruptHandler)
     137        return GetCurrentState();
     138
     139    string str = evt.GetString();
     140
     141    const size_t p = str.find_last_of('\n');
     142    if (p!=string::npos)
     143        str[p] = ':';
     144
     145    Info("Interrupt request received ["+str+"]");
     146    return fInterruptHandler(evt);
    132147}
    133148
     
    510525        (bind(&StateMachineDimControl::StopScript, this))
    511526        ("Stop a runnning batch script or JavaScript");
     527
     528    AddEvent("INTERRUPT", "C")
     529        (bind(&StateMachineDimControl::InterruptScript, this, placeholders::_1))
     530        ("Send an interrupt request (IRQ) to a running JavaScript");
    512531}
    513532
     
    565584        return !Dim::SendCommand("DIM_CONTROL/STOP", fUser);
    566585
     586    if (conf.Has("interrupt"))
     587        return !Dim::SendCommand("DIM_CONTROL/INTERRUPT", conf.Get<string>("interrupt")+"\n"+fUser);
     588
    567589    if (conf.Has("start"))
    568590        return !Dim::SendCommand("DIM_CONTROL/START", conf.Get<string>("start")+" user='"+fUser+"'"+fArgumentsJS);
  • trunk/FACT++/src/StateMachineDimControl.h

    r15041 r15430  
    3636    std::string fArgumentsJS;
    3737
     38    std::function<int(const EventImp &)> fInterruptHandler;
     39
    3840    std::string Line(const std::string &txt, char fill);
    3941
     
    4648    int StartScript(const EventImp &imp, const std::string &cmd);
    4749    int StopScript();
     50    int InterruptScript(const EventImp &imp);
    4851
    4952    int HandleStateChange(const std::string &server, DimDescriptions *state);
     
    7275    void SetStateCallback(const std::function<void(const std::string &, const State &)> &func) { fStateCallback = func; }
    7376
     77    void SetInterruptHandler(const std::function<int(const EventImp &)> &func=std::function<int(const EventImp &)>()) { fInterruptHandler = func; }
     78
    7479public:
    7580    StateMachineDimControl(std::ostream &out=std::cout);
  • trunk/FACT++/src/dimctrl.cc

    r15188 r15430  
    11#include "StateMachineDimControl.h"
     2
     3//#include <sys/stat.h>
    24
    35#include "RemoteControl.h"
     
    4345    {
    4446        control.add_options()
     47            ("batch",   var<string>(), "Start a batch script with the given name at the given label (script.dim[:N]) on the dimctrl-server")
    4548            ("start",   var<string>(), "Start a java script with the given name on the dimctrl-server")
    46             ("batch",   var<string>(), "Start a batch script with the given name at the given label (script.dim[:N]) on the dimctrl-server")
    4749            ("stop",    po_switch(),   "Stop a currently running script on the dimctrl-server")
     50            ("interrupt", var<string>()->implicit_value(""), "Send an interrupt request (IRQ) to a running JavaScript.")
    4851            ("restart", var<string>(), "Send 'EXIT 126' to the given server")
    4952            ("msg",     var<string>(), "Send a message to the chat server.")
     
    106109int main(int argc, const char* argv[])
    107110{
     111    //chmod(argv[0], 04775);
     112
    108113    Configuration conf(argv[0]);
    109114    conf.SetPrintUsage(PrintUsage);
Note: See TracChangeset for help on using the changeset viewer.