mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-29 13:03:11 +02:00
Merge pull request #7727 from ZappoMan/supportLargeClockSkew
support for larger than 35 minute clock skew
This commit is contained in:
commit
04dab65b59
22 changed files with 158 additions and 67 deletions
|
@ -952,6 +952,24 @@ bool OctreeServer::readOptionInt(const QString& optionName, const QJsonObject& s
|
||||||
return optionAvailable;
|
return optionAvailable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool OctreeServer::readOptionInt64(const QString& optionName, const QJsonObject& settingsSectionObject, qint64& result) {
|
||||||
|
bool optionAvailable = false;
|
||||||
|
QString argName = "--" + optionName;
|
||||||
|
const char* argValue = getCmdOption(_argc, _argv, qPrintable(argName));
|
||||||
|
if (argValue) {
|
||||||
|
optionAvailable = true;
|
||||||
|
result = atoll(argValue);
|
||||||
|
qDebug() << "From payload arguments: " << qPrintable(argName) << ":" << result;
|
||||||
|
} else if (settingsSectionObject.contains(optionName)) {
|
||||||
|
optionAvailable = true;
|
||||||
|
result = settingsSectionObject[optionName].toString().toLongLong(&optionAvailable);
|
||||||
|
if (optionAvailable) {
|
||||||
|
qDebug() << "From domain settings: " << qPrintable(optionName) << ":" << result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return optionAvailable;
|
||||||
|
}
|
||||||
|
|
||||||
bool OctreeServer::readOptionString(const QString& optionName, const QJsonObject& settingsSectionObject, QString& result) {
|
bool OctreeServer::readOptionString(const QString& optionName, const QJsonObject& settingsSectionObject, QString& result) {
|
||||||
bool optionAvailable = false;
|
bool optionAvailable = false;
|
||||||
QString argName = "--" + optionName;
|
QString argName = "--" + optionName;
|
||||||
|
@ -1055,10 +1073,10 @@ void OctreeServer::readConfiguration() {
|
||||||
// Debug option to demonstrate that the server's local time does not
|
// Debug option to demonstrate that the server's local time does not
|
||||||
// need to be in sync with any other network node. This forces clock
|
// need to be in sync with any other network node. This forces clock
|
||||||
// skew for the individual server node
|
// skew for the individual server node
|
||||||
int clockSkew;
|
qint64 clockSkew;
|
||||||
if (readOptionInt(QString("clockSkew"), settingsSectionObject, clockSkew)) {
|
if (readOptionInt64(QString("clockSkew"), settingsSectionObject, clockSkew)) {
|
||||||
usecTimestampNowForceClockSkew(clockSkew);
|
usecTimestampNowForceClockSkew(clockSkew);
|
||||||
qDebug("clockSkew=%d", clockSkew);
|
qDebug() << "clockSkew=" << clockSkew;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check to see if the user passed in a command line option for setting packet send rate
|
// Check to see if the user passed in a command line option for setting packet send rate
|
||||||
|
|
|
@ -145,6 +145,7 @@ protected:
|
||||||
virtual OctreePointer createTree() = 0;
|
virtual OctreePointer createTree() = 0;
|
||||||
bool readOptionBool(const QString& optionName, const QJsonObject& settingsSectionObject, bool& result);
|
bool readOptionBool(const QString& optionName, const QJsonObject& settingsSectionObject, bool& result);
|
||||||
bool readOptionInt(const QString& optionName, const QJsonObject& settingsSectionObject, int& result);
|
bool readOptionInt(const QString& optionName, const QJsonObject& settingsSectionObject, int& result);
|
||||||
|
bool readOptionInt64(const QString& optionName, const QJsonObject& settingsSectionObject, qint64& result);
|
||||||
bool readOptionString(const QString& optionName, const QJsonObject& settingsSectionObject, QString& result);
|
bool readOptionString(const QString& optionName, const QJsonObject& settingsSectionObject, QString& result);
|
||||||
void readConfiguration();
|
void readConfiguration();
|
||||||
virtual void readAdditionalConfiguration(const QJsonObject& settingsSectionObject) { };
|
virtual void readAdditionalConfiguration(const QJsonObject& settingsSectionObject) { };
|
||||||
|
|
|
@ -127,9 +127,9 @@ int main(int argc, const char* argv[]) {
|
||||||
const char* CLOCK_SKEW = "--clockSkew";
|
const char* CLOCK_SKEW = "--clockSkew";
|
||||||
const char* clockSkewOption = getCmdOption(argc, argv, CLOCK_SKEW);
|
const char* clockSkewOption = getCmdOption(argc, argv, CLOCK_SKEW);
|
||||||
if (clockSkewOption) {
|
if (clockSkewOption) {
|
||||||
int clockSkew = atoi(clockSkewOption);
|
qint64 clockSkew = atoll(clockSkewOption);
|
||||||
usecTimestampNowForceClockSkew(clockSkew);
|
usecTimestampNowForceClockSkew(clockSkew);
|
||||||
qCDebug(interfaceapp, "clockSkewOption=%s clockSkew=%d", clockSkewOption, clockSkew);
|
qCDebug(interfaceapp) << "clockSkewOption=" << clockSkewOption << "clockSkew=" << clockSkew;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Oculus initialization MUST PRECEDE OpenGL context creation.
|
// Oculus initialization MUST PRECEDE OpenGL context creation.
|
||||||
|
|
|
@ -515,7 +515,9 @@ void OctreeStatsDialog::showOctreeServersOfType(int& serverCount, NodeType_t ser
|
||||||
QString incomingLikelyLostString = locale.toString((uint)seqStats.getLost());
|
QString incomingLikelyLostString = locale.toString((uint)seqStats.getLost());
|
||||||
QString incomingRecovered = locale.toString((uint)seqStats.getRecovered());
|
QString incomingRecovered = locale.toString((uint)seqStats.getRecovered());
|
||||||
|
|
||||||
int clockSkewInMS = node->getClockSkewUsec() / (int)USECS_PER_MSEC;
|
qint64 clockSkewInUsecs = node->getClockSkewUsec();
|
||||||
|
QString formattedClockSkewString = formatUsecTime(clockSkewInUsecs);
|
||||||
|
qint64 clockSkewInMS = clockSkewInUsecs / (qint64)USECS_PER_MSEC;
|
||||||
QString incomingFlightTimeString = locale.toString((int)stats.getIncomingFlightTimeAverage());
|
QString incomingFlightTimeString = locale.toString((int)stats.getIncomingFlightTimeAverage());
|
||||||
QString incomingPingTimeString = locale.toString(node->getPingMs());
|
QString incomingPingTimeString = locale.toString(node->getPingMs());
|
||||||
QString incomingClockSkewString = locale.toString(clockSkewInMS);
|
QString incomingClockSkewString = locale.toString(clockSkewInMS);
|
||||||
|
@ -536,7 +538,9 @@ void OctreeStatsDialog::showOctreeServersOfType(int& serverCount, NodeType_t ser
|
||||||
" Average Ping Time: " << qPrintable(incomingPingTimeString) << " msecs";
|
" Average Ping Time: " << qPrintable(incomingPingTimeString) << " msecs";
|
||||||
|
|
||||||
serverDetails << "<br/>" <<
|
serverDetails << "<br/>" <<
|
||||||
" Average Clock Skew: " << qPrintable(incomingClockSkewString) << " msecs";
|
" Average Clock Skew: " << qPrintable(incomingClockSkewString) << " msecs" <<
|
||||||
|
" [" << qPrintable(formattedClockSkewString) << "]";
|
||||||
|
|
||||||
|
|
||||||
serverDetails << "<br/>" << "Incoming" <<
|
serverDetails << "<br/>" << "Incoming" <<
|
||||||
" Bytes: " << qPrintable(incomingBytesString) <<
|
" Bytes: " << qPrintable(incomingBytesString) <<
|
||||||
|
|
|
@ -29,7 +29,7 @@ void EntityEditPacketSender::processEntityEditNackPacket(QSharedPointer<Received
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityEditPacketSender::adjustEditPacketForClockSkew(PacketType type, QByteArray& buffer, int clockSkew) {
|
void EntityEditPacketSender::adjustEditPacketForClockSkew(PacketType type, QByteArray& buffer, qint64 clockSkew) {
|
||||||
if (type == PacketType::EntityAdd || type == PacketType::EntityEdit) {
|
if (type == PacketType::EntityAdd || type == PacketType::EntityEdit) {
|
||||||
EntityItem::adjustEditPacketForClockSkew(buffer, clockSkew);
|
EntityItem::adjustEditPacketForClockSkew(buffer, clockSkew);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ public:
|
||||||
|
|
||||||
// My server type is the model server
|
// My server type is the model server
|
||||||
virtual char getMyNodeType() const { return NodeType::EntityServer; }
|
virtual char getMyNodeType() const { return NodeType::EntityServer; }
|
||||||
virtual void adjustEditPacketForClockSkew(PacketType type, QByteArray& buffer, int clockSkew);
|
virtual void adjustEditPacketForClockSkew(PacketType type, QByteArray& buffer, qint64 clockSkew);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void processEntityEditNackPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode);
|
void processEntityEditNackPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode);
|
||||||
|
|
|
@ -370,7 +370,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int clockSkew = args.sourceNode ? args.sourceNode->getClockSkewUsec() : 0;
|
qint64 clockSkew = args.sourceNode ? args.sourceNode->getClockSkewUsec() : 0;
|
||||||
|
|
||||||
BufferParser parser(data, bytesLeftToRead);
|
BufferParser parser(data, bytesLeftToRead);
|
||||||
|
|
||||||
|
@ -485,7 +485,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
||||||
qCDebug(entities) << " now:" << now;
|
qCDebug(entities) << " now:" << now;
|
||||||
qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now);
|
qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now);
|
||||||
qCDebug(entities) << " lastEditedFromBuffer:" << debugTime(lastEditedFromBuffer, now);
|
qCDebug(entities) << " lastEditedFromBuffer:" << debugTime(lastEditedFromBuffer, now);
|
||||||
qCDebug(entities) << " clockSkew:" << debugTimeOnly(clockSkew);
|
qCDebug(entities) << " clockSkew:" << clockSkew;
|
||||||
qCDebug(entities) << " lastEditedFromBufferAdjusted:" << debugTime(lastEditedFromBufferAdjusted, now);
|
qCDebug(entities) << " lastEditedFromBufferAdjusted:" << debugTime(lastEditedFromBufferAdjusted, now);
|
||||||
qCDebug(entities) << " _lastEditedFromRemote:" << debugTime(_lastEditedFromRemote, now);
|
qCDebug(entities) << " _lastEditedFromRemote:" << debugTime(_lastEditedFromRemote, now);
|
||||||
qCDebug(entities) << " _lastEditedFromRemoteInRemoteTime:" << debugTime(_lastEditedFromRemoteInRemoteTime, now);
|
qCDebug(entities) << " _lastEditedFromRemoteInRemoteTime:" << debugTime(_lastEditedFromRemoteInRemoteTime, now);
|
||||||
|
@ -760,7 +760,7 @@ void EntityItem::debugDump() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
// adjust any internal timestamps to fix clock skew for this server
|
// adjust any internal timestamps to fix clock skew for this server
|
||||||
void EntityItem::adjustEditPacketForClockSkew(QByteArray& buffer, int clockSkew) {
|
void EntityItem::adjustEditPacketForClockSkew(QByteArray& buffer, qint64 clockSkew) {
|
||||||
unsigned char* dataAt = reinterpret_cast<unsigned char*>(buffer.data());
|
unsigned char* dataAt = reinterpret_cast<unsigned char*>(buffer.data());
|
||||||
int octets = numberOfThreeBitSectionsInCode(dataAt);
|
int octets = numberOfThreeBitSectionsInCode(dataAt);
|
||||||
int lengthOfOctcode = (int)bytesRequiredForCodeLength(octets);
|
int lengthOfOctcode = (int)bytesRequiredForCodeLength(octets);
|
||||||
|
|
|
@ -144,7 +144,7 @@ public:
|
||||||
|
|
||||||
static int expectedBytes();
|
static int expectedBytes();
|
||||||
|
|
||||||
static void adjustEditPacketForClockSkew(QByteArray& buffer, int clockSkew);
|
static void adjustEditPacketForClockSkew(QByteArray& buffer, qint64 clockSkew);
|
||||||
|
|
||||||
// perform update
|
// perform update
|
||||||
virtual void update(const quint64& now) { _lastUpdated = now; }
|
virtual void update(const quint64& now) { _lastUpdated = now; }
|
||||||
|
|
|
@ -73,9 +73,9 @@ void Node::setType(char type) {
|
||||||
_symmetricSocket.setObjectName(typeString);
|
_symmetricSocket.setObjectName(typeString);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Node::updateClockSkewUsec(int clockSkewSample) {
|
void Node::updateClockSkewUsec(qint64 clockSkewSample) {
|
||||||
_clockSkewMovingPercentile.updatePercentile((float)clockSkewSample);
|
_clockSkewMovingPercentile.updatePercentile(clockSkewSample);
|
||||||
_clockSkewUsec = (int)_clockSkewMovingPercentile.getValueAtPercentile();
|
_clockSkewUsec = (quint64)_clockSkewMovingPercentile.getValueAtPercentile();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -54,8 +54,8 @@ public:
|
||||||
int getPingMs() const { return _pingMs; }
|
int getPingMs() const { return _pingMs; }
|
||||||
void setPingMs(int pingMs) { _pingMs = pingMs; }
|
void setPingMs(int pingMs) { _pingMs = pingMs; }
|
||||||
|
|
||||||
int getClockSkewUsec() const { return _clockSkewUsec; }
|
qint64 getClockSkewUsec() const { return _clockSkewUsec; }
|
||||||
void updateClockSkewUsec(int clockSkewSample);
|
void updateClockSkewUsec(qint64 clockSkewSample);
|
||||||
QMutex& getMutex() { return _mutex; }
|
QMutex& getMutex() { return _mutex; }
|
||||||
|
|
||||||
void setIsAllowedEditor(bool isAllowedEditor) { _isAllowedEditor = isAllowedEditor; }
|
void setIsAllowedEditor(bool isAllowedEditor) { _isAllowedEditor = isAllowedEditor; }
|
||||||
|
@ -78,7 +78,7 @@ private:
|
||||||
std::unique_ptr<NodeData> _linkedData;
|
std::unique_ptr<NodeData> _linkedData;
|
||||||
bool _isAlive;
|
bool _isAlive;
|
||||||
int _pingMs;
|
int _pingMs;
|
||||||
int _clockSkewUsec;
|
qint64 _clockSkewUsec;
|
||||||
QMutex _mutex;
|
QMutex _mutex;
|
||||||
MovingPercentile _clockSkewMovingPercentile;
|
MovingPercentile _clockSkewMovingPercentile;
|
||||||
bool _isAllowedEditor;
|
bool _isAllowedEditor;
|
||||||
|
|
|
@ -147,13 +147,13 @@ void NodeList::timePingReply(ReceivedMessage& message, const SharedNodePointer&
|
||||||
message.readPrimitive(&othersReplyTime);
|
message.readPrimitive(&othersReplyTime);
|
||||||
|
|
||||||
quint64 now = usecTimestampNow();
|
quint64 now = usecTimestampNow();
|
||||||
int pingTime = now - ourOriginalTime;
|
qint64 pingTime = now - ourOriginalTime;
|
||||||
int oneWayFlightTime = pingTime / 2; // half of the ping is our one way flight
|
qint64 oneWayFlightTime = pingTime / 2; // half of the ping is our one way flight
|
||||||
|
|
||||||
// The other node's expected time should be our original time plus the one way flight time
|
// The other node's expected time should be our original time plus the one way flight time
|
||||||
// anything other than that is clock skew
|
// anything other than that is clock skew
|
||||||
quint64 othersExpectedReply = ourOriginalTime + oneWayFlightTime;
|
quint64 othersExpectedReply = ourOriginalTime + oneWayFlightTime;
|
||||||
int clockSkew = othersReplyTime - othersExpectedReply;
|
qint64 clockSkew = othersReplyTime - othersExpectedReply;
|
||||||
|
|
||||||
sendingNode->setPingMs(pingTime / 1000);
|
sendingNode->setPingMs(pingTime / 1000);
|
||||||
sendingNode->updateClockSkewUsec(clockSkew);
|
sendingNode->updateClockSkewUsec(clockSkew);
|
||||||
|
@ -161,6 +161,7 @@ void NodeList::timePingReply(ReceivedMessage& message, const SharedNodePointer&
|
||||||
const bool wantDebug = false;
|
const bool wantDebug = false;
|
||||||
|
|
||||||
if (wantDebug) {
|
if (wantDebug) {
|
||||||
|
auto averageClockSkew = sendingNode->getClockSkewUsec();
|
||||||
qCDebug(networking) << "PING_REPLY from node " << *sendingNode << "\n" <<
|
qCDebug(networking) << "PING_REPLY from node " << *sendingNode << "\n" <<
|
||||||
" now: " << now << "\n" <<
|
" now: " << now << "\n" <<
|
||||||
" ourTime: " << ourOriginalTime << "\n" <<
|
" ourTime: " << ourOriginalTime << "\n" <<
|
||||||
|
@ -168,8 +169,8 @@ void NodeList::timePingReply(ReceivedMessage& message, const SharedNodePointer&
|
||||||
" oneWayFlightTime: " << oneWayFlightTime << "\n" <<
|
" oneWayFlightTime: " << oneWayFlightTime << "\n" <<
|
||||||
" othersReplyTime: " << othersReplyTime << "\n" <<
|
" othersReplyTime: " << othersReplyTime << "\n" <<
|
||||||
" othersExprectedReply: " << othersExpectedReply << "\n" <<
|
" othersExprectedReply: " << othersExpectedReply << "\n" <<
|
||||||
" clockSkew: " << clockSkew << "\n" <<
|
" clockSkew: " << clockSkew << "[" << formatUsecTime(clockSkew) << "]" << "\n" <<
|
||||||
" average clockSkew: " << sendingNode->getClockSkewUsec();
|
" average clockSkew: " << averageClockSkew << "[" << formatUsecTime(averageClockSkew) << "]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -315,7 +315,7 @@ void OctreeEditPacketSender::releaseQueuedPacket(const QUuid& nodeID, std::uniqu
|
||||||
_releaseQueuedPacketMutex.unlock();
|
_releaseQueuedPacketMutex.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<NLPacket> OctreeEditPacketSender::initializePacket(PacketType type, int nodeClockSkew) {
|
std::unique_ptr<NLPacket> OctreeEditPacketSender::initializePacket(PacketType type, qint64 nodeClockSkew) {
|
||||||
auto newPacket = NLPacket::create(type);
|
auto newPacket = NLPacket::create(type);
|
||||||
|
|
||||||
// skip over sequence number for now; will be packed when packet is ready to be sent out
|
// skip over sequence number for now; will be packed when packet is ready to be sent out
|
||||||
|
|
|
@ -75,7 +75,7 @@ public:
|
||||||
|
|
||||||
// you must override these...
|
// you must override these...
|
||||||
virtual char getMyNodeType() const = 0;
|
virtual char getMyNodeType() const = 0;
|
||||||
virtual void adjustEditPacketForClockSkew(PacketType type, QByteArray& buffer, int clockSkew) { }
|
virtual void adjustEditPacketForClockSkew(PacketType type, QByteArray& buffer, qint64 clockSkew) { }
|
||||||
|
|
||||||
void processNackPacket(ReceivedMessage& message, SharedNodePointer sendingNode);
|
void processNackPacket(ReceivedMessage& message, SharedNodePointer sendingNode);
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ protected:
|
||||||
void queuePacketToNode(const QUuid& nodeID, std::unique_ptr<NLPacket> packet);
|
void queuePacketToNode(const QUuid& nodeID, std::unique_ptr<NLPacket> packet);
|
||||||
void queuePendingPacketToNodes(std::unique_ptr<NLPacket> packet);
|
void queuePendingPacketToNodes(std::unique_ptr<NLPacket> packet);
|
||||||
void queuePacketToNodes(std::unique_ptr<NLPacket> packet);
|
void queuePacketToNodes(std::unique_ptr<NLPacket> packet);
|
||||||
std::unique_ptr<NLPacket> initializePacket(PacketType type, int nodeClockSkew);
|
std::unique_ptr<NLPacket> initializePacket(PacketType type, qint64 nodeClockSkew);
|
||||||
void releaseQueuedPacket(const QUuid& nodeUUID, std::unique_ptr<NLPacket> packetBuffer); // releases specific queued packet
|
void releaseQueuedPacket(const QUuid& nodeUUID, std::unique_ptr<NLPacket> packetBuffer); // releases specific queued packet
|
||||||
|
|
||||||
void processPreServerExistsPackets();
|
void processPreServerExistsPackets();
|
||||||
|
|
|
@ -74,16 +74,19 @@ void OctreeRenderer::processDatagram(ReceivedMessage& message, SharedNodePointer
|
||||||
bool packetIsCompressed = oneAtBit(flags, PACKET_IS_COMPRESSED_BIT);
|
bool packetIsCompressed = oneAtBit(flags, PACKET_IS_COMPRESSED_BIT);
|
||||||
|
|
||||||
OCTREE_PACKET_SENT_TIME arrivedAt = usecTimestampNow();
|
OCTREE_PACKET_SENT_TIME arrivedAt = usecTimestampNow();
|
||||||
int clockSkew = sourceNode ? sourceNode->getClockSkewUsec() : 0;
|
qint64 clockSkew = sourceNode ? sourceNode->getClockSkewUsec() : 0;
|
||||||
int flightTime = arrivedAt - sentAt + clockSkew;
|
qint64 flightTime = arrivedAt - sentAt + clockSkew;
|
||||||
|
|
||||||
OCTREE_PACKET_INTERNAL_SECTION_SIZE sectionLength = 0;
|
OCTREE_PACKET_INTERNAL_SECTION_SIZE sectionLength = 0;
|
||||||
|
|
||||||
if (extraDebugging) {
|
if (extraDebugging) {
|
||||||
qCDebug(octree, "OctreeRenderer::processDatagram() ... Got Packet Section"
|
qCDebug(octree) << "OctreeRenderer::processDatagram() ... "
|
||||||
" color:%s compressed:%s sequence: %u flight:%d usec size:%lld data:%lld",
|
"Got Packet Section color:" << packetIsColored <<
|
||||||
debug::valueOf(packetIsColored), debug::valueOf(packetIsCompressed),
|
"compressed:" << packetIsCompressed <<
|
||||||
sequence, flightTime, message.getSize(), message.getBytesLeftToRead());
|
"sequence: " << sequence <<
|
||||||
|
"flight: " << flightTime << " usec" <<
|
||||||
|
"size:" << message.getSize() <<
|
||||||
|
"data:" << message.getBytesLeftToRead();
|
||||||
}
|
}
|
||||||
|
|
||||||
_packetsInLastWindow++;
|
_packetsInLastWindow++;
|
||||||
|
@ -128,12 +131,16 @@ void OctreeRenderer::processDatagram(ReceivedMessage& message, SharedNodePointer
|
||||||
packetData.loadFinalizedContent(reinterpret_cast<const unsigned char*>(message.getRawMessage() + message.getPosition()),
|
packetData.loadFinalizedContent(reinterpret_cast<const unsigned char*>(message.getRawMessage() + message.getPosition()),
|
||||||
sectionLength);
|
sectionLength);
|
||||||
if (extraDebugging) {
|
if (extraDebugging) {
|
||||||
qCDebug(octree, "OctreeRenderer::processDatagram() ... Got Packet Section"
|
qCDebug(octree) << "OctreeRenderer::processDatagram() ... "
|
||||||
" color:%s compressed:%s sequence: %u flight:%d usec size:%lld data:%lld"
|
"Got Packet Section color:" << packetIsColored <<
|
||||||
" subsection:%d sectionLength:%d uncompressed:%d",
|
"compressed:" << packetIsCompressed <<
|
||||||
debug::valueOf(packetIsColored), debug::valueOf(packetIsCompressed),
|
"sequence: " << sequence <<
|
||||||
sequence, flightTime, message.getSize(), message.getBytesLeftToRead(), subsection, sectionLength,
|
"flight: " << flightTime << " usec" <<
|
||||||
packetData.getUncompressedSize());
|
"size:" << message.getSize() <<
|
||||||
|
"data:" << message.getBytesLeftToRead() <<
|
||||||
|
"subsection:" << subsection <<
|
||||||
|
"sectionLength:" << sectionLength <<
|
||||||
|
"uncompressed:" << packetData.getUncompressedSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (extraDebugging) {
|
if (extraDebugging) {
|
||||||
|
|
|
@ -746,7 +746,7 @@ const char* OctreeSceneStats::getItemValue(Item item) {
|
||||||
return _itemValueBuffer;
|
return _itemValueBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OctreeSceneStats::trackIncomingOctreePacket(ReceivedMessage& message, bool wasStatsPacket, int nodeClockSkewUsec) {
|
void OctreeSceneStats::trackIncomingOctreePacket(ReceivedMessage& message, bool wasStatsPacket, qint64 nodeClockSkewUsec) {
|
||||||
const bool wantExtraDebugging = false;
|
const bool wantExtraDebugging = false;
|
||||||
|
|
||||||
// skip past the flags
|
// skip past the flags
|
||||||
|
@ -768,12 +768,13 @@ void OctreeSceneStats::trackIncomingOctreePacket(ReceivedMessage& message, bool
|
||||||
qCDebug(octree) << "sentAt:" << sentAt << " usecs";
|
qCDebug(octree) << "sentAt:" << sentAt << " usecs";
|
||||||
qCDebug(octree) << "arrivedAt:" << arrivedAt << " usecs";
|
qCDebug(octree) << "arrivedAt:" << arrivedAt << " usecs";
|
||||||
qCDebug(octree) << "nodeClockSkewUsec:" << nodeClockSkewUsec << " usecs";
|
qCDebug(octree) << "nodeClockSkewUsec:" << nodeClockSkewUsec << " usecs";
|
||||||
|
qCDebug(octree) << "node Clock Skew:" << formatUsecTime(nodeClockSkewUsec);
|
||||||
qCDebug(octree) << "flightTime:" << flightTime << " usecs";
|
qCDebug(octree) << "flightTime:" << flightTime << " usecs";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Guard against possible corrupted packets... with bad timestamps
|
// Guard against possible corrupted packets... with bad timestamps
|
||||||
const int MAX_RESONABLE_FLIGHT_TIME = 200 * USECS_PER_SECOND; // 200 seconds is more than enough time for a packet to arrive
|
const qint64 MAX_RESONABLE_FLIGHT_TIME = 200 * USECS_PER_SECOND; // 200 seconds is more than enough time for a packet to arrive
|
||||||
const int MIN_RESONABLE_FLIGHT_TIME = 0;
|
const qint64 MIN_RESONABLE_FLIGHT_TIME = -1 * (qint64)USECS_PER_SECOND; // more than 1 second of "reverse flight time" would be unreasonable
|
||||||
if (flightTime > MAX_RESONABLE_FLIGHT_TIME || flightTime < MIN_RESONABLE_FLIGHT_TIME) {
|
if (flightTime > MAX_RESONABLE_FLIGHT_TIME || flightTime < MIN_RESONABLE_FLIGHT_TIME) {
|
||||||
static QString repeatedMessage
|
static QString repeatedMessage
|
||||||
= LogHandler::getInstance().addRepeatedMessageRegex(
|
= LogHandler::getInstance().addRepeatedMessageRegex(
|
||||||
|
|
|
@ -162,7 +162,7 @@ public:
|
||||||
quint64 getLastFullTotalBytes() const { return _lastFullTotalBytes; }
|
quint64 getLastFullTotalBytes() const { return _lastFullTotalBytes; }
|
||||||
|
|
||||||
// Used in client implementations to track individual octree packets
|
// Used in client implementations to track individual octree packets
|
||||||
void trackIncomingOctreePacket(ReceivedMessage& message, bool wasStatsPacket, int nodeClockSkewUsec);
|
void trackIncomingOctreePacket(ReceivedMessage& message, bool wasStatsPacket, qint64 nodeClockSkewUsec);
|
||||||
|
|
||||||
quint32 getIncomingPackets() const { return _incomingPacket; }
|
quint32 getIncomingPackets() const { return _incomingPacket; }
|
||||||
quint64 getIncomingBytes() const { return _incomingBytes; }
|
quint64 getIncomingBytes() const { return _incomingBytes; }
|
||||||
|
|
|
@ -61,7 +61,7 @@ void ObjectAction::updateAction(btCollisionWorld* collisionWorld, btScalar delta
|
||||||
updateActionWorker(deltaTimeStep);
|
updateActionWorker(deltaTimeStep);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ObjectAction::getEntityServerClockSkew() const {
|
qint64 ObjectAction::getEntityServerClockSkew() const {
|
||||||
auto nodeList = DependencyManager::get<NodeList>();
|
auto nodeList = DependencyManager::get<NodeList>();
|
||||||
|
|
||||||
auto ownerEntity = _ownerEntity.lock();
|
auto ownerEntity = _ownerEntity.lock();
|
||||||
|
@ -276,7 +276,7 @@ quint64 ObjectAction::localTimeToServerTime(quint64 timeValue) const {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int serverClockSkew = getEntityServerClockSkew();
|
qint64 serverClockSkew = getEntityServerClockSkew();
|
||||||
if (serverClockSkew < 0 && timeValue <= (quint64)(-serverClockSkew)) {
|
if (serverClockSkew < 0 && timeValue <= (quint64)(-serverClockSkew)) {
|
||||||
return 1; // non-zero but long-expired value to avoid negative roll-over
|
return 1; // non-zero but long-expired value to avoid negative roll-over
|
||||||
}
|
}
|
||||||
|
@ -290,7 +290,7 @@ quint64 ObjectAction::serverTimeToLocalTime(quint64 timeValue) const {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int serverClockSkew = getEntityServerClockSkew();
|
qint64 serverClockSkew = getEntityServerClockSkew();
|
||||||
if (serverClockSkew > 0 && timeValue <= (quint64)serverClockSkew) {
|
if (serverClockSkew > 0 && timeValue <= (quint64)serverClockSkew) {
|
||||||
return 1; // non-zero but long-expired value to avoid negative roll-over
|
return 1; // non-zero but long-expired value to avoid negative roll-over
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,7 +70,7 @@ protected:
|
||||||
quint64 _expires { 0 }; // in seconds since epoch
|
quint64 _expires { 0 }; // in seconds since epoch
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int getEntityServerClockSkew() const;
|
qint64 getEntityServerClockSkew() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_ObjectAction_h
|
#endif // hifi_ObjectAction_h
|
||||||
|
|
|
@ -17,11 +17,11 @@ MovingPercentile::MovingPercentile(int numSamples, float percentile)
|
||||||
_sampleIds(),
|
_sampleIds(),
|
||||||
_newSampleId(0),
|
_newSampleId(0),
|
||||||
_indexOfPercentile(0),
|
_indexOfPercentile(0),
|
||||||
_valueAtPercentile(0.0f)
|
_valueAtPercentile(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void MovingPercentile::updatePercentile(float sample) {
|
void MovingPercentile::updatePercentile(qint64 sample) {
|
||||||
|
|
||||||
// insert the new sample into _samplesSorted
|
// insert the new sample into _samplesSorted
|
||||||
int newSampleIndex;
|
int newSampleIndex;
|
||||||
|
|
|
@ -18,19 +18,19 @@ class MovingPercentile {
|
||||||
public:
|
public:
|
||||||
MovingPercentile(int numSamples, float percentile = 0.5f);
|
MovingPercentile(int numSamples, float percentile = 0.5f);
|
||||||
|
|
||||||
void updatePercentile(float sample);
|
void updatePercentile(qint64 sample);
|
||||||
float getValueAtPercentile() const { return _valueAtPercentile; }
|
qint64 getValueAtPercentile() const { return _valueAtPercentile; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const int _numSamples;
|
const int _numSamples;
|
||||||
const float _percentile;
|
const float _percentile;
|
||||||
|
|
||||||
QList<float> _samplesSorted;
|
QList<qint64> _samplesSorted;
|
||||||
QList<int> _sampleIds; // incrementally assigned, is cyclic
|
QList<int> _sampleIds; // incrementally assigned, is cyclic
|
||||||
int _newSampleId;
|
int _newSampleId;
|
||||||
|
|
||||||
int _indexOfPercentile;
|
int _indexOfPercentile;
|
||||||
float _valueAtPercentile;
|
qint64 _valueAtPercentile;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -19,6 +19,9 @@
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -43,8 +46,8 @@
|
||||||
#include "OctalCode.h"
|
#include "OctalCode.h"
|
||||||
#include "SharedLogging.h"
|
#include "SharedLogging.h"
|
||||||
|
|
||||||
static int usecTimestampNowAdjust = 0; // in usec
|
static qint64 usecTimestampNowAdjust = 0; // in usec
|
||||||
void usecTimestampNowForceClockSkew(int clockSkew) {
|
void usecTimestampNowForceClockSkew(qint64 clockSkew) {
|
||||||
::usecTimestampNowAdjust = clockSkew;
|
::usecTimestampNowAdjust = clockSkew;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -621,23 +624,75 @@ void debug::checkDeadBeef(void* memoryVoid, int size) {
|
||||||
assert(memcmp((unsigned char*)memoryVoid, DEADBEEF, std::min(size, DEADBEEF_SIZE)) != 0);
|
assert(memcmp((unsigned char*)memoryVoid, DEADBEEF, std::min(size, DEADBEEF_SIZE)) != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString formatUsecTime(float usecs, int prec) {
|
|
||||||
static const quint64 SECONDS_PER_MINUTE = 60;
|
// glm::abs() works for signed or unsigned types
|
||||||
static const quint64 USECS_PER_MINUTE = USECS_PER_SECOND * SECONDS_PER_MINUTE;
|
template <typename T>
|
||||||
|
QString formatUsecTime(T usecs) {
|
||||||
|
static const int PRECISION = 3;
|
||||||
|
static const int FRACTION_MASK = pow(10, PRECISION);
|
||||||
|
|
||||||
|
static const T USECS_PER_MSEC = 1000;
|
||||||
|
static const T USECS_PER_SECOND = 1000 * USECS_PER_MSEC;
|
||||||
|
static const T USECS_PER_MINUTE = USECS_PER_SECOND * 60;
|
||||||
|
static const T USECS_PER_HOUR = USECS_PER_MINUTE * 60;
|
||||||
|
|
||||||
QString result;
|
QString result;
|
||||||
if (usecs > USECS_PER_MINUTE) {
|
if (glm::abs(usecs) > USECS_PER_HOUR) {
|
||||||
result = QString::number(usecs / USECS_PER_MINUTE, 'f', prec) + "min";
|
if (std::is_integral<T>::value) {
|
||||||
} else if (usecs > USECS_PER_SECOND) {
|
result = QString::number(usecs / USECS_PER_HOUR);
|
||||||
result = QString::number(usecs / USECS_PER_SECOND, 'f', prec) + 's';
|
result += "." + QString::number(((int)(usecs * FRACTION_MASK / USECS_PER_HOUR)) % FRACTION_MASK);
|
||||||
} else if (usecs > USECS_PER_MSEC) {
|
} else {
|
||||||
result = QString::number(usecs / USECS_PER_MSEC, 'f', prec) + "ms";
|
result = QString::number(usecs / USECS_PER_HOUR, 'f', PRECISION);
|
||||||
|
}
|
||||||
|
result += " hrs";
|
||||||
|
} else if (glm::abs(usecs) > USECS_PER_MINUTE) {
|
||||||
|
if (std::is_integral<T>::value) {
|
||||||
|
result = QString::number(usecs / USECS_PER_MINUTE);
|
||||||
|
result += "." + QString::number(((int)(usecs * FRACTION_MASK / USECS_PER_MINUTE)) % FRACTION_MASK);
|
||||||
|
} else {
|
||||||
|
result = QString::number(usecs / USECS_PER_MINUTE, 'f', PRECISION);
|
||||||
|
}
|
||||||
|
result += " mins";
|
||||||
|
} else if (glm::abs(usecs) > USECS_PER_SECOND) {
|
||||||
|
if (std::is_integral<T>::value) {
|
||||||
|
result = QString::number(usecs / USECS_PER_SECOND);
|
||||||
|
result += "." + QString::number(((int)(usecs * FRACTION_MASK / USECS_PER_SECOND)) % FRACTION_MASK);
|
||||||
|
} else {
|
||||||
|
result = QString::number(usecs / USECS_PER_SECOND, 'f', PRECISION);
|
||||||
|
}
|
||||||
|
result += " secs";
|
||||||
|
} else if (glm::abs(usecs) > USECS_PER_MSEC) {
|
||||||
|
if (std::is_integral<T>::value) {
|
||||||
|
result = QString::number(usecs / USECS_PER_MSEC);
|
||||||
|
result += "." + QString::number(((int)(usecs * FRACTION_MASK / USECS_PER_MSEC)) % FRACTION_MASK);
|
||||||
|
} else {
|
||||||
|
result = QString::number(usecs / USECS_PER_MSEC, 'f', PRECISION);
|
||||||
|
}
|
||||||
|
result += " msecs";
|
||||||
} else {
|
} else {
|
||||||
result = QString::number(usecs, 'f', prec) + "us";
|
result = QString::number(usecs) + " usecs";
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QString formatUsecTime(quint64 usecs) {
|
||||||
|
return formatUsecTime<quint64>(usecs);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString formatUsecTime(qint64 usecs) {
|
||||||
|
return formatUsecTime<qint64>(usecs);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString formatUsecTime(float usecs) {
|
||||||
|
return formatUsecTime<float>(usecs);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString formatUsecTime(double usecs) {
|
||||||
|
return formatUsecTime<double>(usecs);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
QString formatSecondsElapsed(float seconds) {
|
QString formatSecondsElapsed(float seconds) {
|
||||||
QString result;
|
QString result;
|
||||||
|
|
||||||
|
|
|
@ -121,7 +121,7 @@ const QByteArray HIGH_FIDELITY_USER_AGENT = "Mozilla/5.0 (HighFidelityInterface)
|
||||||
|
|
||||||
// Equivalent to time_t but in usecs instead of secs
|
// Equivalent to time_t but in usecs instead of secs
|
||||||
quint64 usecTimestampNow(bool wantDebug = false);
|
quint64 usecTimestampNow(bool wantDebug = false);
|
||||||
void usecTimestampNowForceClockSkew(int clockSkew);
|
void usecTimestampNowForceClockSkew(qint64 clockSkew);
|
||||||
|
|
||||||
// Number of seconds expressed since the first call to this function, expressed as a float
|
// Number of seconds expressed since the first call to this function, expressed as a float
|
||||||
// Maximum accuracy in msecs
|
// Maximum accuracy in msecs
|
||||||
|
@ -186,7 +186,11 @@ inline bool isBetween(int64_t value, int64_t max, int64_t min) { return ((value
|
||||||
/// \return bool is the float NaN
|
/// \return bool is the float NaN
|
||||||
inline bool isNaN(float value) { return value != value; }
|
inline bool isNaN(float value) { return value != value; }
|
||||||
|
|
||||||
QString formatUsecTime(float usecs, int prec = 3);
|
QString formatUsecTime(float usecs);
|
||||||
|
QString formatUsecTime(double usecs);
|
||||||
|
QString formatUsecTime(quint64 usecs);
|
||||||
|
QString formatUsecTime(qint64 usecs);
|
||||||
|
|
||||||
QString formatSecondsElapsed(float seconds);
|
QString formatSecondsElapsed(float seconds);
|
||||||
bool similarStrings(const QString& stringA, const QString& stringB);
|
bool similarStrings(const QString& stringA, const QString& stringB);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue