mirror of
https://thingvellir.net/git/overte
synced 2025-03-27 23:52:03 +01:00
recursive SequenceNumberStats; untested
This commit is contained in:
parent
cdcc6ece04
commit
eba07b03e2
2 changed files with 120 additions and 4 deletions
|
@ -13,22 +13,67 @@
|
|||
|
||||
#include <limits>
|
||||
|
||||
SequenceNumberStats::SequenceNumberStats(int statsHistoryLength)
|
||||
SequenceNumberStats::SequenceNumberStats(int statsHistoryLength, int maxRecursion)
|
||||
: _received(0),
|
||||
_lastReceivedSequence(0),
|
||||
_missingSet(),
|
||||
_stats(),
|
||||
_lastSenderUUID(),
|
||||
_statsHistory(statsHistoryLength)
|
||||
_statsHistory(statsHistoryLength),
|
||||
|
||||
_unreasonableTracker(NULL),
|
||||
_maxRecursion(maxRecursion)
|
||||
{
|
||||
}
|
||||
|
||||
SequenceNumberStats::SequenceNumberStats(const SequenceNumberStats& other)
|
||||
: _received(other._received),
|
||||
_lastReceivedSequence(other._lastReceivedSequence),
|
||||
_missingSet(other._missingSet),
|
||||
_stats(other._stats),
|
||||
_lastSenderUUID(other._lastSenderUUID),
|
||||
_statsHistory(other._statsHistory),
|
||||
_unreasonableTracker(NULL),
|
||||
_maxRecursion(other._maxRecursion)
|
||||
{
|
||||
if (other._unreasonableTracker) {
|
||||
_unreasonableTracker = new SequenceNumberStats(*other._unreasonableTracker);
|
||||
}
|
||||
}
|
||||
|
||||
SequenceNumberStats& SequenceNumberStats::operator=(const SequenceNumberStats& rhs) {
|
||||
_received = rhs._received;
|
||||
_lastReceivedSequence = rhs._lastReceivedSequence;
|
||||
_missingSet = rhs._missingSet;
|
||||
_stats = rhs._stats;
|
||||
_lastSenderUUID = rhs._lastSenderUUID;
|
||||
_statsHistory = rhs._statsHistory;
|
||||
_maxRecursion = rhs._maxRecursion;
|
||||
|
||||
if (rhs._unreasonableTracker) {
|
||||
_unreasonableTracker = new SequenceNumberStats(*rhs._unreasonableTracker);
|
||||
} else {
|
||||
_unreasonableTracker = NULL;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
SequenceNumberStats::~SequenceNumberStats() {
|
||||
if (_unreasonableTracker) {
|
||||
delete _unreasonableTracker;
|
||||
}
|
||||
}
|
||||
|
||||
void SequenceNumberStats::reset() {
|
||||
_received = 0;
|
||||
_missingSet.clear();
|
||||
_stats = PacketStreamStats();
|
||||
_lastSenderUUID = QUuid();
|
||||
_statsHistory.clear();
|
||||
|
||||
if (_unreasonableTracker) {
|
||||
delete _unreasonableTracker;
|
||||
}
|
||||
}
|
||||
|
||||
static const int UINT16_RANGE = std::numeric_limits<uint16_t>::max() + 1;
|
||||
|
@ -78,10 +123,64 @@ SequenceNumberStats::ArrivalInfo SequenceNumberStats::sequenceNumberReceived(qui
|
|||
} else if (absGap > MAX_REASONABLE_SEQUENCE_GAP) {
|
||||
arrivalInfo._status = Unreasonable;
|
||||
|
||||
/*
|
||||
// ignore packet if gap is unreasonable
|
||||
qDebug() << "ignoring unreasonable sequence number:" << incoming
|
||||
<< "previous:" << _lastReceivedSequence;
|
||||
_stats._unreasonable++;
|
||||
*/
|
||||
|
||||
// do not create a child tracker for unreasonable seq nums if this instance is the last one in the chain.
|
||||
// otherwise, create one if we don't have one.
|
||||
|
||||
if (!_unreasonableTracker && _maxRecursion > 0) {
|
||||
_unreasonableTracker = new SequenceNumberStats(0, _maxRecursion - 1);
|
||||
}
|
||||
|
||||
|
||||
if (_unreasonableTracker) {
|
||||
|
||||
// track this unreasonable seq number with our _unreasonableTracker.
|
||||
ArrivalInfo unreasonableTrackerArrivalInfo = _unreasonableTracker->sequenceNumberReceived(incoming);
|
||||
|
||||
|
||||
const int UNREASONABLE_TRACKER_RECEIVED_THRESHOLD = 10;
|
||||
const float UNRUNREASONABLE_TRACKER_UNREASONABLE_RATE_THRESHOLD = 0.1f;
|
||||
const float UNREASONABLE_TRACKER_OUT_OF_ORDER_RATE_THRESHOLD = 0.1f;
|
||||
|
||||
// when our _unreasonableTracker has received enough seq nums and doesn't have an _unreasonableTracker of its own,
|
||||
// we'll either inherit its state only if we think its stream is plausible. it will then be deleted.
|
||||
// (if it has an _unreasonableTracker of its own, its _unreasonableTracker may be detecting a plausible stream
|
||||
// while its parent does not, so we should let it accrue seq nums and decide plausibility first)
|
||||
|
||||
if (!_unreasonableTracker->hasUnreasonableTracker() &&
|
||||
_unreasonableTracker->_received >= UNREASONABLE_TRACKER_RECEIVED_THRESHOLD) {
|
||||
|
||||
if (_unreasonableTracker->getUnreasonableRate() < UNRUNREASONABLE_TRACKER_UNREASONABLE_RATE_THRESHOLD &&
|
||||
_unreasonableTracker->getStats().getOutOfOrderRate() < UNREASONABLE_TRACKER_OUT_OF_ORDER_RATE_THRESHOLD) {
|
||||
|
||||
// the _unreasonableTracker has detected a plausible stream of seq numbers;
|
||||
// copy its state to this tracker.
|
||||
|
||||
_received = _unreasonableTracker->_received;
|
||||
_lastReceivedSequence = _unreasonableTracker->_lastReceivedSequence;
|
||||
_missingSet = _unreasonableTracker->_missingSet;
|
||||
_stats = _unreasonableTracker->_stats;
|
||||
|
||||
// don't copy _lastSenderUUID; _unreasonableTracker always has null UUID for that member.
|
||||
// ours should be up-to-date.
|
||||
|
||||
// don't copy _statsHistory; _unreasonableTracker keeps a history of length 0.
|
||||
// simply clear ours.
|
||||
_statsHistory.clear();
|
||||
|
||||
arrivalInfo = unreasonableTrackerArrivalInfo;
|
||||
|
||||
}
|
||||
// remove our _unreasonableTracker
|
||||
delete _unreasonableTracker;
|
||||
}
|
||||
}
|
||||
|
||||
return arrivalInfo;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,10 @@
|
|||
|
||||
const int MAX_REASONABLE_SEQUENCE_GAP = 1000;
|
||||
|
||||
|
||||
const int DEFAULT_MAX_RECURSION = 5;
|
||||
|
||||
|
||||
class PacketStreamStats {
|
||||
public:
|
||||
PacketStreamStats()
|
||||
|
@ -30,7 +34,7 @@ public:
|
|||
_duplicate(0)
|
||||
{}
|
||||
|
||||
float getUnreasonableRate() const { return (float)_unreasonable / _expectedReceived; }
|
||||
float getOutOfOrderRate() const { return (float)(_early + _late) / _expectedReceived; }
|
||||
float getEaryRate() const { return (float)_early / _expectedReceived; }
|
||||
float getLateRate() const { return (float)_late / _expectedReceived; }
|
||||
float getLostRate() const { return (float)_lost / _expectedReceived; }
|
||||
|
@ -61,14 +65,19 @@ public:
|
|||
};
|
||||
|
||||
|
||||
SequenceNumberStats(int statsHistoryLength = 0);
|
||||
SequenceNumberStats(int statsHistoryLength = 0, int maxRecursion = DEFAULT_MAX_RECURSION);
|
||||
SequenceNumberStats(const SequenceNumberStats& other);
|
||||
SequenceNumberStats& operator=(const SequenceNumberStats& rhs);
|
||||
~SequenceNumberStats();
|
||||
|
||||
public:
|
||||
void reset();
|
||||
ArrivalInfo sequenceNumberReceived(quint16 incoming, QUuid senderUUID = QUuid(), const bool wantExtraDebugging = false);
|
||||
void pruneMissingSet(const bool wantExtraDebugging = false);
|
||||
void pushStatsToHistory() { _statsHistory.insert(_stats); }
|
||||
|
||||
quint32 getReceived() const { return _received; }
|
||||
float getUnreasonableRate() const { return _stats._unreasonable / _received; }
|
||||
|
||||
quint32 getExpectedReceived() const { return _stats._expectedReceived; }
|
||||
quint32 getUnreasonable() const { return _stats._unreasonable; }
|
||||
|
@ -94,6 +103,14 @@ private:
|
|||
QUuid _lastSenderUUID;
|
||||
|
||||
RingBufferHistory<PacketStreamStats> _statsHistory;
|
||||
|
||||
|
||||
// to deal with the incoming seq nums going out of sync with this tracker, we'll create another instance
|
||||
// of this class when we encounter an unreasonable
|
||||
SequenceNumberStats* _unreasonableTracker;
|
||||
int _maxRecursion;
|
||||
|
||||
bool hasUnreasonableTracker() const { return _unreasonableTracker != NULL; }
|
||||
};
|
||||
|
||||
#endif // hifi_SequenceNumberStats_h
|
||||
|
|
Loading…
Reference in a new issue