From a376ebbca21f436e030b64fa756bb723d60e39c9 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 5 Dec 2013 10:00:20 -0800 Subject: [PATCH 1/5] make DomainServer a proper QCoreApplication instance, closes #1313 --- domain-server/src/DomainServer.cpp | 513 ++++++++++++++--------------- domain-server/src/DomainServer.h | 14 +- domain-server/src/main.cpp | 3 +- 3 files changed, 258 insertions(+), 272 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index b10006e6cc..5ea1908800 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -19,11 +20,224 @@ #include "DomainServer.h" +const int RESTART_HOLD_TIME_MSECS = 5 * 1000; + DomainServer* DomainServer::domainServerInstance = NULL; -void DomainServer::signalHandler(int signal) { - domainServerInstance->cleanup(); - exit(1); +DomainServer::DomainServer(int argc, char* argv[]) : + QCoreApplication(argc, argv), + _assignmentQueueMutex(), + _assignmentQueue(), + _staticAssignmentFile(QString("%1/config.ds").arg(QCoreApplication::applicationDirPath())), + _staticAssignmentFileData(NULL), + _voxelServerConfig(NULL), + _hasCompletedRestartHold(false) +{ + DomainServer::setDomainServerInstance(this); + + const char CUSTOM_PORT_OPTION[] = "-p"; + const char* customPortString = getCmdOption(argc, (const char**) argv, CUSTOM_PORT_OPTION); + unsigned short domainServerPort = customPortString ? atoi(customPortString) : DEFAULT_DOMAIN_SERVER_PORT; + + NodeList* nodeList = NodeList::createInstance(NODE_TYPE_DOMAIN, domainServerPort); + + const char VOXEL_CONFIG_OPTION[] = "--voxelServerConfig"; + _voxelServerConfig = getCmdOption(argc, (const char**) argv, VOXEL_CONFIG_OPTION); + + // setup the mongoose web server + struct mg_callbacks callbacks = {}; + + QString documentRootString = QString("%1/resources/web").arg(QCoreApplication::applicationDirPath()); + + char documentRoot[documentRootString.size() + 1]; + strcpy(documentRoot, documentRootString.toLocal8Bit().constData()); + + // list of options. Last element must be NULL. + const char* options[] = {"listening_ports", "8080", + "document_root", documentRoot, NULL}; + + callbacks.begin_request = civetwebRequestHandler; + callbacks.upload = civetwebUploadHandler; + + // Start the web server. + mg_start(&callbacks, NULL, options); + + nodeList->addHook(this); + + if (!_staticAssignmentFile.exists() || _voxelServerConfig) { + + if (_voxelServerConfig) { + // we have a new VS config, clear the existing file to start fresh + _staticAssignmentFile.remove(); + } + + prepopulateStaticAssignmentFile(); + } + + _staticAssignmentFile.open(QIODevice::ReadWrite); + + _staticAssignmentFileData = _staticAssignmentFile.map(0, _staticAssignmentFile.size()); + + _staticAssignments = (Assignment*) _staticAssignmentFileData; + + QTimer* silentNodeTimer = new QTimer(this); + connect(silentNodeTimer, SIGNAL(timeout()), nodeList, SLOT(removeSilentNodes())); + silentNodeTimer->start(NODE_SILENCE_THRESHOLD_USECS / 1000); + + connect(&nodeList->getNodeSocket(), SIGNAL(readyRead()), SLOT(readAvailableDatagrams())); + + // fire a single shot timer to add static assignments back into the queue after a restart + QTimer::singleShot(RESTART_HOLD_TIME_MSECS, this, SLOT(addStaticAssignmentsBackToQueueAfterRestart())); +} + +void DomainServer::exit(int retCode) { + cleanup(); +} + +void DomainServer::readAvailableDatagrams() { + NodeList* nodeList = NodeList::getInstance(); + + HifiSockAddr senderSockAddr, nodePublicAddress, nodeLocalAddress; + + static unsigned char packetData[MAX_PACKET_SIZE]; + + static unsigned char broadcastPacket[MAX_PACKET_SIZE]; + + static unsigned char* currentBufferPos; + static unsigned char* startPointer; + + int receivedBytes = 0; + + while (nodeList->getNodeSocket().hasPendingDatagrams()) { + if ((receivedBytes = nodeList->getNodeSocket().readDatagram((char*) packetData, MAX_PACKET_SIZE, + senderSockAddr.getAddressPointer(), + senderSockAddr.getPortPointer())) + && packetVersionMatch((unsigned char*) packetData)) { + if (packetData[0] == PACKET_TYPE_DOMAIN_REPORT_FOR_DUTY || packetData[0] == PACKET_TYPE_DOMAIN_LIST_REQUEST) { + // this is an RFD or domain list request packet, and there is a version match + + int numBytesSenderHeader = numBytesForPacketHeader((unsigned char*) packetData); + + NODE_TYPE nodeType = *(packetData + numBytesSenderHeader); + + int packetIndex = numBytesSenderHeader + sizeof(NODE_TYPE); + QUuid nodeUUID = QUuid::fromRfc4122(QByteArray(((char*) packetData + packetIndex), NUM_BYTES_RFC4122_UUID)); + packetIndex += NUM_BYTES_RFC4122_UUID; + + int numBytesPrivateSocket = HifiSockAddr::unpackSockAddr(packetData + packetIndex, nodePublicAddress); + packetIndex += numBytesPrivateSocket; + + if (nodePublicAddress.getAddress().isNull()) { + // this node wants to use us its STUN server + // so set the node public address to whatever we perceive the public address to be + + // if the sender is on our box then leave its public address to 0 so that + // other users attempt to reach it on the same address they have for the domain-server + if (senderSockAddr.getAddress().isLoopback()) { + nodePublicAddress.setAddress(QHostAddress()); + } else { + nodePublicAddress.setAddress(senderSockAddr.getAddress()); + } + } + + int numBytesPublicSocket = HifiSockAddr::unpackSockAddr(packetData + packetIndex, nodeLocalAddress); + packetIndex += numBytesPublicSocket; + + const char STATICALLY_ASSIGNED_NODES[3] = { + NODE_TYPE_AUDIO_MIXER, + NODE_TYPE_AVATAR_MIXER, + NODE_TYPE_VOXEL_SERVER + }; + + Assignment* matchingStaticAssignment = NULL; + + if (memchr(STATICALLY_ASSIGNED_NODES, nodeType, sizeof(STATICALLY_ASSIGNED_NODES)) == NULL + || ((matchingStaticAssignment = matchingStaticAssignmentForCheckIn(nodeUUID, nodeType)) + || checkInWithUUIDMatchesExistingNode(nodePublicAddress, + nodeLocalAddress, + nodeUUID))) + { + Node* checkInNode = nodeList->addOrUpdateNode(nodeUUID, + nodeType, + nodePublicAddress, + nodeLocalAddress); + + if (matchingStaticAssignment) { + // this was a newly added node with a matching static assignment + + if (_hasCompletedRestartHold) { + // remove the matching assignment from the assignment queue so we don't take the next check in + removeAssignmentFromQueue(matchingStaticAssignment); + } + + // set the linked data for this node to a copy of the matching assignment + // so we can re-queue it should the node die + Assignment* nodeCopyOfMatchingAssignment = new Assignment(*matchingStaticAssignment); + + checkInNode->setLinkedData(nodeCopyOfMatchingAssignment); + } + + int numHeaderBytes = populateTypeAndVersion(broadcastPacket, PACKET_TYPE_DOMAIN); + + currentBufferPos = broadcastPacket + numHeaderBytes; + startPointer = currentBufferPos; + + unsigned char* nodeTypesOfInterest = packetData + packetIndex + sizeof(unsigned char); + int numInterestTypes = *(nodeTypesOfInterest - 1); + + if (numInterestTypes > 0) { + // if the node has sent no types of interest, assume they want nothing but their own ID back + for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { + if (node->getUUID() != nodeUUID && + memchr(nodeTypesOfInterest, node->getType(), numInterestTypes)) { + + // don't send avatar nodes to other avatars, that will come from avatar mixer + if (nodeType != NODE_TYPE_AGENT || node->getType() != NODE_TYPE_AGENT) { + currentBufferPos = addNodeToBroadcastPacket(currentBufferPos, &(*node)); + } + + } + } + } + + // update last receive to now + uint64_t timeNow = usecTimestampNow(); + checkInNode->setLastHeardMicrostamp(timeNow); + + // send the constructed list back to this node + nodeList->getNodeSocket().writeDatagram((char*) broadcastPacket, + (currentBufferPos - startPointer) + numHeaderBytes, + senderSockAddr.getAddress(), senderSockAddr.getPort()); + } + } else if (packetData[0] == PACKET_TYPE_REQUEST_ASSIGNMENT) { + + qDebug("Received a request for assignment.\n"); + + if (_assignmentQueue.size() > 0) { + // construct the requested assignment from the packet data + Assignment requestAssignment(packetData, receivedBytes); + + Assignment* assignmentToDeploy = deployableAssignmentForRequest(requestAssignment); + + if (assignmentToDeploy) { + + // give this assignment out, either the type matches or the requestor said they will take any + int numHeaderBytes = populateTypeAndVersion(broadcastPacket, PACKET_TYPE_CREATE_ASSIGNMENT); + int numAssignmentBytes = assignmentToDeploy->packToBuffer(broadcastPacket + numHeaderBytes); + + nodeList->getNodeSocket().writeDatagram((char*) broadcastPacket, numHeaderBytes + numAssignmentBytes, + senderSockAddr.getAddress(), senderSockAddr.getPort()); + + if (assignmentToDeploy->getNumberOfInstances() == 0) { + // there are no more instances of this script to send out, delete it + delete assignmentToDeploy; + } + } + + } + } + } + } } void DomainServer::setDomainServerInstance(DomainServer* domainServer) { @@ -292,52 +506,6 @@ unsigned char* DomainServer::addNodeToBroadcastPacket(unsigned char* currentPosi return currentPosition; } -DomainServer::DomainServer(int argc, char* argv[]) : - _assignmentQueueMutex(), - _assignmentQueue(), - _staticAssignmentFile(QString("%1/config.ds").arg(QCoreApplication::applicationDirPath())), - _staticAssignmentFileData(NULL), - _voxelServerConfig(NULL), - _hasCompletedRestartHold(false) -{ - DomainServer::setDomainServerInstance(this); - - const char CUSTOM_PORT_OPTION[] = "-p"; - const char* customPortString = getCmdOption(argc, (const char**) argv, CUSTOM_PORT_OPTION); - unsigned short domainServerPort = customPortString ? atoi(customPortString) : DEFAULT_DOMAIN_SERVER_PORT; - - NodeList::createInstance(NODE_TYPE_DOMAIN, domainServerPort); - - struct sigaction sigIntHandler; - - sigIntHandler.sa_handler = DomainServer::signalHandler; - sigemptyset(&sigIntHandler.sa_mask); - sigIntHandler.sa_flags = 0; - - sigaction(SIGINT, &sigIntHandler, NULL); - - const char VOXEL_CONFIG_OPTION[] = "--voxelServerConfig"; - _voxelServerConfig = getCmdOption(argc, (const char**) argv, VOXEL_CONFIG_OPTION); - - // setup the mongoose web server - struct mg_callbacks callbacks = {}; - - QString documentRootString = QString("%1/resources/web").arg(QCoreApplication::applicationDirPath()); - - char documentRoot[documentRootString.size() + 1]; - strcpy(documentRoot, documentRootString.toLocal8Bit().constData()); - - // list of options. Last element must be NULL. - const char* options[] = {"listening_ports", "8080", - "document_root", documentRoot, NULL}; - - callbacks.begin_request = civetwebRequestHandler; - callbacks.upload = civetwebUploadHandler; - - // Start the web server. - mg_start(&callbacks, NULL, options); -} - void DomainServer::prepopulateStaticAssignmentFile() { int numFreshStaticAssignments = 0; @@ -521,234 +689,51 @@ bool DomainServer::checkInWithUUIDMatchesExistingNode(const HifiSockAddr& nodePu return false; } -void DomainServer::possiblyAddStaticAssignmentsBackToQueueAfterRestart(timeval* startTime) { +void DomainServer::addStaticAssignmentsBackToQueueAfterRestart() { + _hasCompletedRestartHold = true; + // if the domain-server has just restarted, // check if there are static assignments in the file that we need to // throw into the assignment queue - const uint64_t RESTART_HOLD_TIME_USECS = 5 * 1000 * 1000; - if (!_hasCompletedRestartHold && usecTimestampNow() - usecTimestamp(startTime) > RESTART_HOLD_TIME_USECS) { - _hasCompletedRestartHold = true; + // pull anything in the static assignment file that isn't spoken for and add to the assignment queue + for (int i = 0; i < MAX_STATIC_ASSIGNMENT_FILE_ASSIGNMENTS; i++) { + if (_staticAssignments[i].getUUID().isNull()) { + // reached the end of static assignments, bail + break; + } - // pull anything in the static assignment file that isn't spoken for and add to the assignment queue - for (int i = 0; i < MAX_STATIC_ASSIGNMENT_FILE_ASSIGNMENTS; i++) { - if (_staticAssignments[i].getUUID().isNull()) { - // reached the end of static assignments, bail - break; - } - - bool foundMatchingAssignment = false; - - NodeList* nodeList = NodeList::getInstance(); - - // enumerate the nodes and check if there is one with an attached assignment with matching UUID - for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { - if (node->getLinkedData()) { - Assignment* linkedAssignment = (Assignment*) node->getLinkedData(); - if (linkedAssignment->getUUID() == _staticAssignments[i].getUUID()) { - foundMatchingAssignment = true; - break; - } + bool foundMatchingAssignment = false; + + NodeList* nodeList = NodeList::getInstance(); + + // enumerate the nodes and check if there is one with an attached assignment with matching UUID + for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { + if (node->getLinkedData()) { + Assignment* linkedAssignment = (Assignment*) node->getLinkedData(); + if (linkedAssignment->getUUID() == _staticAssignments[i].getUUID()) { + foundMatchingAssignment = true; + break; } } + } + + if (!foundMatchingAssignment) { + // this assignment has not been fulfilled - reset the UUID and add it to the assignment queue + _staticAssignments[i].resetUUID(); - if (!foundMatchingAssignment) { - // this assignment has not been fulfilled - reset the UUID and add it to the assignment queue - _staticAssignments[i].resetUUID(); - - qDebug() << "Adding static assignment to queue -" << _staticAssignments[i] << "\n"; - - _assignmentQueueMutex.lock(); - _assignmentQueue.push_back(&_staticAssignments[i]); - _assignmentQueueMutex.unlock(); - } + qDebug() << "Adding static assignment to queue -" << _staticAssignments[i] << "\n"; + + _assignmentQueueMutex.lock(); + _assignmentQueue.push_back(&_staticAssignments[i]); + _assignmentQueueMutex.unlock(); } } } void DomainServer::cleanup() { + qDebug() << "cleanup called!\n"; + _staticAssignmentFile.unmap(_staticAssignmentFileData); _staticAssignmentFile.close(); -} - -int DomainServer::run() { - NodeList* nodeList = NodeList::getInstance(); - - nodeList->addHook(this); - - ssize_t receivedBytes = 0; - char nodeType = '\0'; - - unsigned char broadcastPacket[MAX_PACKET_SIZE]; - unsigned char packetData[MAX_PACKET_SIZE]; - - unsigned char* currentBufferPos; - unsigned char* startPointer; - - QHostAddress senderAddress; - quint16 senderPort; - HifiSockAddr nodePublicAddress, nodeLocalAddress; - - nodeList->startSilentNodeRemovalThread(); - - if (!_staticAssignmentFile.exists() || _voxelServerConfig) { - - if (_voxelServerConfig) { - // we have a new VS config, clear the existing file to start fresh - _staticAssignmentFile.remove(); - } - - prepopulateStaticAssignmentFile(); - } - - _staticAssignmentFile.open(QIODevice::ReadWrite); - - _staticAssignmentFileData = _staticAssignmentFile.map(0, _staticAssignmentFile.size()); - - _staticAssignments = (Assignment*) _staticAssignmentFileData; - - timeval startTime; - gettimeofday(&startTime, NULL); - - while (true) { - while (nodeList->getNodeSocket().hasPendingDatagrams() - && nodeList->getNodeSocket().readDatagram((char*) packetData, MAX_PACKET_SIZE, &senderAddress, &senderPort) && - packetVersionMatch(packetData)) { - if (packetData[0] == PACKET_TYPE_DOMAIN_REPORT_FOR_DUTY || packetData[0] == PACKET_TYPE_DOMAIN_LIST_REQUEST) { - // this is an RFD or domain list request packet, and there is a version match - - int numBytesSenderHeader = numBytesForPacketHeader(packetData); - - nodeType = *(packetData + numBytesSenderHeader); - - int packetIndex = numBytesSenderHeader + sizeof(NODE_TYPE); - QUuid nodeUUID = QUuid::fromRfc4122(QByteArray(((char*) packetData + packetIndex), NUM_BYTES_RFC4122_UUID)); - packetIndex += NUM_BYTES_RFC4122_UUID; - - int numBytesPrivateSocket = HifiSockAddr::unpackSockAddr(packetData + packetIndex, nodePublicAddress); - packetIndex += numBytesPrivateSocket; - - if (nodePublicAddress.getAddress().isNull()) { - // this node wants to use us its STUN server - // so set the node public address to whatever we perceive the public address to be - - // if the sender is on our box then leave its public address to 0 so that - // other users attempt to reach it on the same address they have for the domain-server - if (senderAddress.isLoopback()) { - nodePublicAddress.setAddress(QHostAddress()); - } else { - nodePublicAddress.setAddress(senderAddress); - } - } - - int numBytesPublicSocket = HifiSockAddr::unpackSockAddr(packetData + packetIndex, nodeLocalAddress); - packetIndex += numBytesPublicSocket; - - const char STATICALLY_ASSIGNED_NODES[3] = { - NODE_TYPE_AUDIO_MIXER, - NODE_TYPE_AVATAR_MIXER, - NODE_TYPE_VOXEL_SERVER - }; - - Assignment* matchingStaticAssignment = NULL; - - if (memchr(STATICALLY_ASSIGNED_NODES, nodeType, sizeof(STATICALLY_ASSIGNED_NODES)) == NULL - || ((matchingStaticAssignment = matchingStaticAssignmentForCheckIn(nodeUUID, nodeType)) - || checkInWithUUIDMatchesExistingNode(nodePublicAddress, - nodeLocalAddress, - nodeUUID))) - { - Node* checkInNode = nodeList->addOrUpdateNode(nodeUUID, - nodeType, - nodePublicAddress, - nodeLocalAddress); - - if (matchingStaticAssignment) { - // this was a newly added node with a matching static assignment - - if (_hasCompletedRestartHold) { - // remove the matching assignment from the assignment queue so we don't take the next check in - removeAssignmentFromQueue(matchingStaticAssignment); - } - - // set the linked data for this node to a copy of the matching assignment - // so we can re-queue it should the node die - Assignment* nodeCopyOfMatchingAssignment = new Assignment(*matchingStaticAssignment); - - checkInNode->setLinkedData(nodeCopyOfMatchingAssignment); - } - - int numHeaderBytes = populateTypeAndVersion(broadcastPacket, PACKET_TYPE_DOMAIN); - - currentBufferPos = broadcastPacket + numHeaderBytes; - startPointer = currentBufferPos; - - unsigned char* nodeTypesOfInterest = packetData + packetIndex + sizeof(unsigned char); - int numInterestTypes = *(nodeTypesOfInterest - 1); - - if (numInterestTypes > 0) { - // if the node has sent no types of interest, assume they want nothing but their own ID back - for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { - if (node->getUUID() != nodeUUID && - memchr(nodeTypesOfInterest, node->getType(), numInterestTypes)) { - - // don't send avatar nodes to other avatars, that will come from avatar mixer - if (nodeType != NODE_TYPE_AGENT || node->getType() != NODE_TYPE_AGENT) { - currentBufferPos = addNodeToBroadcastPacket(currentBufferPos, &(*node)); - } - - } - } - } - - // update last receive to now - uint64_t timeNow = usecTimestampNow(); - checkInNode->setLastHeardMicrostamp(timeNow); - - // send the constructed list back to this node - nodeList->getNodeSocket().writeDatagram((char*) broadcastPacket, - (currentBufferPos - startPointer) + numHeaderBytes, - senderAddress, senderPort); - } - } else if (packetData[0] == PACKET_TYPE_REQUEST_ASSIGNMENT) { - - qDebug("Received a request for assignment.\n"); - - if (!_hasCompletedRestartHold) { - possiblyAddStaticAssignmentsBackToQueueAfterRestart(&startTime); - } - - if (_assignmentQueue.size() > 0) { - // construct the requested assignment from the packet data - Assignment requestAssignment(packetData, receivedBytes); - - Assignment* assignmentToDeploy = deployableAssignmentForRequest(requestAssignment); - - if (assignmentToDeploy) { - - // give this assignment out, either the type matches or the requestor said they will take any - int numHeaderBytes = populateTypeAndVersion(broadcastPacket, PACKET_TYPE_CREATE_ASSIGNMENT); - int numAssignmentBytes = assignmentToDeploy->packToBuffer(broadcastPacket + numHeaderBytes); - - nodeList->getNodeSocket().writeDatagram((char*) broadcastPacket, numHeaderBytes + numAssignmentBytes, - senderAddress, senderPort); - - if (assignmentToDeploy->getNumberOfInstances() == 0) { - // there are no more instances of this script to send out, delete it - delete assignmentToDeploy; - } - } - - } - } - } - - if (!_hasCompletedRestartHold) { - possiblyAddStaticAssignmentsBackToQueueAfterRestart(&startTime); - } - } - - this->cleanup(); - - return 0; } \ No newline at end of file diff --git a/domain-server/src/DomainServer.h b/domain-server/src/DomainServer.h index 755f73485c..a6ff71673f 100644 --- a/domain-server/src/DomainServer.h +++ b/domain-server/src/DomainServer.h @@ -22,20 +22,20 @@ const int MAX_STATIC_ASSIGNMENT_FILE_ASSIGNMENTS = 1000; -class DomainServer : public NodeListHook { +class DomainServer : public QCoreApplication, public NodeListHook { + Q_OBJECT public: DomainServer(int argc, char* argv[]); - int run(); - - static void signalHandler(int signal); + void exit(int retCode = 0); + static void setDomainServerInstance(DomainServer* domainServer); /// Called by NodeList to inform us that a node has been added. void nodeAdded(Node* node); /// Called by NodeList to inform us that a node has been killed. void nodeKilled(Node* node); -private: +private: static int civetwebRequestHandler(struct mg_connection *connection); static void civetwebUploadHandler(struct mg_connection *connection, const char *path); @@ -48,7 +48,6 @@ private: bool checkInWithUUIDMatchesExistingNode(const HifiSockAddr& nodePublicSocket, const HifiSockAddr& nodeLocalSocket, const QUuid& checkInUUI); - void possiblyAddStaticAssignmentsBackToQueueAfterRestart(timeval* startTime); void addReleasedAssignmentBackToQueue(Assignment* releasedAssignment); void cleanup(); @@ -66,6 +65,9 @@ private: const char* _voxelServerConfig; bool _hasCompletedRestartHold; +private slots: + void readAvailableDatagrams(); + void addStaticAssignmentsBackToQueueAfterRestart(); }; #endif /* defined(__hifi__DomainServer__) */ diff --git a/domain-server/src/main.cpp b/domain-server/src/main.cpp index 87d1cce061..1d9f554237 100644 --- a/domain-server/src/main.cpp +++ b/domain-server/src/main.cpp @@ -24,9 +24,8 @@ int main(int argc, char* argv[]) { qInstallMessageHandler(Logging::verboseMessageHandler); - QCoreApplication application(argc, argv); DomainServer domainServer(argc, argv); - return domainServer.run(); + return domainServer.exec(); } From 7613f3d00c13fd54b5b0cbc05a57ca6b595c81e3 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 5 Dec 2013 10:08:41 -0800 Subject: [PATCH 2/5] fix VoxelServer to be correctly event-driven, closes #1314 --- .../voxel-server-library/src/VoxelServer.cpp | 57 ++++++++----------- .../voxel-server-library/src/VoxelServer.h | 1 + 2 files changed, 24 insertions(+), 34 deletions(-) diff --git a/libraries/voxel-server-library/src/VoxelServer.cpp b/libraries/voxel-server-library/src/VoxelServer.cpp index 96323f7d1a..b53f44ee88 100644 --- a/libraries/voxel-server-library/src/VoxelServer.cpp +++ b/libraries/voxel-server-library/src/VoxelServer.cpp @@ -91,6 +91,29 @@ VoxelServer::~VoxelServer() { } delete[] _parsedArgV; } + + if (_jurisdictionSender) { + _jurisdictionSender->terminate(); + delete _jurisdictionSender; + } + + if (_voxelServerPacketProcessor) { + _voxelServerPacketProcessor->terminate(); + delete _voxelServerPacketProcessor; + } + + if (_voxelPersistThread) { + _voxelPersistThread->terminate(); + delete _voxelPersistThread; + } + + // tell our NodeList we're done with notifications + NodeList::getInstance()->removeHook(&_nodeWatcher); + + delete _jurisdiction; + _jurisdiction = NULL; + + qDebug() << "VoxelServer::run()... DONE\n"; } void VoxelServer::initMongoose(int port) { @@ -751,38 +774,4 @@ void VoxelServer::run() { QTimer* pingNodesTimer = new QTimer(this); connect(pingNodesTimer, SIGNAL(timeout()), nodeList, SLOT(pingInactiveNodes())); pingNodesTimer->start(PING_INACTIVE_NODE_INTERVAL_USECS / 1000); - - // loop to send to nodes requesting data - while (!_isFinished) { - QCoreApplication::processEvents(); - } - - // call NodeList::clear() so that all of our node specific objects, including our sending threads, are - // properly shutdown and cleaned up. - NodeList::getInstance()->clear(); - - if (_jurisdictionSender) { - _jurisdictionSender->terminate(); - delete _jurisdictionSender; - } - - if (_voxelServerPacketProcessor) { - _voxelServerPacketProcessor->terminate(); - delete _voxelServerPacketProcessor; - } - - if (_voxelPersistThread) { - _voxelPersistThread->terminate(); - delete _voxelPersistThread; - } - - // tell our NodeList we're done with notifications - nodeList->removeHook(&_nodeWatcher); - - delete _jurisdiction; - _jurisdiction = NULL; - - qDebug() << "VoxelServer::run()... DONE\n"; } - - diff --git a/libraries/voxel-server-library/src/VoxelServer.h b/libraries/voxel-server-library/src/VoxelServer.h index f4923778c1..2c3b7188c6 100644 --- a/libraries/voxel-server-library/src/VoxelServer.h +++ b/libraries/voxel-server-library/src/VoxelServer.h @@ -27,6 +27,7 @@ /// Handles assignments of type VoxelServer - sending voxels to various clients. class VoxelServer : public ThreadedAssignment { + Q_OBJECT public: VoxelServer(const unsigned char* dataBuffer, int numBytes); From aac01ee70da791d55c3b482f4e0ebc557c92793b Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 5 Dec 2013 11:42:34 -0800 Subject: [PATCH 3/5] rename in OctreeServer destructor debug --- libraries/octree-server/src/OctreeServer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/octree-server/src/OctreeServer.cpp b/libraries/octree-server/src/OctreeServer.cpp index f7dd2ce680..f9128e812b 100644 --- a/libraries/octree-server/src/OctreeServer.cpp +++ b/libraries/octree-server/src/OctreeServer.cpp @@ -97,7 +97,7 @@ OctreeServer::~OctreeServer() { delete _jurisdiction; _jurisdiction = NULL; - qDebug() << "VoxelServer::run()... DONE\n"; + qDebug() << "OctreeServer::run()... DONE\n"; } void OctreeServer::initMongoose(int port) { From 5b6c2531a468a07450c15d7c47bb5d8877e89df5 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 5 Dec 2013 11:43:48 -0800 Subject: [PATCH 4/5] use correct cleanup calls in OctreeServer destructor --- libraries/octree-server/src/OctreeServer.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/libraries/octree-server/src/OctreeServer.cpp b/libraries/octree-server/src/OctreeServer.cpp index f9128e812b..a18e8c1af4 100644 --- a/libraries/octree-server/src/OctreeServer.cpp +++ b/libraries/octree-server/src/OctreeServer.cpp @@ -81,18 +81,18 @@ OctreeServer::~OctreeServer() { delete _jurisdictionSender; } - if (_voxelServerPacketProcessor) { - _voxelServerPacketProcessor->terminate(); - delete _voxelServerPacketProcessor; + if (_octreeInboundPacketProcessor) { + _octreeInboundPacketProcessor->terminate(); + delete _octreeInboundPacketProcessor; } - if (_voxelPersistThread) { - _voxelPersistThread->terminate(); - delete _voxelPersistThread; + if (_persistThread) { + _persistThread->terminate(); + delete _persistThread; } // tell our NodeList we're done with notifications - NodeList::getInstance()->removeHook(&_nodeWatcher); + nodeList->removeHook(this); delete _jurisdiction; _jurisdiction = NULL; From baae2a3e41f340c450c4b8e5e9951a0d4bd50d2c Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 5 Dec 2013 11:44:11 -0800 Subject: [PATCH 5/5] fix reference to NodeList in OctreeServer destructor --- libraries/octree-server/src/OctreeServer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/octree-server/src/OctreeServer.cpp b/libraries/octree-server/src/OctreeServer.cpp index a18e8c1af4..82d5fa4035 100644 --- a/libraries/octree-server/src/OctreeServer.cpp +++ b/libraries/octree-server/src/OctreeServer.cpp @@ -92,7 +92,7 @@ OctreeServer::~OctreeServer() { } // tell our NodeList we're done with notifications - nodeList->removeHook(this); + NodeList::getInstance()->removeHook(this); delete _jurisdiction; _jurisdiction = NULL;