diff --git a/assignment-client/src/octree/OctreeServer.cpp b/assignment-client/src/octree/OctreeServer.cpp index a7fa068868..d763d1abe7 100644 --- a/assignment-client/src/octree/OctreeServer.cpp +++ b/assignment-client/src/octree/OctreeServer.cpp @@ -952,6 +952,24 @@ bool OctreeServer::readOptionInt(const QString& optionName, const QJsonObject& s 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 optionAvailable = false; QString argName = "--" + optionName; @@ -1055,10 +1073,10 @@ void OctreeServer::readConfiguration() { // 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 // skew for the individual server node - int clockSkew; - if (readOptionInt(QString("clockSkew"), settingsSectionObject, clockSkew)) { + qint64 clockSkew; + if (readOptionInt64(QString("clockSkew"), settingsSectionObject, 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 diff --git a/assignment-client/src/octree/OctreeServer.h b/assignment-client/src/octree/OctreeServer.h index c96c4bb5ad..d153f31154 100644 --- a/assignment-client/src/octree/OctreeServer.h +++ b/assignment-client/src/octree/OctreeServer.h @@ -145,6 +145,7 @@ protected: virtual OctreePointer createTree() = 0; bool readOptionBool(const QString& optionName, const QJsonObject& settingsSectionObject, bool& 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); void readConfiguration(); virtual void readAdditionalConfiguration(const QJsonObject& settingsSectionObject) { }; diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 09369dc25a..4b6d50c274 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -127,9 +127,9 @@ int main(int argc, const char* argv[]) { const char* CLOCK_SKEW = "--clockSkew"; const char* clockSkewOption = getCmdOption(argc, argv, CLOCK_SKEW); if (clockSkewOption) { - int clockSkew = atoi(clockSkewOption); + qint64 clockSkew = atoll(clockSkewOption); usecTimestampNowForceClockSkew(clockSkew); - qCDebug(interfaceapp, "clockSkewOption=%s clockSkew=%d", clockSkewOption, clockSkew); + qCDebug(interfaceapp) << "clockSkewOption=" << clockSkewOption << "clockSkew=" << clockSkew; } // Oculus initialization MUST PRECEDE OpenGL context creation. diff --git a/interface/src/ui/OctreeStatsDialog.cpp b/interface/src/ui/OctreeStatsDialog.cpp index b1f7be0524..6b6d600e20 100644 --- a/interface/src/ui/OctreeStatsDialog.cpp +++ b/interface/src/ui/OctreeStatsDialog.cpp @@ -515,7 +515,9 @@ void OctreeStatsDialog::showOctreeServersOfType(int& serverCount, NodeType_t ser QString incomingLikelyLostString = locale.toString((uint)seqStats.getLost()); 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 incomingPingTimeString = locale.toString(node->getPingMs()); QString incomingClockSkewString = locale.toString(clockSkewInMS); @@ -536,7 +538,9 @@ void OctreeStatsDialog::showOctreeServersOfType(int& serverCount, NodeType_t ser " Average Ping Time: " << qPrintable(incomingPingTimeString) << " msecs"; serverDetails << "
" << - " Average Clock Skew: " << qPrintable(incomingClockSkewString) << " msecs"; + " Average Clock Skew: " << qPrintable(incomingClockSkewString) << " msecs" << + " [" << qPrintable(formattedClockSkewString) << "]"; + serverDetails << "
" << "Incoming" << " Bytes: " << qPrintable(incomingBytesString) << diff --git a/libraries/entities/src/EntityEditPacketSender.cpp b/libraries/entities/src/EntityEditPacketSender.cpp index 91f21659ec..1e38c32964 100644 --- a/libraries/entities/src/EntityEditPacketSender.cpp +++ b/libraries/entities/src/EntityEditPacketSender.cpp @@ -29,7 +29,7 @@ void EntityEditPacketSender::processEntityEditNackPacket(QSharedPointer message, SharedNodePointer sendingNode); diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 7260e5e782..83cf6ec5d6 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -370,7 +370,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef return 0; } - int clockSkew = args.sourceNode ? args.sourceNode->getClockSkewUsec() : 0; + qint64 clockSkew = args.sourceNode ? args.sourceNode->getClockSkewUsec() : 0; BufferParser parser(data, bytesLeftToRead); @@ -485,7 +485,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef qCDebug(entities) << " now:" << now; qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now); qCDebug(entities) << " lastEditedFromBuffer:" << debugTime(lastEditedFromBuffer, now); - qCDebug(entities) << " clockSkew:" << debugTimeOnly(clockSkew); + qCDebug(entities) << " clockSkew:" << clockSkew; qCDebug(entities) << " lastEditedFromBufferAdjusted:" << debugTime(lastEditedFromBufferAdjusted, now); qCDebug(entities) << " _lastEditedFromRemote:" << debugTime(_lastEditedFromRemote, 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 -void EntityItem::adjustEditPacketForClockSkew(QByteArray& buffer, int clockSkew) { +void EntityItem::adjustEditPacketForClockSkew(QByteArray& buffer, qint64 clockSkew) { unsigned char* dataAt = reinterpret_cast(buffer.data()); int octets = numberOfThreeBitSectionsInCode(dataAt); int lengthOfOctcode = (int)bytesRequiredForCodeLength(octets); diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index c145334f80..5e34d942f6 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -144,7 +144,7 @@ public: static int expectedBytes(); - static void adjustEditPacketForClockSkew(QByteArray& buffer, int clockSkew); + static void adjustEditPacketForClockSkew(QByteArray& buffer, qint64 clockSkew); // perform update virtual void update(const quint64& now) { _lastUpdated = now; } diff --git a/libraries/networking/src/Node.cpp b/libraries/networking/src/Node.cpp index 7e9bf60ea4..e4fe292223 100644 --- a/libraries/networking/src/Node.cpp +++ b/libraries/networking/src/Node.cpp @@ -73,9 +73,9 @@ void Node::setType(char type) { _symmetricSocket.setObjectName(typeString); } -void Node::updateClockSkewUsec(int clockSkewSample) { - _clockSkewMovingPercentile.updatePercentile((float)clockSkewSample); - _clockSkewUsec = (int)_clockSkewMovingPercentile.getValueAtPercentile(); +void Node::updateClockSkewUsec(qint64 clockSkewSample) { + _clockSkewMovingPercentile.updatePercentile(clockSkewSample); + _clockSkewUsec = (quint64)_clockSkewMovingPercentile.getValueAtPercentile(); } diff --git a/libraries/networking/src/Node.h b/libraries/networking/src/Node.h index ca05e5b84d..3927672319 100644 --- a/libraries/networking/src/Node.h +++ b/libraries/networking/src/Node.h @@ -54,8 +54,8 @@ public: int getPingMs() const { return _pingMs; } void setPingMs(int pingMs) { _pingMs = pingMs; } - int getClockSkewUsec() const { return _clockSkewUsec; } - void updateClockSkewUsec(int clockSkewSample); + qint64 getClockSkewUsec() const { return _clockSkewUsec; } + void updateClockSkewUsec(qint64 clockSkewSample); QMutex& getMutex() { return _mutex; } void setIsAllowedEditor(bool isAllowedEditor) { _isAllowedEditor = isAllowedEditor; } @@ -78,7 +78,7 @@ private: std::unique_ptr _linkedData; bool _isAlive; int _pingMs; - int _clockSkewUsec; + qint64 _clockSkewUsec; QMutex _mutex; MovingPercentile _clockSkewMovingPercentile; bool _isAllowedEditor; diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index 63189abb3e..25dfe884db 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -147,13 +147,13 @@ void NodeList::timePingReply(ReceivedMessage& message, const SharedNodePointer& message.readPrimitive(&othersReplyTime); quint64 now = usecTimestampNow(); - int pingTime = now - ourOriginalTime; - int oneWayFlightTime = pingTime / 2; // half of the ping is our one way flight + qint64 pingTime = now - ourOriginalTime; + 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 // anything other than that is clock skew quint64 othersExpectedReply = ourOriginalTime + oneWayFlightTime; - int clockSkew = othersReplyTime - othersExpectedReply; + qint64 clockSkew = othersReplyTime - othersExpectedReply; sendingNode->setPingMs(pingTime / 1000); sendingNode->updateClockSkewUsec(clockSkew); @@ -161,6 +161,7 @@ void NodeList::timePingReply(ReceivedMessage& message, const SharedNodePointer& const bool wantDebug = false; if (wantDebug) { + auto averageClockSkew = sendingNode->getClockSkewUsec(); qCDebug(networking) << "PING_REPLY from node " << *sendingNode << "\n" << " now: " << now << "\n" << " ourTime: " << ourOriginalTime << "\n" << @@ -168,8 +169,8 @@ void NodeList::timePingReply(ReceivedMessage& message, const SharedNodePointer& " oneWayFlightTime: " << oneWayFlightTime << "\n" << " othersReplyTime: " << othersReplyTime << "\n" << " othersExprectedReply: " << othersExpectedReply << "\n" << - " clockSkew: " << clockSkew << "\n" << - " average clockSkew: " << sendingNode->getClockSkewUsec(); + " clockSkew: " << clockSkew << "[" << formatUsecTime(clockSkew) << "]" << "\n" << + " average clockSkew: " << averageClockSkew << "[" << formatUsecTime(averageClockSkew) << "]"; } } diff --git a/libraries/octree/src/OctreeEditPacketSender.cpp b/libraries/octree/src/OctreeEditPacketSender.cpp index ad59dcbf99..f3c9ece9fe 100644 --- a/libraries/octree/src/OctreeEditPacketSender.cpp +++ b/libraries/octree/src/OctreeEditPacketSender.cpp @@ -315,7 +315,7 @@ void OctreeEditPacketSender::releaseQueuedPacket(const QUuid& nodeID, std::uniqu _releaseQueuedPacketMutex.unlock(); } -std::unique_ptr OctreeEditPacketSender::initializePacket(PacketType type, int nodeClockSkew) { +std::unique_ptr OctreeEditPacketSender::initializePacket(PacketType type, qint64 nodeClockSkew) { auto newPacket = NLPacket::create(type); // skip over sequence number for now; will be packed when packet is ready to be sent out diff --git a/libraries/octree/src/OctreeEditPacketSender.h b/libraries/octree/src/OctreeEditPacketSender.h index 12cb03fcd8..4a390814f4 100644 --- a/libraries/octree/src/OctreeEditPacketSender.h +++ b/libraries/octree/src/OctreeEditPacketSender.h @@ -75,7 +75,7 @@ public: // you must override these... 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); @@ -89,7 +89,7 @@ protected: void queuePacketToNode(const QUuid& nodeID, std::unique_ptr packet); void queuePendingPacketToNodes(std::unique_ptr packet); void queuePacketToNodes(std::unique_ptr packet); - std::unique_ptr initializePacket(PacketType type, int nodeClockSkew); + std::unique_ptr initializePacket(PacketType type, qint64 nodeClockSkew); void releaseQueuedPacket(const QUuid& nodeUUID, std::unique_ptr packetBuffer); // releases specific queued packet void processPreServerExistsPackets(); diff --git a/libraries/octree/src/OctreeRenderer.cpp b/libraries/octree/src/OctreeRenderer.cpp index 324a8ca20f..bcf7c301c7 100644 --- a/libraries/octree/src/OctreeRenderer.cpp +++ b/libraries/octree/src/OctreeRenderer.cpp @@ -74,16 +74,19 @@ void OctreeRenderer::processDatagram(ReceivedMessage& message, SharedNodePointer bool packetIsCompressed = oneAtBit(flags, PACKET_IS_COMPRESSED_BIT); OCTREE_PACKET_SENT_TIME arrivedAt = usecTimestampNow(); - int clockSkew = sourceNode ? sourceNode->getClockSkewUsec() : 0; - int flightTime = arrivedAt - sentAt + clockSkew; + qint64 clockSkew = sourceNode ? sourceNode->getClockSkewUsec() : 0; + qint64 flightTime = arrivedAt - sentAt + clockSkew; OCTREE_PACKET_INTERNAL_SECTION_SIZE sectionLength = 0; if (extraDebugging) { - qCDebug(octree, "OctreeRenderer::processDatagram() ... Got Packet Section" - " color:%s compressed:%s sequence: %u flight:%d usec size:%lld data:%lld", - debug::valueOf(packetIsColored), debug::valueOf(packetIsCompressed), - sequence, flightTime, message.getSize(), message.getBytesLeftToRead()); + qCDebug(octree) << "OctreeRenderer::processDatagram() ... " + "Got Packet Section color:" << packetIsColored << + "compressed:" << packetIsCompressed << + "sequence: " << sequence << + "flight: " << flightTime << " usec" << + "size:" << message.getSize() << + "data:" << message.getBytesLeftToRead(); } _packetsInLastWindow++; @@ -128,12 +131,16 @@ void OctreeRenderer::processDatagram(ReceivedMessage& message, SharedNodePointer packetData.loadFinalizedContent(reinterpret_cast(message.getRawMessage() + message.getPosition()), sectionLength); if (extraDebugging) { - qCDebug(octree, "OctreeRenderer::processDatagram() ... Got Packet Section" - " color:%s compressed:%s sequence: %u flight:%d usec size:%lld data:%lld" - " subsection:%d sectionLength:%d uncompressed:%d", - debug::valueOf(packetIsColored), debug::valueOf(packetIsCompressed), - sequence, flightTime, message.getSize(), message.getBytesLeftToRead(), subsection, sectionLength, - packetData.getUncompressedSize()); + qCDebug(octree) << "OctreeRenderer::processDatagram() ... " + "Got Packet Section color:" << packetIsColored << + "compressed:" << packetIsCompressed << + "sequence: " << sequence << + "flight: " << flightTime << " usec" << + "size:" << message.getSize() << + "data:" << message.getBytesLeftToRead() << + "subsection:" << subsection << + "sectionLength:" << sectionLength << + "uncompressed:" << packetData.getUncompressedSize(); } if (extraDebugging) { diff --git a/libraries/octree/src/OctreeSceneStats.cpp b/libraries/octree/src/OctreeSceneStats.cpp index f761d9ad05..578d35b687 100644 --- a/libraries/octree/src/OctreeSceneStats.cpp +++ b/libraries/octree/src/OctreeSceneStats.cpp @@ -746,7 +746,7 @@ const char* OctreeSceneStats::getItemValue(Item item) { return _itemValueBuffer; } -void OctreeSceneStats::trackIncomingOctreePacket(ReceivedMessage& message, bool wasStatsPacket, int nodeClockSkewUsec) { +void OctreeSceneStats::trackIncomingOctreePacket(ReceivedMessage& message, bool wasStatsPacket, qint64 nodeClockSkewUsec) { const bool wantExtraDebugging = false; // skip past the flags @@ -768,12 +768,13 @@ void OctreeSceneStats::trackIncomingOctreePacket(ReceivedMessage& message, bool qCDebug(octree) << "sentAt:" << sentAt << " usecs"; qCDebug(octree) << "arrivedAt:" << arrivedAt << " usecs"; qCDebug(octree) << "nodeClockSkewUsec:" << nodeClockSkewUsec << " usecs"; + qCDebug(octree) << "node Clock Skew:" << formatUsecTime(nodeClockSkewUsec); qCDebug(octree) << "flightTime:" << flightTime << " usecs"; } // 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 int MIN_RESONABLE_FLIGHT_TIME = 0; + const qint64 MAX_RESONABLE_FLIGHT_TIME = 200 * USECS_PER_SECOND; // 200 seconds is more than enough time for a packet to arrive + 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) { static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex( diff --git a/libraries/octree/src/OctreeSceneStats.h b/libraries/octree/src/OctreeSceneStats.h index a7d485a28f..11aa0b82b2 100644 --- a/libraries/octree/src/OctreeSceneStats.h +++ b/libraries/octree/src/OctreeSceneStats.h @@ -162,7 +162,7 @@ public: quint64 getLastFullTotalBytes() const { return _lastFullTotalBytes; } // 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; } quint64 getIncomingBytes() const { return _incomingBytes; } diff --git a/libraries/physics/src/ObjectAction.cpp b/libraries/physics/src/ObjectAction.cpp index d32495e30c..8d33c69d1c 100644 --- a/libraries/physics/src/ObjectAction.cpp +++ b/libraries/physics/src/ObjectAction.cpp @@ -61,7 +61,7 @@ void ObjectAction::updateAction(btCollisionWorld* collisionWorld, btScalar delta updateActionWorker(deltaTimeStep); } -int ObjectAction::getEntityServerClockSkew() const { +qint64 ObjectAction::getEntityServerClockSkew() const { auto nodeList = DependencyManager::get(); auto ownerEntity = _ownerEntity.lock(); @@ -276,7 +276,7 @@ quint64 ObjectAction::localTimeToServerTime(quint64 timeValue) const { return 0; } - int serverClockSkew = getEntityServerClockSkew(); + qint64 serverClockSkew = getEntityServerClockSkew(); if (serverClockSkew < 0 && timeValue <= (quint64)(-serverClockSkew)) { 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; } - int serverClockSkew = getEntityServerClockSkew(); + qint64 serverClockSkew = getEntityServerClockSkew(); if (serverClockSkew > 0 && timeValue <= (quint64)serverClockSkew) { return 1; // non-zero but long-expired value to avoid negative roll-over } diff --git a/libraries/physics/src/ObjectAction.h b/libraries/physics/src/ObjectAction.h index 4e3390b386..efc5808f14 100644 --- a/libraries/physics/src/ObjectAction.h +++ b/libraries/physics/src/ObjectAction.h @@ -70,7 +70,7 @@ protected: quint64 _expires { 0 }; // in seconds since epoch private: - int getEntityServerClockSkew() const; + qint64 getEntityServerClockSkew() const; }; #endif // hifi_ObjectAction_h diff --git a/libraries/shared/src/MovingPercentile.cpp b/libraries/shared/src/MovingPercentile.cpp index ec007b5c22..5bcdbb5e80 100644 --- a/libraries/shared/src/MovingPercentile.cpp +++ b/libraries/shared/src/MovingPercentile.cpp @@ -17,11 +17,11 @@ MovingPercentile::MovingPercentile(int numSamples, float percentile) _sampleIds(), _newSampleId(0), _indexOfPercentile(0), - _valueAtPercentile(0.0f) + _valueAtPercentile(0) { } -void MovingPercentile::updatePercentile(float sample) { +void MovingPercentile::updatePercentile(qint64 sample) { // insert the new sample into _samplesSorted int newSampleIndex; diff --git a/libraries/shared/src/MovingPercentile.h b/libraries/shared/src/MovingPercentile.h index 284ed9d890..bc52c4b4e7 100644 --- a/libraries/shared/src/MovingPercentile.h +++ b/libraries/shared/src/MovingPercentile.h @@ -18,19 +18,19 @@ class MovingPercentile { public: MovingPercentile(int numSamples, float percentile = 0.5f); - void updatePercentile(float sample); - float getValueAtPercentile() const { return _valueAtPercentile; } + void updatePercentile(qint64 sample); + qint64 getValueAtPercentile() const { return _valueAtPercentile; } private: const int _numSamples; const float _percentile; - QList _samplesSorted; + QList _samplesSorted; QList _sampleIds; // incrementally assigned, is cyclic int _newSampleId; int _indexOfPercentile; - float _valueAtPercentile; + qint64 _valueAtPercentile; }; #endif diff --git a/libraries/shared/src/SharedUtil.cpp b/libraries/shared/src/SharedUtil.cpp index 8f68e20222..7925c8ad4e 100644 --- a/libraries/shared/src/SharedUtil.cpp +++ b/libraries/shared/src/SharedUtil.cpp @@ -19,6 +19,9 @@ #include #include +#include + + #ifdef _WIN32 #include #endif @@ -43,8 +46,8 @@ #include "OctalCode.h" #include "SharedLogging.h" -static int usecTimestampNowAdjust = 0; // in usec -void usecTimestampNowForceClockSkew(int clockSkew) { +static qint64 usecTimestampNowAdjust = 0; // in usec +void usecTimestampNowForceClockSkew(qint64 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); } -QString formatUsecTime(float usecs, int prec) { - static const quint64 SECONDS_PER_MINUTE = 60; - static const quint64 USECS_PER_MINUTE = USECS_PER_SECOND * SECONDS_PER_MINUTE; + +// glm::abs() works for signed or unsigned types +template +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; - if (usecs > USECS_PER_MINUTE) { - result = QString::number(usecs / USECS_PER_MINUTE, 'f', prec) + "min"; - } else if (usecs > USECS_PER_SECOND) { - result = QString::number(usecs / USECS_PER_SECOND, 'f', prec) + 's'; - } else if (usecs > USECS_PER_MSEC) { - result = QString::number(usecs / USECS_PER_MSEC, 'f', prec) + "ms"; + if (glm::abs(usecs) > USECS_PER_HOUR) { + if (std::is_integral::value) { + result = QString::number(usecs / USECS_PER_HOUR); + result += "." + QString::number(((int)(usecs * FRACTION_MASK / USECS_PER_HOUR)) % FRACTION_MASK); + } else { + result = QString::number(usecs / USECS_PER_HOUR, 'f', PRECISION); + } + result += " hrs"; + } else if (glm::abs(usecs) > USECS_PER_MINUTE) { + if (std::is_integral::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::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::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 { - result = QString::number(usecs, 'f', prec) + "us"; + result = QString::number(usecs) + " usecs"; } return result; } + +QString formatUsecTime(quint64 usecs) { + return formatUsecTime(usecs); +} + +QString formatUsecTime(qint64 usecs) { + return formatUsecTime(usecs); +} + +QString formatUsecTime(float usecs) { + return formatUsecTime(usecs); +} + +QString formatUsecTime(double usecs) { + return formatUsecTime(usecs); +} + + QString formatSecondsElapsed(float seconds) { QString result; diff --git a/libraries/shared/src/SharedUtil.h b/libraries/shared/src/SharedUtil.h index e9201b4a92..042396f474 100644 --- a/libraries/shared/src/SharedUtil.h +++ b/libraries/shared/src/SharedUtil.h @@ -121,7 +121,7 @@ const QByteArray HIGH_FIDELITY_USER_AGENT = "Mozilla/5.0 (HighFidelityInterface) // Equivalent to time_t but in usecs instead of secs 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 // 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 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); bool similarStrings(const QString& stringA, const QString& stringB);