added rollover handling to OctreeSceneStats

This commit is contained in:
wangyix 2014-06-17 16:40:08 -07:00
parent 604b17185b
commit 7f4cf3719e

View file

@ -842,8 +842,8 @@ const char* OctreeSceneStats::getItemValue(Item item) {
} }
void OctreeSceneStats::trackIncomingOctreePacket(const QByteArray& packet, void OctreeSceneStats::trackIncomingOctreePacket(const QByteArray& packet,
bool wasStatsPacket, int nodeClockSkewUsec) { bool wasStatsPacket, int nodeClockSkewUsec) {
const bool wantExtraDebugging = false; const bool wantExtraDebugging = true;
int numBytesPacketHeader = numBytesForPacketHeader(packet); int numBytesPacketHeader = numBytesForPacketHeader(packet);
const unsigned char* dataAt = reinterpret_cast<const unsigned char*>(packet.data()) + numBytesPacketHeader; const unsigned char* dataAt = reinterpret_cast<const unsigned char*>(packet.data()) + numBytesPacketHeader;
@ -852,10 +852,10 @@ void OctreeSceneStats::trackIncomingOctreePacket(const QByteArray& packet,
dataAt += sizeof(OCTREE_PACKET_FLAGS); dataAt += sizeof(OCTREE_PACKET_FLAGS);
OCTREE_PACKET_SEQUENCE sequence = (*(OCTREE_PACKET_SEQUENCE*)dataAt); OCTREE_PACKET_SEQUENCE sequence = (*(OCTREE_PACKET_SEQUENCE*)dataAt);
dataAt += sizeof(OCTREE_PACKET_SEQUENCE); dataAt += sizeof(OCTREE_PACKET_SEQUENCE);
OCTREE_PACKET_SENT_TIME sentAt = (*(OCTREE_PACKET_SENT_TIME*)dataAt); OCTREE_PACKET_SENT_TIME sentAt = (*(OCTREE_PACKET_SENT_TIME*)dataAt);
dataAt += sizeof(OCTREE_PACKET_SENT_TIME); dataAt += sizeof(OCTREE_PACKET_SENT_TIME);
//bool packetIsColored = oneAtBit(flags, PACKET_IS_COLOR_BIT); //bool packetIsColored = oneAtBit(flags, PACKET_IS_COLOR_BIT);
//bool packetIsCompressed = oneAtBit(flags, PACKET_IS_COMPRESSED_BIT); //bool packetIsCompressed = oneAtBit(flags, PACKET_IS_COMPRESSED_BIT);
@ -877,49 +877,67 @@ void OctreeSceneStats::trackIncomingOctreePacket(const QByteArray& packet,
return; // ignore any packets that are unreasonable return; // ignore any packets that are unreasonable
} }
const int UINT16_RANGE = UINT16_MAX + 1;
// determine our expected sequence number... handle rollover appropriately // determine our expected sequence number... handle rollover appropriately
OCTREE_PACKET_SEQUENCE expected = _incomingPacket > 0 ? _incomingLastSequence + 1 : sequence; OCTREE_PACKET_SEQUENCE expected = _incomingPacket > 0 ? _incomingLastSequence + (quint16)1 : sequence;
// Guard against possible corrupted packets... with bad sequence numbers
const int MAX_RESONABLE_SEQUENCE_OFFSET = 2000;
const int MIN_RESONABLE_SEQUENCE_OFFSET = -2000;
int sequenceOffset = (sequence - expected);
if (sequenceOffset > MAX_RESONABLE_SEQUENCE_OFFSET || sequenceOffset < MIN_RESONABLE_SEQUENCE_OFFSET) {
qDebug() << "ignoring unreasonable packet... sequence:" << sequence << "_incomingLastSequence:" << _incomingLastSequence;
return; // ignore any packets that are unreasonable
}
// track packets here...
_incomingPacket++;
_incomingBytes += packet.size();
if (!wasStatsPacket) {
_incomingWastedBytes += (MAX_PACKET_SIZE - packet.size());
}
const int USECS_PER_MSEC = 1000; const int USECS_PER_MSEC = 1000;
float flightTimeMsecs = flightTime / USECS_PER_MSEC; float flightTimeMsecs = flightTime / USECS_PER_MSEC;
_incomingFlightTimeAverage.updateAverage(flightTimeMsecs); _incomingFlightTimeAverage.updateAverage(flightTimeMsecs);
// track out of order and possibly lost packets... // track out of order and possibly lost packets...
if (sequence == _incomingLastSequence) { if (sequence == _incomingLastSequence) {
if (wantExtraDebugging) { if (wantExtraDebugging) {
qDebug() << "last packet duplicate got:" << sequence << "_incomingLastSequence:" << _incomingLastSequence; qDebug() << "last packet duplicate got:" << sequence << "_incomingLastSequence:" << _incomingLastSequence;
} }
} else { }
else {
if (sequence != expected) { if (sequence != expected) {
if (wantExtraDebugging) { if (wantExtraDebugging) {
qDebug() << "out of order... got:" << sequence << "expected:" << expected; qDebug() << "out of order... got:" << sequence << "expected:" << expected;
} }
int sequenceInt = (int)sequence;
int expectedInt = (int)expected;
// if distance between sequence and expected are more than half of the total range of possible seq numbers,
// assume that a rollover occurred between the two.
// correct the larger one so it's in the range [-UINT16_RANGE, -1] while the other remains in [0, UINT16_RANGE-1]
// after doing so, sequenceInt and expectedInt can be correctly compared to each other, though one may be negative
if (std::abs(sequenceInt - expectedInt) > UINT16_RANGE / 2) {
if (sequenceInt > expectedInt) {
sequenceInt -= UINT16_RANGE;
}
else {
expectedInt -= UINT16_RANGE;
}
}
// Guard against possible corrupted packets... with bad sequence numbers
const int MAX_RESONABLE_SEQUENCE_OFFSET = 2000;
const int MIN_RESONABLE_SEQUENCE_OFFSET = -2000;
int sequenceOffset = (sequenceInt - expectedInt);
if (sequenceOffset > MAX_RESONABLE_SEQUENCE_OFFSET || sequenceOffset < MIN_RESONABLE_SEQUENCE_OFFSET) {
qDebug() << "ignoring unreasonable packet... sequence:" << sequence << "_incomingLastSequence:" << _incomingLastSequence;
return; // ignore any packets that are unreasonable
}
// if the sequence is less than our expected, then this might be a packet // if the sequence is less than our expected, then this might be a packet
// that was delayed and so we should find it in our lostSequence list // that was delayed and so we should find it in our lostSequence list
if (sequence < expected) { if (sequenceInt < expectedInt) {
// if no rollover between them: sequenceInt, expectedInt are both in range [0, UINT16_RANGE-1]
// if rollover between them: sequenceInt in [-UINT16_RANGE, -1], expectedInt in [0, UINT16_RANGE-1]
if (wantExtraDebugging) { if (wantExtraDebugging) {
qDebug() << "this packet is later than expected..."; qDebug() << "this packet is later than expected...";
} }
if (sequence < std::max(0, (expected - MAX_MISSING_SEQUENCE_OLD_AGE))) { if (sequenceInt < expectedInt - MAX_MISSING_SEQUENCE_OLD_AGE) {
_incomingReallyLate++; _incomingReallyLate++;
} else { }
else {
_incomingLate++; _incomingLate++;
} }
@ -931,57 +949,80 @@ void OctreeSceneStats::trackIncomingOctreePacket(const QByteArray& packet,
_sequenceNumbersToNack.remove(sequence); _sequenceNumbersToNack.remove(sequence);
_incomingLikelyLost--; _incomingLikelyLost--;
_incomingRecovered++; _incomingRecovered++;
} else { }
else {
// if we're still in our pruning window, and we didn't find it in our missing list, // if we're still in our pruning window, and we didn't find it in our missing list,
// than this is really unexpected and can probably only happen if the packet was a // than this is really unexpected and can probably only happen if the packet was a
// duplicate // duplicate
if (sequence >= std::max(0, (expected - MAX_MISSING_SEQUENCE_OLD_AGE))) { if (sequenceInt >= expectedInt - MAX_MISSING_SEQUENCE_OLD_AGE) {
if (wantExtraDebugging) { if (wantExtraDebugging) {
qDebug() << "sequence:" << sequence << "WAS NOT found in _missingSequenceNumbers, and not that old... (expected - MAX_MISSING_SEQUENCE_OLD_AGE):" << (expected - MAX_MISSING_SEQUENCE_OLD_AGE); qDebug() << "sequence:" << sequence << "WAS NOT found in _missingSequenceNumbers, and not that old... (expected - MAX_MISSING_SEQUENCE_OLD_AGE):"
<< (uint16_t)(expectedInt - MAX_MISSING_SEQUENCE_OLD_AGE);
} }
_incomingPossibleDuplicate++; _incomingPossibleDuplicate++;
} }
} }
// don't update _incomingLastSequence in this case.
// only bump the last sequence if it was greater than our expected sequence, this will keep us from
// accidentally going backwards when an out of order (recovered) packet comes in
} }
else { // sequenceInt > expectedInt
if (sequence > expected) {
// if no rollover between them: sequenceInt, expectedInt are both in range [0, UINT16_RANGE-1]
// if rollover between them: sequenceInt in [0, UINT16_RANGE-1], expectedInt in [-UINT16_RANGE, -1]
if (wantExtraDebugging) { if (wantExtraDebugging) {
qDebug() << "this packet is earlier than expected..."; qDebug() << "this packet is earlier than expected...";
} }
_incomingEarly++; _incomingEarly++;
// hmm... so, we either didn't get some packets, or this guy came early... // hmm... so, we either didn't get some packets, or this guy came early...
unsigned int missing = sequence - expected; int missing = sequenceInt - expectedInt;
if (wantExtraDebugging) { if (wantExtraDebugging) {
qDebug() << ">>>>>>>> missing gap=" << missing; qDebug() << ">>>>>>>> missing gap=" << missing;
} }
_incomingLikelyLost += missing; _incomingLikelyLost += missing;
for(unsigned int missingSequence = expected; missingSequence < sequence; missingSequence++) { for (int missingSequenceInt = expectedInt; missingSequenceInt < sequenceInt; missingSequenceInt++) {
OCTREE_PACKET_SEQUENCE missingSequence = missingSequenceInt >= 0 ? missingSequenceInt : missingSequenceInt + UINT16_RANGE;
_missingSequenceNumbers << missingSequence; _missingSequenceNumbers << missingSequence;
_sequenceNumbersToNack << missingSequence; _sequenceNumbersToNack << missingSequence;
} }
_incomingLastSequence = sequence;
} }
} }
else { // sequence = expected
_incomingLastSequence = sequence;
}
} }
// only bump the last sequence if it was greater than our expected sequence, this will keep us from
// accidentally going backwards when an out of order (recovered) packet comes in
if (sequence >= expected) {
_incomingLastSequence = sequence;
}
// do some garbage collecting on our _missingSequenceNumbers // do some garbage collecting on our _missingSequenceNumbers
if (_missingSequenceNumbers.size() > MAX_MISSING_SEQUENCE) { if (_missingSequenceNumbers.size() > MAX_MISSING_SEQUENCE) {
if (wantExtraDebugging) { if (wantExtraDebugging) {
qDebug() << "too many _missingSequenceNumbers:" << _missingSequenceNumbers.size(); qDebug() << "too many _missingSequenceNumbers:" << _missingSequenceNumbers.size();
} }
int oldAgeCutoff = (int)_incomingLastSequence - MAX_MISSING_SEQUENCE_OLD_AGE;
foreach(uint16_t missingItem, _missingSequenceNumbers) { foreach(uint16_t missingItem, _missingSequenceNumbers) {
if (wantExtraDebugging) { if (wantExtraDebugging) {
qDebug() << "checking item:" << missingItem << "is it in need of pruning?"; qDebug() << "checking item:" << missingItem << "is it in need of pruning?";
qDebug() << "(_incomingLastSequence - MAX_MISSING_SEQUENCE_OLD_AGE):" qDebug() << "(_incomingLastSequence - MAX_MISSING_SEQUENCE_OLD_AGE):"
<< (_incomingLastSequence - MAX_MISSING_SEQUENCE_OLD_AGE); << (uint16_t)((int)_incomingLastSequence - MAX_MISSING_SEQUENCE_OLD_AGE);
} }
if (missingItem <= std::max(0, _incomingLastSequence - MAX_MISSING_SEQUENCE_OLD_AGE)) {
bool prune;
if (oldAgeCutoff >= 0) {
prune = (missingItem <= oldAgeCutoff || missingItem > _incomingLastSequence);
}
else {
prune = (missingItem <= oldAgeCutoff + UINT16_RANGE && missingItem > _incomingLastSequence);
}
if (prune) {
if (wantExtraDebugging) { if (wantExtraDebugging) {
qDebug() << "pruning really old missing sequence:" << missingItem; qDebug() << "pruning really old missing sequence:" << missingItem;
} }
@ -991,6 +1032,12 @@ void OctreeSceneStats::trackIncomingOctreePacket(const QByteArray& packet,
} }
} }
// track packets here...
_incomingPacket++;
_incomingBytes += packet.size();
if (!wasStatsPacket) {
_incomingWastedBytes += (MAX_PACKET_SIZE - packet.size());
}
} }
int OctreeSceneStats::getNumSequenceNumbersToNack() const { int OctreeSceneStats::getNumSequenceNumbersToNack() const {