diff --git a/CMakeLists.txt b/CMakeLists.txt index a8271abd8e..13d5b2bc79 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.8.12.2) +cmake_minimum_required(VERSION 3.2) if (USE_ANDROID_TOOLCHAIN) set(CMAKE_TOOLCHAIN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/cmake/android/android.toolchain.cmake") @@ -67,9 +67,9 @@ if ((NOT MSVC12) AND (NOT MSVC14)) CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X) if (COMPILER_SUPPORTS_CXX11) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") elseif(COMPILER_SUPPORTS_CXX0X) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") else() message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.") endif() @@ -228,34 +228,4 @@ if (HIFI_MEMORY_DEBUGGING) endif () include_application_version() - -if (DEFINED DEPLOY_PACKAGE AND DEPLOY_PACKAGE) - message(STATUS "+++++ Package for deployment will be generated on this build +++++") - - file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/full-stack-deployment) - - set(ICONPATH_INTERFACE "$INSTDIR/${PATH_INSTALL_DATA}/interface.ico") - set(ICONPATH_STACK_MANAGER "$INSTDIR/${PATH_INSTALL_DATA}/stack-manager.ico") - string(REPLACE "/" "\\\\" ICONPATH_INTERFACE ${ICONPATH_INTERFACE}) - string(REPLACE "/" "\\\\" ICONPATH_STACK_MANAGER ${ICONPATH_STACK_MANAGER}) - - set(CPACK_PACKAGE_NAME "High Fidelity") - set(CPACK_PACKAGE_VENDOR "High Fidelity, Inc") - set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "High Fidelity Interface and Stack") - set(CPACK_PACKAGE_VERSION "${BUILD_SEQ}") - set(CPACK_PACKAGE_VERSION_MAJOR "${BUILD_SEQ}") - set(CPACK_PACKAGE_VERSION_MINOR "0") - set(CPACK_PACKAGE_VERSION_PATCH "0") - set(CPACK_PACKAGE_INSTALL_DIRECTORY "High Fidelity-${BUILD_SEQ}") - set(CPACK_NSIS_EXECUTABLES_DIRECTORY ".") - set(CPACK_PACKAGE_EXECUTABLES - stack-manager "Stack Manager" - interface "Interface" - ) - - if (WIN32) - install(DIRECTORY ${CMAKE_BINARY_DIR}/full-stack-deployment/ DESTINATION "./") - endif (WIN32) - - include(CPack) -endif () +generate_installers() \ No newline at end of file diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index fc0cfe1abb..bbee597797 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -35,6 +35,7 @@ #include "AssignmentActionFactory.h" #include "AssignmentClient.h" +#include "AssignmentClientLogging.h" #include "avatars/ScriptableAvatar.h" const QString ASSIGNMENT_CLIENT_TARGET_NAME = "assignment-client"; @@ -84,7 +85,7 @@ AssignmentClient::AssignmentClient(Assignment::Type requestAssignmentType, QStri // check for a wallet UUID on the command line or in the config // this would represent where the user running AC wants funds sent to if (!walletUUID.isNull()) { - qDebug() << "The destination wallet UUID for credits is" << uuidStringWithoutCurlyBraces(walletUUID); + qCDebug(assigmnentclient) << "The destination wallet UUID for credits is" << uuidStringWithoutCurlyBraces(walletUUID); _requestAssignment.setWalletUUID(walletUUID); } @@ -98,13 +99,13 @@ AssignmentClient::AssignmentClient(Assignment::Type requestAssignmentType, QStri _assignmentServerSocket.setObjectName("AssigmentServer"); nodeList->setAssignmentServerSocket(_assignmentServerSocket); - qDebug() << "Assignment server socket is" << _assignmentServerSocket; + qCDebug(assigmnentclient) << "Assignment server socket is" << _assignmentServerSocket; // call a timer function every ASSIGNMENT_REQUEST_INTERVAL_MSECS to ask for assignment, if required - qDebug() << "Waiting for assignment -" << _requestAssignment; + qCDebug(assigmnentclient) << "Waiting for assignment -" << _requestAssignment; if (_assignmentServerHostname != "localhost") { - qDebug () << "- will attempt to connect to domain-server on" << _assignmentServerSocket.getPort(); + qCDebug(assigmnentclient) << "- will attempt to connect to domain-server on" << _assignmentServerSocket.getPort(); } connect(&_requestTimer, SIGNAL(timeout()), SLOT(sendAssignmentRequest())); @@ -122,7 +123,7 @@ AssignmentClient::AssignmentClient(Assignment::Type requestAssignmentType, QStri _assignmentClientMonitorSocket = HifiSockAddr(DEFAULT_ASSIGNMENT_CLIENT_MONITOR_HOSTNAME, assignmentMonitorPort); _assignmentClientMonitorSocket.setObjectName("AssignmentClientMonitor"); - qDebug() << "Assignment-client monitor socket is" << _assignmentClientMonitorSocket; + qCDebug(assigmnentclient) << "Assignment-client monitor socket is" << _assignmentClientMonitorSocket; // Hook up a timer to send this child's status to the Monitor once per second setUpStatusToMonitor(); @@ -133,7 +134,7 @@ AssignmentClient::AssignmentClient(Assignment::Type requestAssignmentType, QStri } void AssignmentClient::stopAssignmentClient() { - qDebug() << "Forced stop of assignment-client."; + qCDebug(assigmnentclient) << "Forced stop of assignment-client."; _requestTimer.stop(); _statsTimerACM.stop(); @@ -209,14 +210,14 @@ void AssignmentClient::sendAssignmentRequest() { quint16 localAssignmentServerPort; if (nodeList->getLocalServerPortFromSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, localAssignmentServerPort)) { if (localAssignmentServerPort != _assignmentServerSocket.getPort()) { - qDebug() << "Port for local assignment server read from shared memory is" + qCDebug(assigmnentclient) << "Port for local assignment server read from shared memory is" << localAssignmentServerPort; _assignmentServerSocket.setPort(localAssignmentServerPort); nodeList->setAssignmentServerSocket(_assignmentServerSocket); } } else { - qDebug() << "Failed to read local assignment server port from shared memory" + qCWarning(assigmnentclient) << "Failed to read local assignment server port from shared memory" << "- will send assignment request to previous assignment server socket."; } } @@ -226,13 +227,13 @@ void AssignmentClient::sendAssignmentRequest() { } void AssignmentClient::handleCreateAssignmentPacket(QSharedPointer message) { - qDebug() << "Received a PacketType::CreateAssignment - attempting to unpack."; + qCDebug(assigmnentclient) << "Received a PacketType::CreateAssignment - attempting to unpack."; // construct the deployed assignment from the packet data _currentAssignment = AssignmentFactory::unpackAssignment(*message); if (_currentAssignment && !_isAssigned) { - qDebug() << "Received an assignment -" << *_currentAssignment; + qDebug(assigmnentclient) << "Received an assignment -" << *_currentAssignment; _isAssigned = true; auto nodeList = DependencyManager::get(); @@ -242,7 +243,7 @@ void AssignmentClient::handleCreateAssignmentPacket(QSharedPointergetDomainHandler().setSockAddr(message->getSenderSockAddr(), _assignmentServerHostname); nodeList->getDomainHandler().setAssignmentUUID(_currentAssignment->getUUID()); - qDebug() << "Destination IP for assignment is" << nodeList->getDomainHandler().getIP().toString(); + qCDebug(assigmnentclient) << "Destination IP for assignment is" << nodeList->getDomainHandler().getIP().toString(); // start the deployed assignment QThread* workerThread = new QThread; @@ -270,7 +271,7 @@ void AssignmentClient::handleCreateAssignmentPacket(QSharedPointerstarted() workerThread->start(); } else { - qDebug() << "Received an assignment that could not be unpacked. Re-requesting."; + qCWarning(assigmnentclient) << "Received an assignment that could not be unpacked. Re-requesting."; } } @@ -278,12 +279,12 @@ void AssignmentClient::handleStopNodePacket(QSharedPointer mess const HifiSockAddr& senderSockAddr = message->getSenderSockAddr(); if (senderSockAddr.getAddress() == QHostAddress::LocalHost || - senderSockAddr.getAddress() == QHostAddress::LocalHostIPv6) { - qDebug() << "AssignmentClientMonitor at" << senderSockAddr << "requested stop via PacketType::StopNode."; - + senderSockAddr.getAddress() == QHostAddress::LocalHostIPv6) { + + qCDebug(assigmnentclient) << "AssignmentClientMonitor at" << senderSockAddr << "requested stop via PacketType::StopNode."; QCoreApplication::quit(); } else { - qDebug() << "Got a stop packet from other than localhost."; + qCWarning(assigmnentclient) << "Got a stop packet from other than localhost."; } } @@ -303,7 +304,7 @@ void AssignmentClient::handleAuthenticationRequest() { // ask the account manager to log us in from the env variables accountManager.requestAccessToken(username, password); } else { - qDebug() << "Authentication was requested against" << qPrintable(accountManager.getAuthURL().toString()) + qCWarning(assigmnentclient) << "Authentication was requested against" << qPrintable(accountManager.getAuthURL().toString()) << "but both or one of" << qPrintable(DATA_SERVER_USERNAME_ENV) << "/" << qPrintable(DATA_SERVER_PASSWORD_ENV) << "are not set. Unable to authenticate."; @@ -321,7 +322,7 @@ void AssignmentClient::assignmentCompleted() { // reset the logging target to the the CHILD_TARGET_NAME LogHandler::getInstance().setTargetName(ASSIGNMENT_CLIENT_TARGET_NAME); - qDebug() << "Assignment finished or never started - waiting for new assignment."; + qCDebug(assigmnentclient) << "Assignment finished or never started - waiting for new assignment."; auto nodeList = DependencyManager::get(); diff --git a/assignment-client/src/AssignmentClientLogging.cpp b/assignment-client/src/AssignmentClientLogging.cpp new file mode 100644 index 0000000000..890187ecaa --- /dev/null +++ b/assignment-client/src/AssignmentClientLogging.cpp @@ -0,0 +1,14 @@ +// +// AssignmentClientLogging.cpp +// assignment-client/src +// +// Created by Clement on 12/14/15. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "AssignmentClientLogging.h" + +Q_LOGGING_CATEGORY(assigmnentclient, "hifi.assignment-client") \ No newline at end of file diff --git a/assignment-client/src/AssignmentClientLogging.h b/assignment-client/src/AssignmentClientLogging.h new file mode 100644 index 0000000000..d6b5ee90e0 --- /dev/null +++ b/assignment-client/src/AssignmentClientLogging.h @@ -0,0 +1,19 @@ +// +// AssignmentClientLogging.h +// assignment-client/src +// +// Created by Clement on 12/14/15. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_AssignmentClientLogging_h +#define hifi_AssignmentClientLogging_h + +#include + +Q_DECLARE_LOGGING_CATEGORY(assigmnentclient) + +#endif // hifi_AssignmentClientLogging_h \ No newline at end of file diff --git a/assignment-client/src/octree/OctreeQueryNode.cpp b/assignment-client/src/octree/OctreeQueryNode.cpp index ffe2e24ca0..044b44a165 100644 --- a/assignment-client/src/octree/OctreeQueryNode.cpp +++ b/assignment-client/src/octree/OctreeQueryNode.cpp @@ -20,80 +20,8 @@ #include "OctreeSendThread.h" -OctreeQueryNode::OctreeQueryNode() : - _viewSent(false), - _octreePacket(), - _octreePacketWaiting(false), - _lastOctreePayload(new char[udt::MAX_PACKET_SIZE]), - _lastOctreePacketLength(0), - _duplicatePacketCount(0), - _firstSuppressedPacket(usecTimestampNow()), - _maxSearchLevel(1), - _maxLevelReachedInLastSearch(1), - _lastTimeBagEmpty(0), - _viewFrustumChanging(false), - _viewFrustumJustStoppedChanging(true), - _octreeSendThread(NULL), - _lastClientBoundaryLevelAdjust(0), - _lastClientOctreeSizeScale(DEFAULT_OCTREE_SIZE_SCALE), - _lodChanged(false), - _lodInitialized(false), - _sequenceNumber(0), - _lastRootTimestamp(0), - _myPacketType(PacketType::Unknown), - _isShuttingDown(false), - _sentPacketHistory() -{ -} - -OctreeQueryNode::~OctreeQueryNode() { - _isShuttingDown = true; - if (_octreeSendThread) { - forceNodeShutdown(); - } - - delete[] _lastOctreePayload; -} - void OctreeQueryNode::nodeKilled() { _isShuttingDown = true; - if (_octreeSendThread) { - // just tell our thread we want to shutdown, this is asynchronous, and fast, we don't need or want it to block - // while the thread actually shuts down - _octreeSendThread->setIsShuttingDown(); - } -} - -void OctreeQueryNode::forceNodeShutdown() { - _isShuttingDown = true; - if (_octreeSendThread) { - // we really need to force our thread to shutdown, this is synchronous, we will block while the thread actually - // shuts down because we really need it to shutdown, and it's ok if we wait for it to complete - OctreeSendThread* sendThread = _octreeSendThread; - _octreeSendThread = NULL; - sendThread->setIsShuttingDown(); - sendThread->terminate(); - delete sendThread; - } -} - -void OctreeQueryNode::sendThreadFinished() { - // We've been notified by our thread that it is shutting down. So we can clean up our reference to it, and - // delete the actual thread object. Cleaning up our thread will correctly unroll all refereces to shared - // pointers to our node as well as the octree server assignment - if (_octreeSendThread) { - OctreeSendThread* sendThread = _octreeSendThread; - _octreeSendThread = NULL; - delete sendThread; - } -} - -void OctreeQueryNode::initializeOctreeSendThread(OctreeServer* myServer, const SharedNodePointer& node) { - _octreeSendThread = new OctreeSendThread(myServer, node); - - // we want to be notified when the thread finishes - connect(_octreeSendThread, &GenericThread::finished, this, &OctreeQueryNode::sendThreadFinished); - _octreeSendThread->initialize(true); } bool OctreeQueryNode::packetIsDuplicate() const { @@ -105,7 +33,7 @@ bool OctreeQueryNode::packetIsDuplicate() const { // of the entire packet, we need to compare only the packet content... if (_lastOctreePacketLength == _octreePacket->getPayloadSize()) { - if (memcmp(_lastOctreePayload + OCTREE_PACKET_EXTRA_HEADERS_SIZE, + if (memcmp(&_lastOctreePayload + OCTREE_PACKET_EXTRA_HEADERS_SIZE, _octreePacket->getPayload() + OCTREE_PACKET_EXTRA_HEADERS_SIZE, _octreePacket->getPayloadSize() - OCTREE_PACKET_EXTRA_HEADERS_SIZE) == 0) { return true; @@ -173,7 +101,7 @@ void OctreeQueryNode::resetOctreePacket() { // scene information, (e.g. the root node packet of a static scene), we can use this as a strategy for reducing // packet send rate. _lastOctreePacketLength = _octreePacket->getPayloadSize(); - memcpy(_lastOctreePayload, _octreePacket->getPayload(), _lastOctreePacketLength); + memcpy(&_lastOctreePayload, _octreePacket->getPayload(), _lastOctreePacketLength); // If we're moving, and the client asked for low res, then we force monochrome, otherwise, use // the clients requested color state. diff --git a/assignment-client/src/octree/OctreeQueryNode.h b/assignment-client/src/octree/OctreeQueryNode.h index 89583492e0..0ec876e674 100644 --- a/assignment-client/src/octree/OctreeQueryNode.h +++ b/assignment-client/src/octree/OctreeQueryNode.h @@ -29,8 +29,8 @@ class OctreeServer; class OctreeQueryNode : public OctreeQuery { Q_OBJECT public: - OctreeQueryNode(); - virtual ~OctreeQueryNode(); + OctreeQueryNode() = default; + virtual ~OctreeQueryNode() = default; void init(); // called after creation to set up some virtual items virtual PacketType getMyPacketType() const = 0; @@ -79,9 +79,6 @@ public: OctreeSceneStats stats; - void initializeOctreeSendThread(OctreeServer* myServer, const SharedNodePointer& node); - bool isOctreeSendThreadInitalized() { return _octreeSendThread; } - void dumpOutOfView(); quint64 getLastRootTimestamp() const { return _lastRootTimestamp; } @@ -92,7 +89,6 @@ public: void sceneStart(quint64 sceneSendStartTime) { _sceneSendStartTime = sceneSendStartTime; } void nodeKilled(); - void forceNodeShutdown(); bool isShuttingDown() const { return _isShuttingDown; } void octreePacketSent() { packetSent(*_octreePacket); } @@ -104,49 +100,47 @@ public: bool hasNextNackedPacket() const; const NLPacket* getNextNackedPacket(); -private slots: - void sendThreadFinished(); - private: OctreeQueryNode(const OctreeQueryNode &); OctreeQueryNode& operator= (const OctreeQueryNode&); - bool _viewSent; + bool _viewSent { false }; std::unique_ptr _octreePacket; bool _octreePacketWaiting; - char* _lastOctreePayload = nullptr; - unsigned int _lastOctreePacketLength; - int _duplicatePacketCount; - quint64 _firstSuppressedPacket; + unsigned int _lastOctreePacketLength { 0 }; + int _duplicatePacketCount { 0 }; + quint64 _firstSuppressedPacket { usecTimestampNow() }; - int _maxSearchLevel; - int _maxLevelReachedInLastSearch; + int _maxSearchLevel { 1 }; + int _maxLevelReachedInLastSearch { 1 }; ViewFrustum _currentViewFrustum; ViewFrustum _lastKnownViewFrustum; - quint64 _lastTimeBagEmpty; - bool _viewFrustumChanging; - bool _viewFrustumJustStoppedChanging; + quint64 _lastTimeBagEmpty { 0 }; + bool _viewFrustumChanging { false }; + bool _viewFrustumJustStoppedChanging { true }; - OctreeSendThread* _octreeSendThread; + OctreeSendThread* _octreeSendThread { nullptr }; // watch for LOD changes - int _lastClientBoundaryLevelAdjust; - float _lastClientOctreeSizeScale; - bool _lodChanged; - bool _lodInitialized; + int _lastClientBoundaryLevelAdjust { 0 }; + float _lastClientOctreeSizeScale { DEFAULT_OCTREE_SIZE_SCALE }; + bool _lodChanged { false }; + bool _lodInitialized { false }; - OCTREE_PACKET_SEQUENCE _sequenceNumber; + OCTREE_PACKET_SEQUENCE _sequenceNumber { 0 }; - quint64 _lastRootTimestamp; + quint64 _lastRootTimestamp { 0 }; - PacketType _myPacketType; - bool _isShuttingDown; + PacketType _myPacketType { PacketType::Unknown }; + bool _isShuttingDown { false }; SentPacketHistory _sentPacketHistory; QQueue _nackedSequenceNumbers; quint64 _sceneSendStartTime = 0; + + std::array _lastOctreePayload; }; #endif // hifi_OctreeQueryNode_h diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index b4eb75ede9..2ff06c7439 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -14,6 +14,7 @@ #include #include +#include "OctreeQueryNode.h" #include "OctreeSendThread.h" #include "OctreeServer.h" #include "OctreeServerConsts.h" @@ -25,15 +26,12 @@ quint64 endSceneSleepTime = 0; OctreeSendThread::OctreeSendThread(OctreeServer* myServer, const SharedNodePointer& node) : _myServer(myServer), _node(node), - _nodeUUID(node->getUUID()), - _packetData(), - _nodeMissingCount(0), - _isShuttingDown(false) + _nodeUuid(node->getUUID()) { QString safeServerName("Octree"); // set our QThread object name so we can identify this thread while debugging - setObjectName(QString("Octree Send Thread (%1)").arg(uuidStringWithoutCurlyBraces(node->getUUID()))); + setObjectName(QString("Octree Send Thread (%1)").arg(uuidStringWithoutCurlyBraces(_nodeUuid))); if (_myServer) { safeServerName = _myServer->getMyServerName(); @@ -46,6 +44,8 @@ OctreeSendThread::OctreeSendThread(OctreeServer* myServer, const SharedNodePoint } OctreeSendThread::~OctreeSendThread() { + setIsShuttingDown(); + QString safeServerName("Octree"); if (_myServer) { safeServerName = _myServer->getMyServerName(); @@ -56,8 +56,6 @@ OctreeSendThread::~OctreeSendThread() { OctreeServer::clientDisconnected(); OctreeServer::stopTrackingThread(this); - - _node.clear(); } void OctreeSendThread::setIsShuttingDown() { @@ -79,15 +77,17 @@ bool OctreeSendThread::process() { // don't do any send processing until the initial load of the octree is complete... if (_myServer->isInitialLoadComplete()) { - if (_node) { + if (auto node = _node.lock()) { _nodeMissingCount = 0; - OctreeQueryNode* nodeData = static_cast(_node->getLinkedData()); + 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(nodeData, viewFrustumChanged); + packetDistributor(node, nodeData, viewFrustumChanged); } + } else { + return false; // exit early if we're shutting down } } @@ -123,7 +123,8 @@ AtomicUIntStat OctreeSendThread::_totalSpecialBytes { 0 }; AtomicUIntStat OctreeSendThread::_totalSpecialPackets { 0 }; -int OctreeSendThread::handlePacketSend(OctreeQueryNode* nodeData, int& trueBytesSent, int& truePacketsSent) { +int OctreeSendThread::handlePacketSend(SharedNodePointer node, OctreeQueryNode* nodeData, int& trueBytesSent, + int& truePacketsSent) { OctreeServer::didHandlePacketSend(this); // if we're shutting down, then exit early @@ -183,12 +184,12 @@ int OctreeSendThread::handlePacketSend(OctreeQueryNode* nodeData, int& trueBytes // actually send it OctreeServer::didCallWriteDatagram(this); - DependencyManager::get()->sendUnreliablePacket(statsPacket, *_node); + DependencyManager::get()->sendUnreliablePacket(statsPacket, *node); packetSent = true; } else { // not enough room in the packet, send two packets OctreeServer::didCallWriteDatagram(this); - DependencyManager::get()->sendUnreliablePacket(statsPacket, *_node); + DependencyManager::get()->sendUnreliablePacket(statsPacket, *node); // since a stats message is only included on end of scene, don't consider any of these bytes "wasted", since // there was nothing else to send. @@ -219,7 +220,7 @@ int OctreeSendThread::handlePacketSend(OctreeQueryNode* nodeData, int& trueBytes packetsSent++; OctreeServer::didCallWriteDatagram(this); - DependencyManager::get()->sendUnreliablePacket(nodeData->getPacket(), *_node); + DependencyManager::get()->sendUnreliablePacket(nodeData->getPacket(), *node); packetSent = true; int packetSizeWithHeader = nodeData->getPacket().getDataSize(); @@ -251,7 +252,7 @@ int OctreeSendThread::handlePacketSend(OctreeQueryNode* nodeData, int& trueBytes if (nodeData->isPacketWaiting() && !nodeData->isShuttingDown()) { // just send the octree packet OctreeServer::didCallWriteDatagram(this); - DependencyManager::get()->sendUnreliablePacket(nodeData->getPacket(), *_node); + DependencyManager::get()->sendUnreliablePacket(nodeData->getPacket(), *node); packetSent = true; int packetSizeWithHeader = nodeData->getPacket().getDataSize(); @@ -293,7 +294,7 @@ int OctreeSendThread::handlePacketSend(OctreeQueryNode* nodeData, int& trueBytes } /// Version of octree element distributor that sends the deepest LOD level at once -int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrustumChanged) { +int OctreeSendThread::packetDistributor(SharedNodePointer node, OctreeQueryNode* nodeData, bool viewFrustumChanged) { OctreeServer::didPacketDistributor(this); @@ -322,7 +323,7 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus // If we have a packet waiting, and our desired want color, doesn't match the current waiting packets color // then let's just send that waiting packet. if (nodeData->isPacketWaiting()) { - packetsSentThisInterval += handlePacketSend(nodeData, trueBytesSent, truePacketsSent); + packetsSentThisInterval += handlePacketSend(node, nodeData, trueBytesSent, truePacketsSent); } else { nodeData->resetOctreePacket(); } @@ -355,7 +356,7 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus //unsigned long encodeTime = nodeData->stats.getTotalEncodeTime(); //unsigned long elapsedTime = nodeData->stats.getElapsedTime(); - int packetsJustSent = handlePacketSend(nodeData, trueBytesSent, truePacketsSent); + int packetsJustSent = handlePacketSend(node, nodeData, trueBytesSent, truePacketsSent); packetsSentThisInterval += packetsJustSent; // If we're starting a full scene, then definitely we want to empty the elementBag @@ -431,8 +432,8 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus // Our trackSend() function is implemented by the server subclass, and will be called back // during the encodeTreeBitstream() as new entities/data elements are sent - params.trackSend = [this](const QUuid& dataID, quint64 dataEdited) { - _myServer->trackSend(dataID, dataEdited, _nodeUUID); + params.trackSend = [this, node](const QUuid& dataID, quint64 dataEdited) { + _myServer->trackSend(dataID, dataEdited, node->getUUID()); }; // TODO: should this include the lock time or not? This stat is sent down to the client, @@ -481,7 +482,7 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus unsigned int writtenSize = _packetData.getFinalizedSize() + sizeof(OCTREE_PACKET_INTERNAL_SECTION_SIZE); if (writtenSize > nodeData->getAvailable()) { - packetsSentThisInterval += handlePacketSend(nodeData, trueBytesSent, truePacketsSent); + packetsSentThisInterval += handlePacketSend(node, nodeData, trueBytesSent, truePacketsSent); } nodeData->writeToPacket(_packetData.getFinalizedData(), _packetData.getFinalizedSize()); @@ -501,7 +502,7 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus int targetSize = MAX_OCTREE_PACKET_DATA_SIZE; if (sendNow) { quint64 packetSendingStart = usecTimestampNow(); - packetsSentThisInterval += handlePacketSend(nodeData, trueBytesSent, truePacketsSent); + packetsSentThisInterval += handlePacketSend(node, nodeData, trueBytesSent, truePacketsSent); quint64 packetSendingEnd = usecTimestampNow(); packetSendingElapsedUsec = (float)(packetSendingEnd - packetSendingStart); @@ -538,9 +539,9 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus // Here's where we can/should allow the server to send other data... // send the environment packet // TODO: should we turn this into a while loop to better handle sending multiple special packets - if (_myServer->hasSpecialPacketsToSend(_node) && !nodeData->isShuttingDown()) { + if (_myServer->hasSpecialPacketsToSend(node) && !nodeData->isShuttingDown()) { int specialPacketsSent = 0; - trueBytesSent += _myServer->sendSpecialPackets(_node, nodeData, specialPacketsSent); + trueBytesSent += _myServer->sendSpecialPackets(node, nodeData, specialPacketsSent); nodeData->resetOctreePacket(); // because nodeData's _sequenceNumber has changed truePacketsSent += specialPacketsSent; packetsSentThisInterval += specialPacketsSent; @@ -556,7 +557,7 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus while (nodeData->hasNextNackedPacket() && packetsSentThisInterval < maxPacketsPerInterval) { const NLPacket* packet = nodeData->getNextNackedPacket(); if (packet) { - DependencyManager::get()->sendUnreliablePacket(*packet, *_node); + DependencyManager::get()->sendUnreliablePacket(*packet, *node); truePacketsSent++; packetsSentThisInterval++; diff --git a/assignment-client/src/octree/OctreeSendThread.h b/assignment-client/src/octree/OctreeSendThread.h index 6775e56820..38f5de722f 100644 --- a/assignment-client/src/octree/OctreeSendThread.h +++ b/assignment-client/src/octree/OctreeSendThread.h @@ -18,8 +18,7 @@ #include -#include "OctreeQueryNode.h" - +class OctreeQueryNode; class OctreeServer; using AtomicUIntStat = std::atomic; @@ -32,6 +31,9 @@ public: virtual ~OctreeSendThread(); void setIsShuttingDown(); + bool isShuttingDown() { return _isShuttingDown; } + + QUuid getNodeUuid() const { return _nodeUuid; } static AtomicUIntStat _totalBytes; static AtomicUIntStat _totalWastedBytes; @@ -48,17 +50,18 @@ protected: virtual bool process(); private: - OctreeServer* _myServer; - SharedNodePointer _node; - QUuid _nodeUUID; - - int handlePacketSend(OctreeQueryNode* nodeData, int& trueBytesSent, int& truePacketsSent); - int packetDistributor(OctreeQueryNode* nodeData, bool viewFrustumChanged); + int handlePacketSend(SharedNodePointer node, OctreeQueryNode* nodeData, int& trueBytesSent, int& truePacketsSent); + int packetDistributor(SharedNodePointer node, OctreeQueryNode* nodeData, bool viewFrustumChanged); + + + OctreeServer* _myServer { nullptr }; + QWeakPointer _node; + QUuid _nodeUuid; OctreePacketData _packetData; - int _nodeMissingCount; - bool _isShuttingDown; + int _nodeMissingCount { 0 }; + bool _isShuttingDown { false }; }; #endif // hifi_OctreeSendThread_h diff --git a/assignment-client/src/octree/OctreeServer.cpp b/assignment-client/src/octree/OctreeServer.cpp index ec34ad4410..410aa922dc 100644 --- a/assignment-client/src/octree/OctreeServer.cpp +++ b/assignment-client/src/octree/OctreeServer.cpp @@ -25,9 +25,9 @@ #include "../AssignmentClient.h" +#include "OctreeQueryNode.h" #include "OctreeServerConsts.h" -OctreeServer* OctreeServer::_instance = NULL; int OctreeServer::_clientCount = 0; const int MOVING_AVERAGE_SAMPLE_COUNTS = 1000000; @@ -231,13 +231,6 @@ OctreeServer::OctreeServer(ReceivedMessage& message) : _started(time(0)), _startedUSecs(usecTimestampNow()) { - if (_instance) { - qDebug() << "Octree Server starting... while old instance still running _instance=["<<_instance<<"] this=[" << this << "]"; - } - - qDebug() << "Octree Server starting... setting _instance to=[" << this << "]"; - _instance = this; - _averageLoopTime.updateAverage(0); qDebug() << "Octree server starting... [" << this << "]"; @@ -281,9 +274,6 @@ OctreeServer::~OctreeServer() { _tree.reset(); qDebug() << qPrintable(_safeServerName) << "server DONE cleaning up octree... [" << this << "]"; - if (_instance == this) { - _instance = NULL; // we are gone - } qDebug() << qPrintable(_safeServerName) << "server DONE shutting down... [" << this << "]"; } @@ -878,16 +868,38 @@ void OctreeServer::parsePayload() { } } +OctreeServer::UniqueSendThread OctreeServer::createSendThread(const SharedNodePointer& node) { + auto sendThread = std::unique_ptr(new OctreeSendThread(this, node)); + + // we want to be notified when the thread finishes + connect(sendThread.get(), &GenericThread::finished, this, &OctreeServer::removeSendThread); + sendThread->initialize(true); + + return sendThread; +} + +void OctreeServer::removeSendThread() { + // If the object has been deleted since the event was queued, sender() will return nullptr + if (auto sendThread = qobject_cast(sender())) { + // This deletes the unique_ptr, so sendThread is destructed after that line + _sendThreads.erase(sendThread->getNodeUuid()); + } +} + void OctreeServer::handleOctreeQueryPacket(QSharedPointer message, SharedNodePointer senderNode) { - if (!_isFinished) { + if (!_isFinished && !_isShuttingDown) { // If we got a query packet, then we're talking to an agent, and we // need to make sure we have it in our nodeList. auto nodeList = DependencyManager::get(); nodeList->updateNodeWithDataFromPacket(message, senderNode); - OctreeQueryNode* nodeData = dynamic_cast(senderNode->getLinkedData()); - if (nodeData && !nodeData->isOctreeSendThreadInitalized()) { - nodeData->initializeOctreeSendThread(this, senderNode); + auto it = _sendThreads.find(senderNode->getUUID()); + if (it == _sendThreads.end()) { + _sendThreads.emplace(senderNode->getUUID(), createSendThread(senderNode)); + } else if (it->second->isShuttingDown()) { + _sendThreads.erase(it); // Remove right away and wait on thread to be + + _sendThreads.emplace(senderNode->getUUID(), createSendThread(senderNode)); } } } @@ -1117,8 +1129,8 @@ void OctreeServer::domainSettingsRequestComplete() { setvbuf(stdout, NULL, _IOLBF, 0); #endif - nodeList->linkedDataCreateCallback = [] (Node* node) { - auto queryNodeData = _instance->createOctreeQueryNode(); + nodeList->linkedDataCreateCallback = [this](Node* node) { + auto queryNodeData = createOctreeQueryNode(); queryNodeData->init(); node->setLinkedData(std::move(queryNodeData)); }; @@ -1167,6 +1179,13 @@ void OctreeServer::nodeAdded(SharedNodePointer node) { void OctreeServer::nodeKilled(SharedNodePointer node) { quint64 start = usecTimestampNow(); + + // Shutdown send thread + auto it = _sendThreads.find(node->getUUID()); + if (it != _sendThreads.end()) { + auto& sendThread = *it->second; + sendThread.setIsShuttingDown(); + } // calling this here since nodeKilled slot in ReceivedPacketProcessor can't be triggered by signals yet!! _octreeInboundPacketProcessor->nodeKilled(node); @@ -1188,24 +1207,6 @@ void OctreeServer::nodeKilled(SharedNodePointer node) { trackViewerGone(node->getUUID()); } -void OctreeServer::forceNodeShutdown(SharedNodePointer node) { - quint64 start = usecTimestampNow(); - - qDebug() << qPrintable(_safeServerName) << "server killed node:" << *node; - OctreeQueryNode* nodeData = dynamic_cast(node->getLinkedData()); - if (nodeData) { - nodeData->forceNodeShutdown(); // tell our node data and sending threads that we'd like to shut down - } else { - qDebug() << qPrintable(_safeServerName) << "server node missing linked data node:" << *node; - } - - quint64 end = usecTimestampNow(); - quint64 usecsElapsed = (end - start); - qDebug() << qPrintable(_safeServerName) << "server forceNodeShutdown() took: " - << usecsElapsed << " usecs for node:" << *node; -} - - void OctreeServer::aboutToFinish() { qDebug() << qPrintable(_safeServerName) << "server STARTING about to finish..."; @@ -1214,9 +1215,8 @@ void OctreeServer::aboutToFinish() { qDebug() << qPrintable(_safeServerName) << "inform Octree Inbound Packet Processor that we are shutting down..."; // we're going down - set the NodeList linkedDataCallback to NULL so we do not create any more OctreeQueryNode objects. - // This ensures that when we forceNodeShutdown below for each node we don't get any more newly connecting nodes - auto nodeList = DependencyManager::get(); - nodeList->linkedDataCreateCallback = NULL; + // This ensures that we don't get any more newly connecting nodes + DependencyManager::get()->linkedDataCreateCallback = nullptr; if (_octreeInboundPacketProcessor) { _octreeInboundPacketProcessor->terminating(); @@ -1226,21 +1226,15 @@ void OctreeServer::aboutToFinish() { _jurisdictionSender->terminating(); } - QSet nodesToShutdown; - - // Force a shutdown of all of our OctreeSendThreads. - // At this point it has to be impossible for a linkedDataCreateCallback to be called for a new node - nodeList->eachNode([&nodesToShutdown](const SharedNodePointer& node) { - nodesToShutdown << node; - }); - - // What follows is a hack to force OctreeSendThreads to cleanup before the OctreeServer is gone. - // I would prefer to allow the SharedNodePointer ref count drop to zero to do this automatically - // but that isn't possible as long as the OctreeSendThread has an OctreeServer* that it uses. - for (auto& node : nodesToShutdown) { - qDebug() << qPrintable(_safeServerName) << "server about to finish while node still connected node:" << *node; - forceNodeShutdown(node); + // Shut down all the send threads + for (auto& it : _sendThreads) { + auto& sendThread = *it.second; + sendThread.setIsShuttingDown(); } + + // Clear will destruct all the unique_ptr to OctreeSendThreads which will call the GenericThread's dtor + // which waits on the thread to be done before returning + _sendThreads.clear(); // Cleans up all the send threads. if (_persistThread) { _persistThread->aboutToFinish(); @@ -1459,15 +1453,22 @@ void OctreeServer::didCallWriteDatagram(OctreeSendThread* thread) { 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); + { + QMutexLocker locker(&_threadsDidProcessMutex); + _threadsDidProcess.remove(thread); + } + { + QMutexLocker locker(&_threadsDidPacketDistributorMutex); + _threadsDidPacketDistributor.remove(thread); + } + { + QMutexLocker locker(&_threadsDidHandlePacketSendMutex); + _threadsDidHandlePacketSend.remove(thread); + } + { + QMutexLocker locker(&_threadsDidCallWriteDatagramMutex); + _threadsDidCallWriteDatagram.remove(thread); + } } int howManyThreadsDidSomething(QMutex& mutex, QMap& something, quint64 since) { diff --git a/assignment-client/src/octree/OctreeServer.h b/assignment-client/src/octree/OctreeServer.h index 80668f841c..2aabb97428 100644 --- a/assignment-client/src/octree/OctreeServer.h +++ b/assignment-client/src/octree/OctreeServer.h @@ -124,7 +124,6 @@ public: bool handleHTTPRequest(HTTPConnection* connection, const QUrl& url, bool skipSubHandler); virtual void aboutToFinish(); - void forceNodeShutdown(SharedNodePointer node); public slots: /// runs the octree server assignment @@ -138,8 +137,12 @@ private slots: void handleOctreeQueryPacket(QSharedPointer message, SharedNodePointer senderNode); void handleOctreeDataNackPacket(QSharedPointer message, SharedNodePointer senderNode); void handleJurisdictionRequestPacket(QSharedPointer message, SharedNodePointer senderNode); + void removeSendThread(); protected: + using UniqueSendThread = std::unique_ptr; + using SendThreads = std::unordered_map; + virtual OctreePointer createTree() = 0; bool readOptionBool(const QString& optionName, const QJsonObject& settingsSectionObject, bool& result); bool readOptionInt(const QString& optionName, const QJsonObject& settingsSectionObject, int& result); @@ -153,6 +156,8 @@ protected: QString getFileLoadTime(); QString getConfiguration(); QString getStatusLink(); + + UniqueSendThread createSendThread(const SharedNodePointer& node); int _argc; const char** _argv; @@ -187,11 +192,11 @@ protected: int _backupInterval; int _maxBackupVersions; - static OctreeServer* _instance; - time_t _started; quint64 _startedUSecs; QString _safeServerName; + + SendThreads _sendThreads; static int _clientCount; static SimpleMovingAverage _averageLoopTime; diff --git a/cmake/macros/ConsolidateStackComponents.cmake b/cmake/macros/ConsolidateStackComponents.cmake index 4bcc777751..ca272f6485 100644 --- a/cmake/macros/ConsolidateStackComponents.cmake +++ b/cmake/macros/ConsolidateStackComponents.cmake @@ -1,26 +1,27 @@ macro(CONSOLIDATE_STACK_COMPONENTS) - if (DEFINED DEPLOY_PACKAGE AND DEPLOY_PACKAGE AND WIN32) - - # Copy all the output for this target into the common deployment location - add_custom_command( - TARGET ${TARGET_NAME} POST_BUILD - COMMAND "${CMAKE_COMMAND}" -E copy_directory $ ${CMAKE_BINARY_DIR}/full-stack-deployment - ) - - # Copy icon files for interface and stack manager - if (TARGET_NAME STREQUAL "interface" OR TARGET_NAME STREQUAL "stack-manager") - if (TARGET_NAME STREQUAL "interface") - set (ICON_FILE_PATH "${PROJECT_SOURCE_DIR}/icon/interface.ico") - set (ICON_DESTINATION_NAME "interface.ico") - elseif (TARGET_NAME STREQUAL "stack-manager") - set (ICON_FILE_PATH "${PROJECT_SOURCE_DIR}/assets/icon.ico") - set (ICON_DESTINATION_NAME "stack-manager.ico") - endif () + if (DEFINED DEPLOY_PACKAGE AND DEPLOY_PACKAGE) + if (WIN32) + # Copy all the output for this target into the common deployment location add_custom_command( TARGET ${TARGET_NAME} POST_BUILD - COMMAND "${CMAKE_COMMAND}" -E copy ${ICON_FILE_PATH} ${CMAKE_BINARY_DIR}/full-stack-deployment/${ICON_DESTINATION_NAME} + COMMAND "${CMAKE_COMMAND}" -E copy_directory $ ${CMAKE_BINARY_DIR}/full-stack-deployment ) + + # Copy icon files for interface and stack manager + if (TARGET_NAME STREQUAL "interface" OR TARGET_NAME STREQUAL "stack-manager") + if (TARGET_NAME STREQUAL "interface") + set (ICON_FILE_PATH "${PROJECT_SOURCE_DIR}/icon/interface.ico") + set (ICON_DESTINATION_NAME "interface.ico") + elseif (TARGET_NAME STREQUAL "stack-manager") + set (ICON_FILE_PATH "${PROJECT_SOURCE_DIR}/assets/icon.ico") + set (ICON_DESTINATION_NAME "stack-manager.ico") + endif () + add_custom_command( + TARGET ${TARGET_NAME} POST_BUILD + COMMAND "${CMAKE_COMMAND}" -E copy ${ICON_FILE_PATH} ${CMAKE_BINARY_DIR}/full-stack-deployment/${ICON_DESTINATION_NAME} + ) + endif () endif () endif () diff --git a/cmake/macros/GenerateInstallers.cmake b/cmake/macros/GenerateInstallers.cmake new file mode 100644 index 0000000000..570e24332b --- /dev/null +++ b/cmake/macros/GenerateInstallers.cmake @@ -0,0 +1,30 @@ +# +# GenerateInstallers.cmake +# cmake/macros +# +# Created by Leonardo Murillo on 12/16/2015. +# Copyright 2015 High Fidelity, Inc. +# +# Distributed under the Apache License, Version 2.0. +# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +# + +macro(GENERATE_INSTALLERS) + if (DEFINED DEPLOY_PACKAGE AND DEPLOY_PACKAGE AND WIN32) + file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/full-stack-deployment") + find_program(MAKENSIS_COMMAND makensis PATHS [HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\NSIS]) + if (NOT MAKENSIS_COMMAND) + message(FATAL_ERROR "The Nullsoft Scriptable Install Systems is required for generating packaged installers on Windows (http://nsis.sourceforge.net/)") + endif () + add_custom_target( + build-package ALL + DEPENDS interface assignment-client domain-server stack-manager + COMMAND set INSTALLER_SOURCE_DIR=${CMAKE_BINARY_DIR}/full-stack-deployment + COMMAND set INSTALLER_NAME=${CMAKE_BINARY_DIR}/${INSTALLER_NAME} + COMMAND set INSTALLER_SCRIPTS_DIR=${CMAKE_SOURCE_DIR}/examples + COMMAND set INSTALLER_COMPANY=${INSTALLER_COMPANY} + COMMAND set INSTALLER_DIRECTORY=${INSTALLER_DIRECTORY} + COMMAND CMD /C "\"${MAKENSIS_COMMAND}\" ${CMAKE_SOURCE_DIR}/tools/nsis/release.nsi" + ) + endif () +endmacro() \ No newline at end of file diff --git a/cmake/macros/IncludeApplicationVersion.cmake b/cmake/macros/IncludeApplicationVersion.cmake index a91aad6acc..753a12a01c 100644 --- a/cmake/macros/IncludeApplicationVersion.cmake +++ b/cmake/macros/IncludeApplicationVersion.cmake @@ -14,13 +14,22 @@ macro(INCLUDE_APPLICATION_VERSION) # We are relying on Jenkins defined environment variables to determine the origin of this build # and will only package if this is a PR or Release build if (DEFINED ENV{JOB_ID}) - set (DEPLOY_PACKAGE 1) - set (BUILD_SEQ $ENV{JOB_ID}) + set(DEPLOY_PACKAGE 1) + set(BUILD_SEQ $ENV{JOB_ID}) + set(INSTALLER_COMPANY "High Fidelity") + set(INSTALLER_DIRECTORY "${INSTALLER_COMPANY}") + set(INSTALLER_NAME "interface-win64-${BUILD_SEQ}.exe") elseif (DEFINED ENV{ghprbPullId}) - set (DEPLOY_PACKAGE 1) - set (BUILD_SEQ "PR-$ENV{ghprbPullId}") + set(DEPLOY_PACKAGE 1) + set(BUILD_SEQ "PR-$ENV{ghprbPullId}") + set(INSTALLER_COMPANY "High Fidelity - PR") + set(INSTALLER_DIRECTORY "${INSTALLER_COMPANY}\\${BUILD_SEQ}") + set(INSTALLER_NAME "pr-interface-win64-${BUILD_SEQ}.exe") else () set(BUILD_SEQ "dev") + set(INSTALLER_COMPANY "High Fidelity - Dev") + set(INSTALLER_DIRECTORY "${INSTALLER_COMPANY}") + set(INSTALLER_NAME "dev-interface-win64.exe") endif () configure_file("${MACRO_DIR}/ApplicationVersion.h.in" "${PROJECT_BINARY_DIR}/includes/ApplicationVersion.h") include_directories("${PROJECT_BINARY_DIR}/includes") diff --git a/interface/src/ui/overlays/Image3DOverlay.cpp b/interface/src/ui/overlays/Image3DOverlay.cpp index 7d105a6ccf..f1e0f08a3a 100644 --- a/interface/src/ui/overlays/Image3DOverlay.cpp +++ b/interface/src/ui/overlays/Image3DOverlay.cpp @@ -34,8 +34,8 @@ Image3DOverlay::Image3DOverlay(const Image3DOverlay* image3DOverlay) : Billboard3DOverlay(image3DOverlay), _url(image3DOverlay->_url), _texture(image3DOverlay->_texture), - _fromImage(image3DOverlay->_fromImage), - _emissive(image3DOverlay->_emissive) + _emissive(image3DOverlay->_emissive), + _fromImage(image3DOverlay->_fromImage) { } diff --git a/libraries/networking/src/Assignment.h b/libraries/networking/src/Assignment.h index 399deaa314..97caedcfb3 100644 --- a/libraries/networking/src/Assignment.h +++ b/libraries/networking/src/Assignment.h @@ -23,7 +23,7 @@ const int MAX_PAYLOAD_BYTES = 1024; const QString emptyPool = QString(); /// Holds information used for request, creation, and deployment of assignments -class Assignment : public NodeData { +class Assignment : public QObject { Q_OBJECT public: diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index 4419ba882a..0b194b017e 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -40,7 +40,6 @@ const char SOLO_NODE_TYPES[2] = { }; LimitedNodeList::LimitedNodeList(unsigned short socketListenPort, unsigned short dtlsListenPort) : - linkedDataCreateCallback(NULL), _sessionUUID(), _nodeHash(), _nodeMutex(QReadWriteLock::Recursive), diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index c89949b9fd..87ed12ac66 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -129,7 +129,7 @@ public: qint64 sendPacketList(std::unique_ptr packetList, const HifiSockAddr& sockAddr); qint64 sendPacketList(std::unique_ptr packetList, const Node& destinationNode); - void (*linkedDataCreateCallback)(Node *); + std::function linkedDataCreateCallback; size_t size() const { return _nodeHash.size(); } diff --git a/libraries/shared/src/GenericThread.cpp b/libraries/shared/src/GenericThread.cpp index 66af2e01c8..c1c31ab50a 100644 --- a/libraries/shared/src/GenericThread.cpp +++ b/libraries/shared/src/GenericThread.cpp @@ -15,7 +15,6 @@ GenericThread::GenericThread() : - QObject(), _stopThread(false), _isThreaded(false) // assume non-threaded, must call initialize() { @@ -38,9 +37,10 @@ void GenericThread::initialize(bool isThreaded, QThread::Priority priority) { _thread->setObjectName(objectName()); // when the worker thread is started, call our engine's run.. - connect(_thread, SIGNAL(started()), this, SLOT(threadRoutine())); + connect(_thread, &QThread::started, this, &GenericThread::threadRoutine); + connect(_thread, &QThread::finished, this, &GenericThread::finished); - this->moveToThread(_thread); + moveToThread(_thread); // Starts an event loop, and emits _thread->started() _thread->start(); @@ -82,5 +82,4 @@ void GenericThread::threadRoutine() { if (_isThreaded && _thread) { _thread->quit(); } - emit finished(); } diff --git a/tools/nsis/release.nsi b/tools/nsis/release.nsi new file mode 100644 index 0000000000..9bc75e5274 --- /dev/null +++ b/tools/nsis/release.nsi @@ -0,0 +1,164 @@ +!include LogicLib.nsh +!include x64.nsh + +!define srcdir "$%INSTALLER_SOURCE_DIR%" +!define setup "$%INSTALLER_NAME%" +!define scriptsdir "$%INSTALLER_SCRIPTS_DIR%" +!define company "$%INSTALLER_COMPANY%" +!define install_directory "$%INSTALLER_DIRECTORY%" +!define interface_exec "interface.exe" +!define stack_manager_exec "stack-manager.exe" +!define interface_icon "interface.ico" +!define stack_manager_icon "stack-manager.ico" +!define regkey "Software\${company}" +!define uninstkey "Software\Microsoft\Windows\CurrentVersion\Uninstall\${company}" +!define install_dir_company "$PROGRAMFILES64\${install_directory}" +!define startmenu_company "$SMPROGRAMS\${install_directory}" +!define uninstaller "uninstall.exe" + +;-------------------------------- + +XPStyle on +ShowInstDetails hide +ShowUninstDetails hide + +Name "${company}" +Caption "${company}" + +!ifdef icon + Icon "${icon}" +!endif + +OutFile "${setup}" + +SetDateSave on +SetDatablockOptimize on +CRCCheck on +SilentInstall normal + +InstallDir "${install_dir_company}" +InstallDirRegKey HKLM "${regkey}" "" + +; Page components +Page directory +Page components +Page instfiles + +UninstPage uninstConfirm +UninstPage instfiles + +;-------------------------------- + +AutoCloseWindow true +ShowInstDetails show + + +!ifdef screenimage + + ; set up background image + ; uses BgImage plugin + + Function .onGUIInit + ; extract background BMP into temp plugin directory + InitPluginsDir + File /oname=$PLUGINSDIR\1.bmp "${screenimage}" + + BgImage::SetBg /NOUNLOAD /FILLSCREEN $PLUGINSDIR\1.bmp + BgImage::Redraw /NOUNLOAD + FunctionEnd + + Function .onGUIEnd + ; Destroy must not have /NOUNLOAD so NSIS will be able to unload and delete BgImage before it exits + BgImage::Destroy + FunctionEnd + +!endif + +; Optional Component Selection +Section /o "DDE Face Recognition" SEC01 + SetOutPath "$INSTDIR" + CreateDirectory $INSTDIR\dde + NSISdl::download "https://s3-us-west-1.amazonaws.com/hifi-production/optionals/dde-installer.exe" "$INSTDIR\dde-installer.exe" + ExecWait '"$INSTDIR\dde-installer.exe" /q:a /t:"$INSTDIR\dde"' +SectionEnd + +; beginning (invisible) section +Section "Registry Entries and Procotol Handler" SEC02 + + SectionIn RO + + WriteRegStr HKLM "${regkey}" "Install_Dir" "$INSTDIR" + WriteRegStr HKLM "${uninstkey}" "DisplayName" "${company} (remove only)" + WriteRegStr HKLM "${uninstkey}" "UninstallString" '"$INSTDIR\${uninstaller}"' + WriteRegStr HKCR "${company}\Shell\open\command\" "" '"$INSTDIR\${interface_exec} "%1"' + WriteRegStr HKCR "${company}\DefaultIcon" "" "$INSTDIR\${interface_icon}" + + ; hifi:// protocol handler registry entries + WriteRegStr HKCR 'hifi' '' 'URL:Alert Protocol' + WriteRegStr HKCR 'hifi' 'URL Protocol' '' + WriteRegStr HKCR 'hifi\DefaultIcon' '' '$INSTDIR\${interface_icon},1' + WriteRegStr HKCR 'hifi\shell\open\command' '' '$INSTDIR\${interface_exec} --url "%1"' + + SetOutPath $INSTDIR + + ; package all files, recursively, preserving attributes + ; assume files are in the correct places + File /r "${srcdir}\" + File /a "${srcdir}\${interface_icon}" + File /a "${srcdir}\${stack_manager_icon}" + ; any application-specific files + !ifdef files + !include "${files}" + !endif + WriteUninstaller "${uninstaller}" + Exec '"$INSTDIR\2013_vcredist_x64.exe" /q /norestart' + Exec '"$INSTDIR\2010_vcredist_x86.exe" /q /norestart' +SectionEnd + +; create shortcuts +Section "Start Menu Shortcuts" SEC03 + + SectionIn RO + + ; This should install the shortcuts for "All Users" + SetShellVarContext all + CreateDirectory "${startmenu_company}" + SetOutPath $INSTDIR ; for working directory + CreateShortCut "${startmenu_company}\Interface.lnk" "$INSTDIR\${interface_exec}" "" "$INSTDIR\${interface_icon}" + CreateShortCut "${startmenu_company}\Stack Manager.lnk" "$INSTDIR\${stack_manager_exec}" "" "$INSTDIR\${stack_manager_icon}" + CreateShortCut "${startmenu_company}\Uninstall ${company}.lnk" "$INSTDIR\${uninstaller}" +SectionEnd + +; Uninstaller +; All section names prefixed by "Un" will be in the uninstaller + +UninstallText "This will uninstall ${company}." + +!ifdef icon + UninstallIcon "${interface_icon}" +!endif + +Section "Uninstall" SEC04 + + SectionIn RO + + ; Explicitly remove all added shortcuts + SetShellVarContext all + DELETE "${startmenu_company}\Interface.lnk" + DELETE "${startmenu_company}\Stack Manager.lnk" + DELETE "${startmenu_company}\Uninstall ${company}.lnk" + + RMDIR "${startmenu_company}" + + RMDIR /r "$INSTDIR" + ; This should remove the High Fidelity folder in Program Files if it's empty + RMDIR "${install_dir_company}" + + !ifdef unfiles + !include "${unfiles}" + !endif + ; It's good practice to put the registry key removal at the very end + DeleteRegKey HKLM "${uninstkey}" + DeleteRegKey HKLM "${regkey}" + DeleteRegKey HKCR 'hifi' +SectionEnd \ No newline at end of file