From bda96ef935f00abc36ccbb89e3f0a134be61805c Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 27 Mar 2014 13:35:22 -0700 Subject: [PATCH] added back use of nodeWithUUID() instead of sharedpointer --- .../src/octree/OctreeSendThread.cpp | 25 ++++++++-- .../src/octree/OctreeSendThread.h | 3 +- assignment-client/src/octree/OctreeServer.cpp | 46 +++++++++++++------ assignment-client/src/octree/OctreeServer.h | 4 ++ libraries/shared/src/NodeList.cpp | 18 ++++++-- libraries/shared/src/NodeList.h | 2 +- 6 files changed, 73 insertions(+), 25 deletions(-) diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index 382d8aa528..023f3f3d2c 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -21,8 +21,9 @@ quint64 endSceneSleepTime = 0; OctreeSendThread::OctreeSendThread(OctreeServer* myServer, SharedNodePointer node) : _myServer(myServer), - _node(node), + _nodeUUID(node->getUUID()), _packetData(), + _nodeMissingCount(0), _processLock(), _isShuttingDown(false) { @@ -43,7 +44,6 @@ OctreeSendThread::~OctreeSendThread() { } qDebug() << qPrintable(safeServerName) << "server [" << _myServer << "]: client disconnected " "- ending sending thread [" << this << "]"; - _node.clear(); OctreeServer::clientDisconnected(); } @@ -72,13 +72,28 @@ bool OctreeSendThread::process() { // don't do any send processing until the initial load of the octree is complete... if (_myServer->isInitialLoadComplete()) { - if (!_node.isNull()) { - OctreeQueryNode* nodeData = static_cast(_node->getLinkedData()); + SharedNodePointer node = NodeList::getInstance()->nodeWithUUID(_nodeUUID, false); + if (node) { + _nodeMissingCount = 0; + OctreeQueryNode* nodeData = static_cast(node->getLinkedData()); // Sometimes the node data has not yet been linked, in which case we can't really do anything if (nodeData && !nodeData->isShuttingDown()) { bool viewFrustumChanged = nodeData->updateCurrentViewFrustum(); - packetDistributor(_node, nodeData, viewFrustumChanged); + packetDistributor(node, nodeData, viewFrustumChanged); + } + } else { + _nodeMissingCount++; + const int MANY_FAILED_LOCKS = 1; + if (_nodeMissingCount >= MANY_FAILED_LOCKS) { + + QString safeServerName("Octree"); + if (_myServer) { + safeServerName = _myServer->getMyServerName(); + } + + qDebug() << qPrintable(safeServerName) << "server: sending thread [" << this << "]" + << "failed to get nodeWithUUID() " << _nodeUUID <<". Failed:" << _nodeMissingCount << "times"; } } } diff --git a/assignment-client/src/octree/OctreeSendThread.h b/assignment-client/src/octree/OctreeSendThread.h index 4e18ee9b2a..4b1b6d8c92 100644 --- a/assignment-client/src/octree/OctreeSendThread.h +++ b/assignment-client/src/octree/OctreeSendThread.h @@ -38,14 +38,15 @@ protected: virtual bool process(); private: - SharedNodePointer _node; OctreeServer* _myServer; + QUuid _nodeUUID; int handlePacketSend(const SharedNodePointer& node, OctreeQueryNode* nodeData, int& trueBytesSent, int& truePacketsSent); int packetDistributor(const SharedNodePointer& node, OctreeQueryNode* nodeData, bool viewFrustumChanged); OctreePacketData _packetData; + int _nodeMissingCount; QMutex _processLock; // don't allow us to have our nodeData, or our thread to be deleted while we're processing bool _isShuttingDown; }; diff --git a/assignment-client/src/octree/OctreeServer.cpp b/assignment-client/src/octree/OctreeServer.cpp index fa087cced2..fd3f9e6cb7 100644 --- a/assignment-client/src/octree/OctreeServer.cpp +++ b/assignment-client/src/octree/OctreeServer.cpp @@ -1160,7 +1160,6 @@ QString OctreeServer::getStatusLink() { } void OctreeServer::sendStatsPacket() { - // TODO: we have too many stats to fit in a single MTU... so for now, we break it into multiple JSON objects and // send them separately. What we really should do is change the NodeList::sendStatsToDomainServer() to handle the // the following features: @@ -1241,59 +1240,78 @@ QMap OctreeServer::_threadsDidPacketDistributor; QMap OctreeServer::_threadsDidHandlePacketSend; QMap OctreeServer::_threadsDidCallWriteDatagram; +QMutex OctreeServer::_threadsDidProcessMutex; +QMutex OctreeServer::_threadsDidPacketDistributorMutex; +QMutex OctreeServer::_threadsDidHandlePacketSendMutex; +QMutex OctreeServer::_threadsDidCallWriteDatagramMutex; + void OctreeServer::didProcess(OctreeSendThread* thread) { + QMutexLocker locker(&_threadsDidProcessMutex); _threadsDidProcess[thread] = usecTimestampNow(); } void OctreeServer::didPacketDistributor(OctreeSendThread* thread) { + QMutexLocker locker(&_threadsDidPacketDistributorMutex); _threadsDidPacketDistributor[thread] = usecTimestampNow(); } void OctreeServer::didHandlePacketSend(OctreeSendThread* thread) { + QMutexLocker locker(&_threadsDidHandlePacketSendMutex); _threadsDidHandlePacketSend[thread] = usecTimestampNow(); } void OctreeServer::didCallWriteDatagram(OctreeSendThread* thread) { + QMutexLocker locker(&_threadsDidCallWriteDatagramMutex); _threadsDidCallWriteDatagram[thread] = usecTimestampNow(); } void OctreeServer::stopTrackingThread(OctreeSendThread* thread) { + QMutexLocker lockerA(&_threadsDidProcessMutex); + QMutexLocker lockerB(&_threadsDidPacketDistributorMutex); + QMutexLocker lockerC(&_threadsDidHandlePacketSendMutex); + QMutexLocker lockerD(&_threadsDidCallWriteDatagramMutex); + _threadsDidProcess.remove(thread); _threadsDidPacketDistributor.remove(thread); _threadsDidHandlePacketSend.remove(thread); + _threadsDidCallWriteDatagram.remove(thread); } -int howManyThreadsDidSomething(QMap& something, quint64 since) { - if (since == 0) { - return something.size(); - } +int howManyThreadsDidSomething(QMutex& mutex, QMap& something, quint64 since) { int count = 0; - QMap::const_iterator i = something.constBegin(); - while (i != something.constEnd()) { - if (i.value() > since) { - count++; + if (mutex.tryLock()) { + if (since == 0) { + count = something.size(); + } else { + QMap::const_iterator i = something.constBegin(); + while (i != something.constEnd()) { + if (i.value() > since) { + count++; + } + ++i; + } } - ++i; + mutex.unlock(); } return count; } int OctreeServer::howManyThreadsDidProcess(quint64 since) { - return howManyThreadsDidSomething(_threadsDidProcess, since); + return howManyThreadsDidSomething(_threadsDidProcessMutex, _threadsDidProcess, since); } int OctreeServer::howManyThreadsDidPacketDistributor(quint64 since) { - return howManyThreadsDidSomething(_threadsDidPacketDistributor, since); + return howManyThreadsDidSomething(_threadsDidPacketDistributorMutex, _threadsDidPacketDistributor, since); } int OctreeServer::howManyThreadsDidHandlePacketSend(quint64 since) { - return howManyThreadsDidSomething(_threadsDidHandlePacketSend, since); + return howManyThreadsDidSomething(_threadsDidHandlePacketSendMutex, _threadsDidHandlePacketSend, since); } int OctreeServer::howManyThreadsDidCallWriteDatagram(quint64 since) { - return howManyThreadsDidSomething(_threadsDidCallWriteDatagram, since); + return howManyThreadsDidSomething(_threadsDidCallWriteDatagramMutex, _threadsDidCallWriteDatagram, since); } diff --git a/assignment-client/src/octree/OctreeServer.h b/assignment-client/src/octree/OctreeServer.h index 3dac42709f..63d43b6634 100644 --- a/assignment-client/src/octree/OctreeServer.h +++ b/assignment-client/src/octree/OctreeServer.h @@ -211,6 +211,10 @@ protected: static QMap _threadsDidHandlePacketSend; static QMap _threadsDidCallWriteDatagram; + static QMutex _threadsDidProcessMutex; + static QMutex _threadsDidPacketDistributorMutex; + static QMutex _threadsDidHandlePacketSendMutex; + static QMutex _threadsDidCallWriteDatagramMutex; }; #endif // __octree_server__OctreeServer__ diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index dc5a419295..761ea40d55 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -357,10 +357,20 @@ int NodeList::findNodeAndUpdateWithDataFromPacket(const QByteArray& packet) { return 0; } -SharedNodePointer NodeList::nodeWithUUID(const QUuid& nodeUUID) { - QMutexLocker locker(&_nodeHashMutex); - return _nodeHash.value(nodeUUID); -} +SharedNodePointer NodeList::nodeWithUUID(const QUuid& nodeUUID, bool blockingLock) { + const int WAIT_TIME = 10; // wait up to 10ms in the try lock case + SharedNodePointer node; + // if caller wants us to block and guarantee the correct answer, then honor that request + if (blockingLock) { + // this will block till we can get access + QMutexLocker locker(&_nodeHashMutex); + node = _nodeHash.value(nodeUUID); + } else if (_nodeHashMutex.tryLock(WAIT_TIME)) { // some callers are willing to get wrong answers but not block + node = _nodeHash.value(nodeUUID); + _nodeHashMutex.unlock(); + } + return node; + } SharedNodePointer NodeList::sendingNodeForPacket(const QByteArray& packet) { QUuid nodeUUID = uuidFromPacketHeader(packet); diff --git a/libraries/shared/src/NodeList.h b/libraries/shared/src/NodeList.h index f10e01f3f4..d05d6a2fbc 100644 --- a/libraries/shared/src/NodeList.h +++ b/libraries/shared/src/NodeList.h @@ -103,7 +103,7 @@ public: QByteArray constructPingReplyPacket(const QByteArray& pingPacket); void pingPublicAndLocalSocketsForInactiveNode(const SharedNodePointer& node); - SharedNodePointer nodeWithUUID(const QUuid& nodeUUID); + SharedNodePointer nodeWithUUID(const QUuid& nodeUUID, bool blockingLock = true); SharedNodePointer sendingNodeForPacket(const QByteArray& packet); SharedNodePointer addOrUpdateNode(const QUuid& uuid, char nodeType,