Ignore:
Timestamp:
11/17/03 13:50:48 (21 years ago)
Author:
tbretz
Message:
*** empty log message ***
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/MagicSoft/Cosy/candrv/nodedrv.cc

    r2278 r2518  
    6161// and the node name. The name is a name for debug output.
    6262//
    63 NodeDrv::NodeDrv(BYTE_t nodeid, const char *name, MLog &out) : Log(out), fNetwork(NULL), fId(32), fError(0), fIsZombie(kTRUE)
     63NodeDrv::NodeDrv(BYTE_t nodeid, const char *name, MLog &out) : Log(out), fNetwork(NULL), fId(32), fError(0), fIsZombie(kTRUE), fGuard(NULL)
    6464{
    6565    if (nodeid>0x1f)
     
    7979    }
    8080
    81     fTimerOn = kFALSE;
    82     fTimeout = new TTimer(this, 100, kFALSE); // 100ms, asynchronous
    83 
    8481    lout << "- Node #" << (int)nodeid << " (" << name << ") initialized." << endl;
    8582
     
    9289NodeDrv::~NodeDrv()
    9390{
    94     fTimerOn = kFALSE;
    95     delete fTimeout;
    9691}
    9792
     
    492487// least one Nodeguard message was answered.
    493488//
     489class NodeGuard : public MThread
     490{
     491    Double_t fTimeoutTime;
     492    Double_t fGuardTime;
     493    Int_t    fLifeTimeFactor;
     494
     495    Bool_t   fIsCanOpen;
     496
     497    NodeDrv *fDrv;
     498
     499public:
     500    NodeGuard(NodeDrv *drv, Int_t guard, Int_t ltf, Bool_t canopen)
     501        : MThread(false), fGuardTime(guard/1000.), fLifeTimeFactor(ltf), fIsCanOpen(canopen), fDrv(drv) { }
     502
     503    void Reset(timeval_t *tv=NULL)
     504    {
     505        Timer t;
     506        if (tv)
     507            t.SetTimer(tv);
     508        else
     509            t.Now();
     510
     511        fTimeoutTime = t + (fGuardTime*fLifeTimeFactor);
     512    }
     513
     514    void *Thread()
     515    {
     516        Reset();
     517
     518        while (!HasStopFlag())
     519        {
     520            // Sending nodeguards seems to result in
     521            // loosing CANbus messages or CANbus answers...
     522            // strange. Also protecting VmodIcan::SendCanFrame
     523            // by a Mutex doesn't help.
     524            if (fIsCanOpen)
     525                fDrv->SendNodeguard();
     526
     527            Timer t;
     528            t.Now();
     529
     530            const Timer t0 = t+fGuardTime;
     531
     532            while (!HasStopFlag() && t<t0 && t<fTimeoutTime)
     533            {
     534                usleep(5);
     535                t.Now();
     536            }
     537
     538            //cout << "-d-> " << (Long_t)((fTimeoutTime-t)*1000) << endl;
     539            //cout << "-o-> " << (ULong_t)((fTimeoutTime)*1000)<< " " << (ULong_t)((t)*1000) << endl;
     540            //cout << "-g-> " << (Long_t)((t-t0)*1000)<< endl;
     541
     542            if (t<fTimeoutTime)
     543                continue;
     544
     545            fDrv->SetZombie(false);
     546            return 0;
     547        }
     548        return 0;
     549    }
     550};
     551
    494552void NodeDrv::StartGuarding(Bool_t real=kTRUE)
    495553{
    496     if (fTimerOn)
     554    if (fGuard)
    497555        return;
    498556
    499     if (!real)
    500         SendNodeguard();
    501 
    502     fTimerOn = kTRUE;
    503     fTimeout->SetTime(fGuardTime);
    504     fTimeout->Reset();
    505 
    506     Timer t;
    507     fTimeoutTime = t.Now() + (fGuardTime*fLifeTimeFactor/1000.);
    508     //cout << GetNodeName() << ": " << fmod(fTimeoutTime*10000, 10000)/10 << endl;
    509 
    510     fTimeout->TurnOn();
    511     //fTimeout->Start(fGuardTime, kTRUE);
     557    fGuard = new NodeGuard(this, fGuardTime, fLifeTimeFactor, real);
     558    fGuard->Start();
    512559
    513560    lout << "- " << GetNodeName() << ": Guarding (" << dec;
     
    517564void NodeDrv::StartGuarding(Int_t ms, Int_t ltf, Bool_t real)
    518565{
    519     if (fTimerOn)
     566    if (fGuard)
    520567    {
    521568        lout << "- " << GetNodeName() << ": ERROR - Guarding already started." << endl;
    522569        return;
    523570    }
     571
    524572    fGuardTime      = ms;
    525573    fLifeTimeFactor = ltf;
     
    530578void NodeDrv::StopGuarding()
    531579{
    532     if (!fTimerOn)
     580    if (!fGuard)
    533581        return;
    534582
    535     fTimeout->TurnOff();
    536     fTimerOn = kFALSE;
     583    delete fGuard;
     584    fGuard=NULL;
    537585
    538586    lout << "- " << GetNodeName() << ": Guarding stopped." << endl;
    539 }
    540 
    541 // --------------------------------------------------------------------------
    542 //
    543 // Handle the Nodeguard-Timer Event.
    544 // It checks whether the node timed out. If it timed out it is set to
    545 // the Zombie state.
    546 // A new Nodeguard request is send and a new timer event is triggered.
    547 //
    548 Bool_t NodeDrv::HandleTimer(TTimer *t)
    549 {
    550     //
    551     // WARNING:
    552     //           It seems, that you should never access ANY output from
    553     //           here. Neither the GUI, nor COUT. This can result in
    554     //           'unexpected async reply'
    555     //
    556 
    557    /*
    558      Fons:
    559      -----
    560 
    561      timers never trigger at the same time or when in a TTimer::Notify.
    562      Little explanation:
    563 
    564      - there are two types of timers synchronous and a-synchronous.
    565      - synchronous timers are only handled via the ROOT eventloop
    566        (see TUnixSystem::DispatchOneEvent()). If there are no mouse/keyboard
    567        events then the synchronous timer queue is checked. So if the processing
    568        of a mouse/keyboard event takes a long time synchronous timers are not
    569        called for a while. To prevent this from happening one can call in long
    570        procedures gSystem->ProcessEvents(). The system schedules only the
    571        next timer in the queue when the current one's Notify() has finished.
    572      - a-synchronous timers are triggered via SIGALARM, i.e. the program is
    573        interupted and execution jumps to the Notify() function. When the
    574        notify is finished the next a-sync timer is scheduled and the system
    575        resumes from the place where it was initially interrupted. One of the
    576        things to remember when using a-sync timers is don't make any graphics
    577        calls in them. X11 is not re-entrant and it might be that the SIGALARM
    578        signal interrupted the system while being in X11. A-sync timers are best
    579        used to set flags that you can test at a convenient and controlled
    580        time.
    581        */
    582     if (fIsZombie)
    583         return kTRUE;
    584 
    585     Timer time;
    586     Double_t now = time.Now();
    587     if (now > fTimeoutTime)
    588     {
    589         cout << GetNodeName() << ": " << "==out==> " << fmod(now*1000, 10000)/10 << " > " << fmod(fTimeoutTime*10000, 10000)/10 << endl;
    590         //cout << "ERROR - " << GetNodeName() << " didn't respond in timeout window." << endl;
    591         //lout << "ERROR - " << GetNodeName() << " didn't respond in timeout window." << endl;
    592         //cout << dec << "+" << (int)GetId() << ": Handle: " << fmod(now, 500) << endl;
    593         //cout << dec << "+" << (int)GetId() << ": Handle: " << fmod(fTimeoutTime, 500) << endl;
    594         //cout << fGuardTime << endl;
    595         fIsZombie = true;
    596         //SetZombie();
    597 
    598         return kTRUE;
    599     }
    600 
    601     SendNodeguard();
    602 
    603     return kTRUE;
    604587}
    605588
     
    611594void NodeDrv::HandleNodeguard(timeval_t *tv)
    612595{
    613     Timer t(tv);
    614     fTimeoutTime = t + (fGuardTime*fLifeTimeFactor/1000.);
    615     //cout << GetNodeName() << ": " << fmod(fTimeoutTime*10000, 10000)/10 << endl;
    616 }
    617 
    618 void NodeDrv::SetZombie()
     596    if (fGuard)
     597        fGuard->Reset(tv);
     598}
     599
     600void NodeDrv::SetZombie(bool stopguard)
    619601{
    620602    fIsZombie = true;
    621     StopGuarding();
    622 }
     603    if (stopguard)
     604        StopGuarding();
     605    else
     606        lout << " - " << GetNodeName() << ": Zombie set due to timeout." << endl;
     607}
Note: See TracChangeset for help on using the changeset viewer.