Merge pull request #2545 from ZappoMan/bugfixes

Fixes Voxel Server "stop sending" issue
This commit is contained in:
Stephen Birarda 2014-03-27 09:04:25 -07:00
commit 9dd2573311
9 changed files with 25 additions and 45 deletions

View file

@ -76,9 +76,9 @@ void OctreeQueryNode::deleteLater() {
} }
void OctreeQueryNode::initializeOctreeSendThread(OctreeServer* octreeServer, const QUuid& nodeUUID) { void OctreeQueryNode::initializeOctreeSendThread(OctreeServer* octreeServer, SharedNodePointer node) {
// Create octree sending thread... // Create octree sending thread...
_octreeSendThread = new OctreeSendThread(nodeUUID, octreeServer); _octreeSendThread = new OctreeSendThread(octreeServer, node);
_octreeSendThread->initialize(true); _octreeSendThread->initialize(true);
} }

View file

@ -83,7 +83,7 @@ public:
OctreeSceneStats stats; OctreeSceneStats stats;
void initializeOctreeSendThread(OctreeServer* octreeServer, const QUuid& nodeUUID); void initializeOctreeSendThread(OctreeServer* octreeServer, SharedNodePointer node);
bool isOctreeSendThreadInitalized() { return _octreeSendThread; } bool isOctreeSendThreadInitalized() { return _octreeSendThread; }
void dumpOutOfView(); void dumpOutOfView();

View file

@ -19,11 +19,10 @@
quint64 startSceneSleepTime = 0; quint64 startSceneSleepTime = 0;
quint64 endSceneSleepTime = 0; quint64 endSceneSleepTime = 0;
OctreeSendThread::OctreeSendThread(const QUuid& nodeUUID, OctreeServer* myServer) : OctreeSendThread::OctreeSendThread(OctreeServer* myServer, SharedNodePointer node) :
_nodeUUID(nodeUUID),
_myServer(myServer), _myServer(myServer),
_node(node),
_packetData(), _packetData(),
_nodeMissingCount(0),
_processLock(), _processLock(),
_isShuttingDown(false) _isShuttingDown(false)
{ {
@ -44,7 +43,8 @@ OctreeSendThread::~OctreeSendThread() {
} }
qDebug() << qPrintable(safeServerName) << "server [" << _myServer << "]: client disconnected " qDebug() << qPrintable(safeServerName) << "server [" << _myServer << "]: client disconnected "
"- ending sending thread [" << this << "]"; "- ending sending thread [" << this << "]";
OctreeServer::clientDisconnected(); _node.clear();
OctreeServer::clientDisconnected();
} }
void OctreeSendThread::setIsShuttingDown() { void OctreeSendThread::setIsShuttingDown() {
@ -68,35 +68,18 @@ bool OctreeSendThread::process() {
return false; // exit early if we're shutting down return false; // exit early if we're shutting down
} }
const int MAX_NODE_MISSING_CHECKS = 10;
if (_nodeMissingCount > MAX_NODE_MISSING_CHECKS) {
qDebug() << "our target node:" << _nodeUUID << "has been missing the last" << _nodeMissingCount
<< "times we checked, we are going to stop attempting to send.";
return false; // stop processing and shutdown, our node no longer exists
}
quint64 start = usecTimestampNow(); quint64 start = usecTimestampNow();
// don't do any send processing until the initial load of the octree is complete... // don't do any send processing until the initial load of the octree is complete...
if (_myServer->isInitialLoadComplete()) { if (_myServer->isInitialLoadComplete()) {
if (!_node.isNull()) {
// see if we can get access to our node, but don't wait on the lock, if the nodeList is busy OctreeQueryNode* nodeData = static_cast<OctreeQueryNode*>(_node->getLinkedData());
// it might not return a node that is known, but that's ok we can handle that case.
SharedNodePointer node = NodeList::getInstance()->nodeWithUUID(_nodeUUID, false);
if (node) {
_nodeMissingCount = 0;
OctreeQueryNode* nodeData = NULL;
nodeData = (OctreeQueryNode*) node->getLinkedData();
// Sometimes the node data has not yet been linked, in which case we can't really do anything // Sometimes the node data has not yet been linked, in which case we can't really do anything
if (nodeData && !nodeData->isShuttingDown()) { if (nodeData && !nodeData->isShuttingDown()) {
bool viewFrustumChanged = nodeData->updateCurrentViewFrustum(); bool viewFrustumChanged = nodeData->updateCurrentViewFrustum();
packetDistributor(node, nodeData, viewFrustumChanged); packetDistributor(_node, nodeData, viewFrustumChanged);
} }
} else {
_nodeMissingCount++;
} }
} }

View file

@ -21,7 +21,7 @@
class OctreeSendThread : public GenericThread { class OctreeSendThread : public GenericThread {
Q_OBJECT Q_OBJECT
public: public:
OctreeSendThread(const QUuid& nodeUUID, OctreeServer* myServer); OctreeSendThread(OctreeServer* myServer, SharedNodePointer node);
virtual ~OctreeSendThread(); virtual ~OctreeSendThread();
void setIsShuttingDown(); void setIsShuttingDown();
@ -38,7 +38,7 @@ protected:
virtual bool process(); virtual bool process();
private: private:
QUuid _nodeUUID; SharedNodePointer _node;
OctreeServer* _myServer; OctreeServer* _myServer;
int handlePacketSend(const SharedNodePointer& node, OctreeQueryNode* nodeData, int& trueBytesSent, int& truePacketsSent); int handlePacketSend(const SharedNodePointer& node, OctreeQueryNode* nodeData, int& trueBytesSent, int& truePacketsSent);
@ -46,7 +46,6 @@ private:
OctreePacketData _packetData; OctreePacketData _packetData;
int _nodeMissingCount;
QMutex _processLock; // don't allow us to have our nodeData, or our thread to be deleted while we're processing QMutex _processLock; // don't allow us to have our nodeData, or our thread to be deleted while we're processing
bool _isShuttingDown; bool _isShuttingDown;
}; };

View file

@ -835,7 +835,7 @@ void OctreeServer::readPendingDatagrams() {
if (debug) { if (debug) {
qDebug() << "calling initializeOctreeSendThread()... node:" << *matchingNode; qDebug() << "calling initializeOctreeSendThread()... node:" << *matchingNode;
} }
nodeData->initializeOctreeSendThread(this, matchingNode->getUUID()); nodeData->initializeOctreeSendThread(this, matchingNode);
} }
} }
} else if (packetType == PacketTypeJurisdictionRequest) { } else if (packetType == PacketTypeJurisdictionRequest) {
@ -852,7 +852,9 @@ void OctreeServer::readPendingDatagrams() {
void OctreeServer::run() { void OctreeServer::run() {
_safeServerName = getMyServerName(); _safeServerName = getMyServerName();
// Before we do anything else, create our tree... // Before we do anything else, create our tree...
OctreeElement::resetPopulationStatistics();
_tree = createTree(); _tree = createTree();
// use common init to setup common timers and logging // use common init to setup common timers and logging

View file

@ -29,6 +29,11 @@ quint64 OctreeElement::_externalChildrenMemoryUsage = 0;
quint64 OctreeElement::_voxelNodeCount = 0; quint64 OctreeElement::_voxelNodeCount = 0;
quint64 OctreeElement::_voxelNodeLeafCount = 0; quint64 OctreeElement::_voxelNodeLeafCount = 0;
void OctreeElement::resetPopulationStatistics() {
_voxelNodeCount = 0;
_voxelNodeLeafCount = 0;
}
OctreeElement::OctreeElement() { OctreeElement::OctreeElement() {
// Note: you must call init() from your subclass, otherwise the OctreeElement will not be properly // Note: you must call init() from your subclass, otherwise the OctreeElement will not be properly
// initialized. You will see DEADBEEF in your memory debugger if you have not properly called init() // initialized. You will see DEADBEEF in your memory debugger if you have not properly called init()

View file

@ -152,6 +152,7 @@ public:
static void addUpdateHook(OctreeElementUpdateHook* hook); static void addUpdateHook(OctreeElementUpdateHook* hook);
static void removeUpdateHook(OctreeElementUpdateHook* hook); static void removeUpdateHook(OctreeElementUpdateHook* hook);
static void resetPopulationStatistics();
static unsigned long getNodeCount() { return _voxelNodeCount; } static unsigned long getNodeCount() { return _voxelNodeCount; }
static unsigned long getInternalNodeCount() { return _voxelNodeCount - _voxelNodeLeafCount; } static unsigned long getInternalNodeCount() { return _voxelNodeCount - _voxelNodeLeafCount; }
static unsigned long getLeafNodeCount() { return _voxelNodeLeafCount; } static unsigned long getLeafNodeCount() { return _voxelNodeLeafCount; }

View file

@ -357,18 +357,9 @@ int NodeList::findNodeAndUpdateWithDataFromPacket(const QByteArray& packet) {
return 0; return 0;
} }
SharedNodePointer NodeList::nodeWithUUID(const QUuid& nodeUUID, bool blockingLock) { SharedNodePointer NodeList::nodeWithUUID(const QUuid& nodeUUID) {
SharedNodePointer node; QMutexLocker locker(&_nodeHashMutex);
// if caller wants us to block and guarantee the correct answer, then honor that request return _nodeHash.value(nodeUUID);
if (blockingLock) {
// this will block till we can get access
QMutexLocker locker(&_nodeHashMutex);
node = _nodeHash.value(nodeUUID);
} else if (_nodeHashMutex.tryLock()) { // 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) { SharedNodePointer NodeList::sendingNodeForPacket(const QByteArray& packet) {

View file

@ -103,8 +103,7 @@ public:
QByteArray constructPingReplyPacket(const QByteArray& pingPacket); QByteArray constructPingReplyPacket(const QByteArray& pingPacket);
void pingPublicAndLocalSocketsForInactiveNode(const SharedNodePointer& node); void pingPublicAndLocalSocketsForInactiveNode(const SharedNodePointer& node);
/// passing false for blockingLock, will tryLock, and may return NULL when a node with the UUID actually does exist SharedNodePointer nodeWithUUID(const QUuid& nodeUUID);
SharedNodePointer nodeWithUUID(const QUuid& nodeUUID, bool blockingLock = true);
SharedNodePointer sendingNodeForPacket(const QByteArray& packet); SharedNodePointer sendingNodeForPacket(const QByteArray& packet);
SharedNodePointer addOrUpdateNode(const QUuid& uuid, char nodeType, SharedNodePointer addOrUpdateNode(const QUuid& uuid, char nodeType,