Changeset 2518 for trunk/MagicSoft/Cosy/candrv/nodedrv.cc
- Timestamp:
- 11/17/03 13:50:48 (21 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/MagicSoft/Cosy/candrv/nodedrv.cc
r2278 r2518 61 61 // and the node name. The name is a name for debug output. 62 62 // 63 NodeDrv::NodeDrv(BYTE_t nodeid, const char *name, MLog &out) : Log(out), fNetwork(NULL), fId(32), fError(0), fIsZombie(kTRUE) 63 NodeDrv::NodeDrv(BYTE_t nodeid, const char *name, MLog &out) : Log(out), fNetwork(NULL), fId(32), fError(0), fIsZombie(kTRUE), fGuard(NULL) 64 64 { 65 65 if (nodeid>0x1f) … … 79 79 } 80 80 81 fTimerOn = kFALSE;82 fTimeout = new TTimer(this, 100, kFALSE); // 100ms, asynchronous83 84 81 lout << "- Node #" << (int)nodeid << " (" << name << ") initialized." << endl; 85 82 … … 92 89 NodeDrv::~NodeDrv() 93 90 { 94 fTimerOn = kFALSE;95 delete fTimeout;96 91 } 97 92 … … 492 487 // least one Nodeguard message was answered. 493 488 // 489 class 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 499 public: 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 494 552 void NodeDrv::StartGuarding(Bool_t real=kTRUE) 495 553 { 496 if (f TimerOn)554 if (fGuard) 497 555 return; 498 556 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(); 512 559 513 560 lout << "- " << GetNodeName() << ": Guarding (" << dec; … … 517 564 void NodeDrv::StartGuarding(Int_t ms, Int_t ltf, Bool_t real) 518 565 { 519 if (f TimerOn)566 if (fGuard) 520 567 { 521 568 lout << "- " << GetNodeName() << ": ERROR - Guarding already started." << endl; 522 569 return; 523 570 } 571 524 572 fGuardTime = ms; 525 573 fLifeTimeFactor = ltf; … … 530 578 void NodeDrv::StopGuarding() 531 579 { 532 if (!f TimerOn)580 if (!fGuard) 533 581 return; 534 582 535 fTimeout->TurnOff();536 f TimerOn = kFALSE;583 delete fGuard; 584 fGuard=NULL; 537 585 538 586 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 to545 // 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 from553 // here. Neither the GUI, nor COUT. This can result in554 // '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 eventloop566 (see TUnixSystem::DispatchOneEvent()). If there are no mouse/keyboard567 events then the synchronous timer queue is checked. So if the processing568 of a mouse/keyboard event takes a long time synchronous timers are not569 called for a while. To prevent this from happening one can call in long570 procedures gSystem->ProcessEvents(). The system schedules only the571 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 is573 interupted and execution jumps to the Notify() function. When the574 notify is finished the next a-sync timer is scheduled and the system575 resumes from the place where it was initially interrupted. One of the576 things to remember when using a-sync timers is don't make any graphics577 calls in them. X11 is not re-entrant and it might be that the SIGALARM578 signal interrupted the system while being in X11. A-sync timers are best579 used to set flags that you can test at a convenient and controlled580 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;604 587 } 605 588 … … 611 594 void NodeDrv::HandleNodeguard(timeval_t *tv) 612 595 { 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 600 void NodeDrv::SetZombie(bool stopguard) 619 601 { 620 602 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.