- Timestamp:
- Feb 2, 2009, 2:20:07 PM (16 years ago)
- Location:
- trunk/BNC
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/BNC/bncgetthread.cpp
r1556 r1557 277 277 } 278 278 279 _latencyChecker = new bncGetThread::latencyChecker(_staID); 280 279 281 msleep(100); //sleep 0.1 sec 280 282 } … … 292 294 delete _rawOutFile; 293 295 delete _serialPort; 296 delete _latencyChecker; 294 297 emit getThreadFinished(_staID); 295 298 } … … 369 372 // -------------------------------- 370 373 scanRTCM(); 371 checkLatency();374 _latencyChecker->check(_decoder); 372 375 373 376 // Loop over all observations (observations output) … … 529 532 } 530 533 531 // 534 // Constructor 532 535 ////////////////////////////////////////////////////////////////////////////// 533 void bncGetThread::checkLatency() { 534 //// // Notice threshold 535 //// // ---------------- 536 //// _inspSegm = 50; 537 //// if ( settings.value("obsRate").toString().isEmpty() ) { _inspSegm = 0; } 538 //// if ( settings.value("obsRate").toString().indexOf("5 Hz") != -1 ) { _inspSegm = 2; } 539 //// if ( settings.value("obsRate").toString().indexOf("1 Hz") != -1 ) { _inspSegm = 10; } 540 //// if ( settings.value("obsRate").toString().indexOf("0.5 Hz") != -1 ) { _inspSegm = 20; } 541 //// if ( settings.value("obsRate").toString().indexOf("0.2 Hz") != -1 ) { _inspSegm = 40; } 542 //// if ( settings.value("obsRate").toString().indexOf("0.1 Hz") != -1 ) { _inspSegm = 50; } 543 //// _adviseFail = settings.value("adviseFail").toInt(); 544 //// _adviseReco = settings.value("adviseReco").toInt(); 545 //// _makePause = false; 546 //// if ( Qt::CheckState(settings.value("makePause").toInt()) == Qt::Checked) {_makePause = true; } 547 //// _adviseScript = settings.value("adviseScript").toString(); 548 //// expandEnvVar(_adviseScript); 549 //// 550 //// // Latency interval/average 551 //// // ------------------------ 552 //// _perfIntr = 86400; 553 //// if ( settings.value("perfIntr").toString().isEmpty() ) { _perfIntr = 0; } 554 //// if ( settings.value("perfIntr").toString().indexOf("2 sec") != -1 ) { _perfIntr = 2; } 555 //// if ( settings.value("perfIntr").toString().indexOf("10 sec") != -1 ) { _perfIntr = 10; } 556 //// if ( settings.value("perfIntr").toString().indexOf("1 min") != -1 ) { _perfIntr = 60; } 557 //// if ( settings.value("perfIntr").toString().indexOf("5 min") != -1 ) { _perfIntr = 300; } 558 //// if ( settings.value("perfIntr").toString().indexOf("15 min") != -1 ) { _perfIntr = 900; } 559 //// if ( settings.value("perfIntr").toString().indexOf("1 hour") != -1 ) { _perfIntr = 3600; } 560 //// if ( settings.value("perfIntr").toString().indexOf("6 hours") != -1 ) { _perfIntr = 21600; } 561 //// if ( settings.value("perfIntr").toString().indexOf("1 day") != -1 ) { _perfIntr = 86400; } 562 //// 563 //// // RTCM message types 564 //// // ------------------ 565 //// _checkMountPoint = settings.value("miscMount").toString(); 566 //// 567 //// 568 //// const double maxDt = 600.0; // Check observation epoch 569 //// bool wrongEpoch = false; 570 //// bool decode = true; 571 //// int numSucc = 0; 572 //// int secSucc = 0; 573 //// int secFail = 0; 574 //// int initPause = 30; // Initial pause for corrupted streams 575 //// int currPause = 0; 576 //// bool begCorrupt = false; 577 //// bool endCorrupt = false; 578 //// bool followSec = false; 579 //// int oldSecGPS= 0; 580 //// int newSecGPS = 0; 581 //// int numGaps = 0; 582 //// int diffSecGPS = 0; 583 //// int numLat = 0; 584 //// double sumLat = 0.; 585 //// double sumLatQ = 0.; 586 //// double meanDiff = 0.; 587 //// double minLat = maxDt; 588 //// double maxLat = -maxDt; 589 //// double curLat = 0.; 590 //// 591 //// 592 //// _decodeTime = QDateTime::currentDateTime(); 593 //// _decodeSucc = QDateTime::currentDateTime(); 594 //// 595 //// // Check - once per inspect segment 596 //// // -------------------------------- 597 //// if (!decode) { 598 //// _decodeTime = QDateTime::currentDateTime(); 599 //// if (numSucc>0) { 600 //// secSucc += _inspSegm; 601 //// _decodeSucc = QDateTime::currentDateTime(); 602 //// if (secSucc > _adviseReco * 60) { 603 //// secSucc = _adviseReco * 60 + 1; 604 //// } 605 //// numSucc = 0; 606 //// currPause = initPause; 607 //// _decodePause.setDate(QDate()); 608 //// _decodePause.setTime(QTime()); 609 //// } 610 //// else { 611 //// secFail += _inspSegm; 612 //// secSucc = 0; 613 //// if (secFail > _adviseFail * 60) { 614 //// secFail = _adviseFail * 60 + 1; 615 //// } 616 //// if (!_decodePause.isValid() || !_makePause) { 617 //// _decodePause = QDateTime::currentDateTime(); 618 //// } 619 //// else { 620 //// _decodePause.setDate(QDate()); 621 //// _decodePause.setTime(QTime()); 622 //// secFail = secFail + currPause - _inspSegm; 623 //// currPause = currPause * 2; 624 //// if (currPause > 960) { 625 //// currPause = 960; 626 //// } 627 //// } 628 //// } 629 //// 630 //// // End corrupt threshold 631 //// // --------------------- 632 //// if ( begCorrupt && !endCorrupt && secSucc > _adviseReco * 60 ) { 633 //// _endDateCor = QDateTime::currentDateTime().addSecs(- _adviseReco * 60).toUTC().date().toString("yy-MM-dd"); 634 //// _endTimeCor = QDateTime::currentDateTime().addSecs(- _adviseReco * 60).toUTC().time().toString("hh:mm:ss"); 635 //// emit(newMessage((_staID + ": Recovery threshold exceeded, corruption ended " 636 //// + _endDateCor + " " + _endTimeCor).toAscii(), true)); 637 //// callScript(("End_Corrupted " + _endDateCor + " " + _endTimeCor + " Begin was " + _begDateCor + " " + _begTimeCor).toAscii()); 638 //// endCorrupt = true; 639 //// begCorrupt = false; 640 //// secFail = 0; 641 //// } 642 //// else { 643 //// 644 //// // Begin corrupt threshold 645 //// // ----------------------- 646 //// if ( !begCorrupt && secFail > _adviseFail * 60 ) { 647 //// _begDateCor = _decodeSucc.toUTC().date().toString("yy-MM-dd"); 648 //// _begTimeCor = _decodeSucc.toUTC().time().toString("hh:mm:ss"); 649 //// emit(newMessage((_staID + ": Failure threshold exceeded, corrupted since " 650 //// + _begDateCor + " " + _begTimeCor).toAscii(), true)); 651 //// callScript(("Begin_Corrupted " + _begDateCor + " " + _begTimeCor).toAscii()); 652 //// begCorrupt = true; 653 //// endCorrupt = false; 654 //// secSucc = 0; 655 //// numSucc = 0; 656 //// } 657 //// } 658 //// decode = true; 659 //// } 660 //// } 661 //// } 662 //// 663 //// // End outage threshold 664 //// // -------------------- 665 //// if ( _decodeStart.isValid() && _decodeStart.secsTo(QDateTime::currentDateTime()) > _adviseReco * 60 ) { 666 //// _decodeStart.setDate(QDate()); 667 //// _decodeStart.setTime(QTime()); 668 //// if (_inspSegm>0) { 669 //// _endDateOut = QDateTime::currentDateTime().addSecs(- _adviseReco * 60).toUTC().date().toString("yy-MM-dd"); 670 //// _endTimeOut = QDateTime::currentDateTime().addSecs(- _adviseReco * 60).toUTC().time().toString("hh:mm:ss"); 671 //// emit(newMessage((_staID + ": Recovery threshold exceeded, outage ended " 672 //// + _endDateOut + " " + _endTimeOut).toAscii(), true)); 673 //// callScript(("End_Outage " + _endDateOut + " " + _endTimeOut + " Begin was " + _begDateOut + " " + _begTimeOut).toAscii()); 674 //// } 675 //// } 676 //// 677 //// else { 678 //// wrongEpoch = false; 679 //// 680 //// // Latency and completeness 681 //// // ------------------------ 682 //// if (_perfIntr>0) { 683 //// if ( _checkMountPoint == _staID || _checkMountPoint == "ALL" ) { 684 //// newSecGPS = static_cast<int>(obs->_o.GPSWeeks); 685 //// if (newSecGPS != oldSecGPS) { 686 //// if (newSecGPS % _perfIntr < oldSecGPS % _perfIntr) { 687 //// if (numLat>0) { 688 //// if (meanDiff>0.) { 689 //// emit( newMessage(QString("%1: Mean latency %2 sec, min %3, max %4, rms %5, %6 epochs, %7 gaps") 690 //// .arg(_staID.data()) 691 //// .arg(int(sumLat/numLat*100)/100.) 692 //// .arg(int(minLat*100)/100.) 693 //// .arg(int(maxLat*100)/100.) 694 //// .arg(int((sqrt((sumLatQ - sumLat * sumLat / numLat)/numLat))*100)/100.) 695 //// .arg(numLat) 696 //// .arg(numGaps) 697 //// .toAscii(), true) ); 698 //// } else { 699 //// emit( newMessage(QString("%1: Mean latency %2 sec, min %3, max %4, rms %5, %6 epochs") 700 //// .arg(_staID.data()) 701 //// .arg(int(sumLat/numLat*100)/100.) 702 //// .arg(int(minLat*100)/100.) 703 //// .arg(int(maxLat*100)/100.) 704 //// .arg(int((sqrt((sumLatQ - sumLat * sumLat / numLat)/numLat))*100)/100.) 705 //// .arg(numLat) 706 //// .toAscii(), true) ); 707 //// } 708 //// } 709 //// meanDiff = diffSecGPS/numLat; 710 //// diffSecGPS = 0; 711 //// numGaps = 0; 712 //// sumLat = 0.; 713 //// sumLatQ = 0.; 714 //// numLat = 0; 715 //// minLat = maxDt; 716 //// maxLat = -maxDt; 717 //// } 718 //// if (followSec) { 719 //// diffSecGPS += newSecGPS - oldSecGPS; 720 //// if (meanDiff>0.) { 721 //// if (newSecGPS - oldSecGPS > 1.5 * meanDiff) { 722 //// numGaps += 1; 723 //// } 724 //// } 725 //// } 726 //// curLat = sec - obs->_o.GPSWeeks; 727 //// sumLat += curLat; 728 //// sumLatQ += curLat * curLat; 729 //// if (curLat < minLat) minLat = curLat; 730 //// if (curLat >= maxLat) maxLat = curLat; 731 //// numLat += 1; 732 //// oldSecGPS = newSecGPS; 733 //// followSec = true; 734 //// } 735 //// } 736 //// } 737 //// 738 } 536 bncGetThread::latencyChecker::latencyChecker(QByteArray staID) { 537 538 _staID = staID; 539 540 bncApp* app = (bncApp*) qApp; 541 connect(this, SIGNAL(newMessage(QByteArray,bool)), 542 app, SLOT(slotMessage(const QByteArray,bool))); 543 544 bncSettings settings; 545 546 // Notice threshold 547 // ---------------- 548 QString obsRate = settings.value("obsRate").toString(); 549 _inspSegm = 0; 550 if ( obsRate.isEmpty() ) { 551 _inspSegm = 0; 552 } 553 else if ( obsRate.indexOf("5 Hz") != -1 ) { 554 _inspSegm = 20; 555 } 556 else if ( obsRate.indexOf("1 Hz") != -1 ) { 557 _inspSegm = 10; 558 } 559 else if ( obsRate.indexOf("0.5 Hz") != -1 ) { 560 _inspSegm = 20; 561 } 562 else if ( obsRate.indexOf("0.2 Hz") != -1 ) { 563 _inspSegm = 40; 564 } 565 else if ( obsRate.indexOf("0.1 Hz") != -1 ) { 566 _inspSegm = 50; 567 } 568 _adviseFail = settings.value("adviseFail").toInt(); 569 _adviseReco = settings.value("adviseReco").toInt(); 570 if ( Qt::CheckState(settings.value("makePause").toInt()) == Qt::Checked) { 571 _makePause = true; 572 } 573 else { 574 _makePause = false; 575 } 576 _adviseScript = settings.value("adviseScript").toString(); 577 expandEnvVar(_adviseScript); 578 579 // Latency interval/average 580 // ------------------------ 581 _perfIntr = 0; 582 QString perfIntr = settings.value("perfIntr").toString(); 583 if ( perfIntr.isEmpty() ) { 584 _perfIntr = 0; 585 } 586 else if ( perfIntr.indexOf("2 sec") != -1 ) { 587 _perfIntr = 2; 588 } 589 else if ( perfIntr.indexOf("10 sec") != -1 ) { 590 _perfIntr = 10; 591 } 592 else if ( perfIntr.indexOf("1 min") != -1 ) { 593 _perfIntr = 60; 594 } 595 else if ( perfIntr.indexOf("5 min") != -1 ) { 596 _perfIntr = 300; 597 } 598 else if ( perfIntr.indexOf("15 min") != -1 ) { 599 _perfIntr = 900; 600 } 601 else if ( perfIntr.indexOf("1 hour") != -1 ) { 602 _perfIntr = 3600; 603 } 604 else if ( perfIntr.indexOf("6 hours") != -1 ) { 605 _perfIntr = 21600; 606 } 607 else if ( perfIntr.indexOf("1 day") != -1 ) { 608 _perfIntr = 86400; 609 } 610 611 // RTCM message types 612 // ------------------ 613 _checkMountPoint = settings.value("miscMount").toString(); 614 615 // Initialize private members 616 // -------------------------- 617 _maxDt = 600.0; // Check observation epoch 618 _wrongEpoch = false; 619 _decode = true; 620 _numSucc = 0; 621 _secSucc = 0; 622 _secFail = 0; 623 _initPause = 30; // Initial pause for corrupted streams 624 _currPause = 0; 625 _begCorrupt = false; 626 _endCorrupt = false; 627 _followSec = false; 628 _oldSecGPS = 0; 629 _newSecGPS = 0; 630 _numGaps = 0; 631 _diffSecGPS = 0; 632 _numLat = 0; 633 _sumLat = 0.0; 634 _sumLatQ = 0.0; 635 _meanDiff = 0.0; 636 _minLat = _maxDt; 637 _maxLat = -_maxDt; 638 _curLat = 0.0; 639 640 _decodeTime = QDateTime::currentDateTime(); 641 _decodeSucc = QDateTime::currentDateTime(); 642 } 643 644 // Destructor 645 ////////////////////////////////////////////////////////////////////////////// 646 bncGetThread::latencyChecker::~latencyChecker() { 647 648 } 649 650 // Perform latency checks 651 ////////////////////////////////////////////////////////////////////////////// 652 void bncGetThread::latencyChecker::check(GPSDecoder* decoder) { 653 654 // Check - once per inspect segment 655 // -------------------------------- 656 if (decoder->_obsList.size() > 0) { 657 658 _decodeTime = QDateTime::currentDateTime(); 659 660 if (_numSucc > 0) { 661 _secSucc += _inspSegm; 662 _decodeSucc = QDateTime::currentDateTime(); 663 if (_secSucc > _adviseReco * 60) { 664 _secSucc = _adviseReco * 60 + 1; 665 } 666 _numSucc = 0; 667 _currPause = _initPause; 668 _decodePause.setDate(QDate()); 669 _decodePause.setTime(QTime()); 670 } 671 else { 672 _secFail += _inspSegm; 673 _secSucc = 0; 674 if (_secFail > _adviseFail * 60) { 675 _secFail = _adviseFail * 60 + 1; 676 } 677 if (!_decodePause.isValid() || !_makePause) { 678 _decodePause = QDateTime::currentDateTime(); 679 } 680 else { 681 _decodePause.setDate(QDate()); 682 _decodePause.setTime(QTime()); 683 _secFail = _secFail + _currPause - _inspSegm; 684 _currPause = _currPause * 2; 685 if (_currPause > 960) { 686 _currPause = 960; 687 } 688 } 689 } 690 691 // End corrupt threshold 692 // --------------------- 693 if ( _begCorrupt && !_endCorrupt && _secSucc > _adviseReco * 60 ) { 694 _endDateCor = QDateTime::currentDateTime().addSecs(- _adviseReco * 60).toUTC().date().toString("yy-MM-dd"); 695 _endTimeCor = QDateTime::currentDateTime().addSecs(- _adviseReco * 60).toUTC().time().toString("hh:mm:ss"); 696 emit(newMessage((_staID + ": Recovery threshold exceeded, corruption ended " 697 + _endDateCor + " " + _endTimeCor).toAscii(), true)); 698 callScript(("End_Corrupted " + _endDateCor + " " + _endTimeCor + " Begin was " + _begDateCor + " " + _begTimeCor).toAscii()); 699 _endCorrupt = true; 700 _begCorrupt = false; 701 _secFail = 0; 702 } 703 else { 704 705 // Begin corrupt threshold 706 // ----------------------- 707 if ( !_begCorrupt && _secFail > _adviseFail * 60 ) { 708 _begDateCor = _decodeSucc.toUTC().date().toString("yy-MM-dd"); 709 _begTimeCor = _decodeSucc.toUTC().time().toString("hh:mm:ss"); 710 emit(newMessage((_staID + ": Failure threshold exceeded, corrupted since " 711 + _begDateCor + " " + _begTimeCor).toAscii(), true)); 712 callScript(("Begin_Corrupted " + _begDateCor + " " + _begTimeCor).toAscii()); 713 _begCorrupt = true; 714 _endCorrupt = false; 715 _secSucc = 0; 716 _numSucc = 0; 717 } 718 } 719 } 720 721 // End outage threshold 722 // -------------------- 723 if ( _decodeStart.isValid() && _decodeStart.secsTo(QDateTime::currentDateTime()) > _adviseReco * 60 ) { 724 _decodeStart.setDate(QDate()); 725 _decodeStart.setTime(QTime()); 726 if (_inspSegm > 0) { 727 _endDateOut = QDateTime::currentDateTime().addSecs(- _adviseReco * 60).toUTC().date().toString("yy-MM-dd"); 728 _endTimeOut = QDateTime::currentDateTime().addSecs(- _adviseReco * 60).toUTC().time().toString("hh:mm:ss"); 729 emit(newMessage((_staID + ": Recovery threshold exceeded, outage ended " 730 + _endDateOut + " " + _endTimeOut).toAscii(), true)); 731 callScript(("End_Outage " + _endDateOut + " " + _endTimeOut + " Begin was " + _begDateOut + " " + _begTimeOut).toAscii()); 732 } 733 } 734 735 // Latency and completeness 736 // ------------------------ 737 if ( _checkMountPoint == _staID || _checkMountPoint == "ALL" ) { 738 if (_perfIntr > 0 ) { 739 740 QListIterator<p_obs> it(decoder->_obsList); 741 while (it.hasNext()) { 742 p_obs obs = it.next(); 743 744 _newSecGPS = static_cast<int>(obs->_o.GPSWeeks); 745 if (_newSecGPS != _oldSecGPS) { 746 if (_newSecGPS % _perfIntr < _oldSecGPS % _perfIntr) { 747 if (_numLat > 0) { 748 if (_meanDiff > 0.0) { 749 emit( newMessage(QString("%1: Mean latency %2 sec, min %3, max %4, rms %5, %6 epochs, %7 gaps") 750 .arg(_staID.data()) 751 .arg(int(_sumLat/_numLat*100)/100.) 752 .arg(int(_minLat*100)/100.) 753 .arg(int(_maxLat*100)/100.) 754 .arg(int((sqrt((_sumLatQ - _sumLat * _sumLat / _numLat)/_numLat))*100)/100.) 755 .arg(_numLat) 756 .arg(_numGaps) 757 .toAscii(), true) ); 758 } else { 759 emit( newMessage(QString("%1: Mean latency %2 sec, min %3, max %4, rms %5, %6 epochs") 760 .arg(_staID.data()) 761 .arg(int(_sumLat/_numLat*100)/100.) 762 .arg(int(_minLat*100)/100.) 763 .arg(int(_maxLat*100)/100.) 764 .arg(int((sqrt((_sumLatQ - _sumLat * _sumLat / _numLat)/_numLat))*100)/100.) 765 .arg(_numLat) 766 .toAscii(), true) ); 767 } 768 } 769 _meanDiff = _diffSecGPS / _numLat; 770 _diffSecGPS = 0; 771 _numGaps = 0; 772 _sumLat = 0.0; 773 _sumLatQ = 0.0; 774 _numLat = 0; 775 _minLat = _maxDt; 776 _maxLat = -_maxDt; 777 } 778 if (_followSec) { 779 _diffSecGPS += _newSecGPS - _oldSecGPS; 780 if (_meanDiff>0.) { 781 if (_newSecGPS - _oldSecGPS > 1.5 * _meanDiff) { 782 _numGaps += 1; 783 } 784 } 785 } 786 787 // Compute the observations latency 788 // -------------------------------- 789 int week; 790 double sec; 791 currentGPSWeeks(week, sec); 792 const double secPerWeek = 7.0 * 24.0 * 3600.0; 793 if (week < obs->_o.GPSWeek) { 794 week += 1; 795 sec -= secPerWeek; 796 } 797 if (week > obs->_o.GPSWeek) { 798 week -= 1; 799 sec += secPerWeek; 800 } 801 802 _curLat = sec - obs->_o.GPSWeeks; 803 _sumLat += _curLat; 804 _sumLatQ += _curLat * _curLat; 805 if (_curLat < _minLat) { 806 _minLat = _curLat; 807 } 808 if (_curLat >= _maxLat) { 809 _maxLat = _curLat; 810 } 811 _numLat += 1; 812 _oldSecGPS = _newSecGPS; 813 _followSec = true; 814 } 815 } 816 } 817 } 818 } 819 820 // Call advisory notice script 821 //////////////////////////////////////////////////////////////////////////// 822 void bncGetThread::latencyChecker::callScript(const char* comment) { 823 if (!_adviseScript.isEmpty()) { 824 msleep(1); 825 #ifdef WIN32 826 QProcess::startDetached(_adviseScript, QStringList() << _staID << comment) ; 827 #else 828 QProcess::startDetached("nohup", QStringList() << _adviseScript << _staID << comment) ; 829 #endif 830 } 831 } -
trunk/BNC/bncgetthread.h
r1556 r1557 74 74 75 75 private: 76 77 class latencyChecker : public QObject { 78 Q_OBJECT 79 public: 80 latencyChecker(QByteArray staID); 81 ~latencyChecker(); 82 void check(GPSDecoder* decoder); 83 signals: 84 void newMessage(QByteArray msg, bool showOnScreen); 85 private: 86 void callScript(const char* comment); 87 int _inspSegm; 88 int _adviseFail; 89 int _adviseReco; 90 int _perfIntr; 91 int _numSucc; 92 int _secSucc; 93 int _secFail; 94 int _initPause; 95 int _currPause; 96 int _oldSecGPS; 97 int _newSecGPS; 98 int _numGaps; 99 int _diffSecGPS; 100 int _numLat; 101 bool _makePause; 102 bool _wrongEpoch; 103 bool _decode; 104 bool _begCorrupt; 105 bool _endCorrupt; 106 bool _followSec; 107 double _maxDt; 108 double _sumLat; 109 double _sumLatQ; 110 double _meanDiff; 111 double _minLat; 112 double _maxLat; 113 double _curLat; 114 QByteArray _staID; 115 QString _adviseScript; 116 QString _checkMountPoint; 117 QString _begDateCor; 118 QString _begTimeCor; 119 QString _begDateOut; 120 QString _begTimeOut; 121 QString _endDateCor; 122 QString _endTimeCor; 123 QString _endDateOut; 124 QString _endTimeOut; 125 QDateTime _decodeTime; 126 QDateTime _decodeSucc; 127 QDateTime _decodeFailure; 128 QDateTime _decodeStart; 129 QDateTime _decodeStop; 130 QDateTime _decodePause; 131 }; 132 76 133 void initialize(); 77 134 t_irc tryReconnect(); 78 void checkLatency();79 135 void scanRTCM(); 80 136 … … 97 153 QextSerialPort* _serialPort; 98 154 bool _isToBeDeleted; 155 latencyChecker* _latencyChecker; 99 156 }; 100 157
Note:
See TracChangeset
for help on using the changeset viewer.