support for larger than 35 minute clock skew

This commit is contained in:
Brad Hefta-Gaub 2016-04-20 18:42:00 -07:00
parent 8631fa6cd3
commit 31f9d592e0
22 changed files with 84 additions and 55 deletions

View file

@ -952,6 +952,25 @@ 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 +1074,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

View file

@ -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) { };

View file

@ -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); quint64 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.

View file

@ -515,7 +515,7 @@ 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 clockSkewInMS = node->getClockSkewUsec() / 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);

View file

@ -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);
} }

View file

@ -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);

View file

@ -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);

View file

@ -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; }

View file

@ -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((double)clockSkewSample);
_clockSkewUsec = (int)_clockSkewMovingPercentile.getValueAtPercentile(); _clockSkewUsec = (quint64)_clockSkewMovingPercentile.getValueAtPercentile();
} }

View file

@ -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;

View file

@ -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);

View file

@ -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

View file

@ -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();

View file

@ -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) {

View file

@ -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
@ -772,8 +772,8 @@ void OctreeSceneStats::trackIncomingOctreePacket(ReceivedMessage& message, bool
} }
// 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 * 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(

View file

@ -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; }

View file

@ -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,8 +276,8 @@ 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 <= -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,8 +290,8 @@ 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 <= 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
} }

View file

@ -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

View file

@ -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(quint64 sample) {
// insert the new sample into _samplesSorted // insert the new sample into _samplesSorted
int newSampleIndex; int newSampleIndex;

View file

@ -18,19 +18,21 @@ class MovingPercentile {
public: public:
MovingPercentile(int numSamples, float percentile = 0.5f); MovingPercentile(int numSamples, float percentile = 0.5f);
void updatePercentile(float sample); // FIXME - this class is only currently used in calculating the clockSkew, which is a signed 64bit int, not a double
float getValueAtPercentile() const { return _valueAtPercentile; } // I am somewhat tempted to make this a type sensitive template and/or swith to using qint64's internally
void updatePercentile(quint64 sample);
quint64 getValueAtPercentile() const { return _valueAtPercentile; }
private: private:
const int _numSamples; const int _numSamples;
const float _percentile; const float _percentile;
QList<float> _samplesSorted; QList<quint64> _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; quint64 _valueAtPercentile;
}; };
#endif #endif

View file

@ -43,8 +43,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;
} }

View file

@ -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