From c1e93b4bf1d854788b3ce468a1cdede71fe88b4f Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 16 Sep 2013 12:26:06 -0700 Subject: [PATCH 1/7] first cut at making VoxelServer a class and library --- libraries/voxel-server-library/CMakeLists.txt | 27 ++ .../voxel-server-library}/src/NodeWatcher.cpp | 0 .../voxel-server-library}/src/NodeWatcher.h | 0 .../src/VoxelNodeData.cpp | 0 .../voxel-server-library}/src/VoxelNodeData.h | 0 .../src/VoxelPersistThread.cpp | 0 .../src/VoxelPersistThread.h | 0 .../src/VoxelSendThread.cpp | 0 .../src/VoxelSendThread.h | 0 .../voxel-server-library/src/VoxelServer.cpp | 347 ++++++++++++++++++ .../voxel-server-library}/src/VoxelServer.h | 14 + .../src/VoxelServerPacketProcessor.cpp | 0 .../src/VoxelServerPacketProcessor.h | 0 voxel-server/CMakeLists.txt | 2 + voxel-server/src/main.cpp | 329 +---------------- 15 files changed, 393 insertions(+), 326 deletions(-) create mode 100644 libraries/voxel-server-library/CMakeLists.txt rename {voxel-server => libraries/voxel-server-library}/src/NodeWatcher.cpp (100%) rename {voxel-server => libraries/voxel-server-library}/src/NodeWatcher.h (100%) rename {voxel-server => libraries/voxel-server-library}/src/VoxelNodeData.cpp (100%) rename {voxel-server => libraries/voxel-server-library}/src/VoxelNodeData.h (100%) rename {voxel-server => libraries/voxel-server-library}/src/VoxelPersistThread.cpp (100%) rename {voxel-server => libraries/voxel-server-library}/src/VoxelPersistThread.h (100%) rename {voxel-server => libraries/voxel-server-library}/src/VoxelSendThread.cpp (100%) rename {voxel-server => libraries/voxel-server-library}/src/VoxelSendThread.h (100%) create mode 100644 libraries/voxel-server-library/src/VoxelServer.cpp rename {voxel-server => libraries/voxel-server-library}/src/VoxelServer.h (84%) rename {voxel-server => libraries/voxel-server-library}/src/VoxelServerPacketProcessor.cpp (100%) rename {voxel-server => libraries/voxel-server-library}/src/VoxelServerPacketProcessor.h (100%) diff --git a/libraries/voxel-server-library/CMakeLists.txt b/libraries/voxel-server-library/CMakeLists.txt new file mode 100644 index 0000000000..8612f63c24 --- /dev/null +++ b/libraries/voxel-server-library/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 2.8) + +set(ROOT_DIR ../..) +set(MACRO_DIR ${ROOT_DIR}/cmake/macros) + +# setup for find modules +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/modules/") + +set(TARGET_NAME voxel-server-library) + +find_package(Qt5Widgets REQUIRED) + +include(${MACRO_DIR}/SetupHifiLibrary.cmake) +setup_hifi_library(${TARGET_NAME}) + +qt5_use_modules(${TARGET_NAME} Widgets) + +include(${MACRO_DIR}/IncludeGLM.cmake) +include_glm(${TARGET_NAME} ${ROOT_DIR}) + +include(${MACRO_DIR}/LinkHifiLibrary.cmake) +link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR}) + +# link ZLIB +find_package(ZLIB) +include_directories(${ZLIB_INCLUDE_DIRS}) +target_link_libraries(${TARGET_NAME} ${ZLIB_LIBRARIES}) diff --git a/voxel-server/src/NodeWatcher.cpp b/libraries/voxel-server-library/src/NodeWatcher.cpp similarity index 100% rename from voxel-server/src/NodeWatcher.cpp rename to libraries/voxel-server-library/src/NodeWatcher.cpp diff --git a/voxel-server/src/NodeWatcher.h b/libraries/voxel-server-library/src/NodeWatcher.h similarity index 100% rename from voxel-server/src/NodeWatcher.h rename to libraries/voxel-server-library/src/NodeWatcher.h diff --git a/voxel-server/src/VoxelNodeData.cpp b/libraries/voxel-server-library/src/VoxelNodeData.cpp similarity index 100% rename from voxel-server/src/VoxelNodeData.cpp rename to libraries/voxel-server-library/src/VoxelNodeData.cpp diff --git a/voxel-server/src/VoxelNodeData.h b/libraries/voxel-server-library/src/VoxelNodeData.h similarity index 100% rename from voxel-server/src/VoxelNodeData.h rename to libraries/voxel-server-library/src/VoxelNodeData.h diff --git a/voxel-server/src/VoxelPersistThread.cpp b/libraries/voxel-server-library/src/VoxelPersistThread.cpp similarity index 100% rename from voxel-server/src/VoxelPersistThread.cpp rename to libraries/voxel-server-library/src/VoxelPersistThread.cpp diff --git a/voxel-server/src/VoxelPersistThread.h b/libraries/voxel-server-library/src/VoxelPersistThread.h similarity index 100% rename from voxel-server/src/VoxelPersistThread.h rename to libraries/voxel-server-library/src/VoxelPersistThread.h diff --git a/voxel-server/src/VoxelSendThread.cpp b/libraries/voxel-server-library/src/VoxelSendThread.cpp similarity index 100% rename from voxel-server/src/VoxelSendThread.cpp rename to libraries/voxel-server-library/src/VoxelSendThread.cpp diff --git a/voxel-server/src/VoxelSendThread.h b/libraries/voxel-server-library/src/VoxelSendThread.h similarity index 100% rename from voxel-server/src/VoxelSendThread.h rename to libraries/voxel-server-library/src/VoxelSendThread.h diff --git a/libraries/voxel-server-library/src/VoxelServer.cpp b/libraries/voxel-server-library/src/VoxelServer.cpp new file mode 100644 index 0000000000..c4633ee1fe --- /dev/null +++ b/libraries/voxel-server-library/src/VoxelServer.cpp @@ -0,0 +1,347 @@ +// +// VoxelServer.cpp +// hifi +// +// Created by Brad Hefta-Gaub on 9/16/13. +// Copyright (c) 2013 HighFidelity, Inc. All rights reserved. +// + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include "VoxelNodeData.h" +#include +#include +#include +#include +#include + +#include "NodeWatcher.h" +#include "VoxelPersistThread.h" +#include "VoxelSendThread.h" +#include "VoxelServerPacketProcessor.h" + +#ifdef _WIN32 +#include "Syssocket.h" +#include "Systime.h" +#else +#include +#include +#include +#endif + +#include "VoxelServer.h" + +const char* LOCAL_VOXELS_PERSIST_FILE = "resources/voxels.svo"; +const char* VOXELS_PERSIST_FILE = "/etc/highfidelity/voxel-server/resources/voxels.svo"; +char voxelPersistFilename[MAX_FILENAME_LENGTH]; +int PACKETS_PER_CLIENT_PER_INTERVAL = 10; +VoxelTree serverTree(true); // this IS a reaveraging tree +bool wantVoxelPersist = true; +bool wantLocalDomain = false; +bool debugVoxelSending = false; +bool shouldShowAnimationDebug = false; +bool displayVoxelStats = false; +bool debugVoxelReceiving = false; +bool sendEnvironments = true; +bool sendMinimalEnvironment = false; +bool dumpVoxelsOnMove = false; +EnvironmentData environmentData[3]; +int receivedPacketCount = 0; +JurisdictionMap* jurisdiction = NULL; +JurisdictionSender* jurisdictionSender = NULL; +VoxelServerPacketProcessor* voxelServerPacketProcessor = NULL; +VoxelPersistThread* voxelPersistThread = NULL; +pthread_mutex_t treeLock; +NodeWatcher nodeWatcher; // used to cleanup AGENT data when agents are killed + +int VoxelServer::_argc = 0; +char** VoxelServer::_argv = NULL; + +void attachVoxelNodeDataToNode(Node* newNode) { + if (newNode->getLinkedData() == NULL) { + newNode->setLinkedData(new VoxelNodeData(newNode)); + } +} + +void VoxelServer::setArguments(int argc, char** argv) { + _argc = argc; + _argv = argv; +} + + +//int main(int argc, const char * argv[]) { +void VoxelServer::run() { + pthread_mutex_init(&::treeLock, NULL); + + qInstallMessageHandler(sharedMessageHandler); + + int listenPort = VOXEL_LISTEN_PORT; + // Check to see if the user passed in a command line option for setting listen port + const char* PORT_PARAMETER = "--port"; + const char* portParameter = getCmdOption(_argc, (const char*[])_argv, PORT_PARAMETER); + if (portParameter) { + listenPort = atoi(portParameter); + if (listenPort < 1) { + listenPort = VOXEL_LISTEN_PORT; + } + printf("portParameter=%s listenPort=%d\n", portParameter, listenPort); + } + + const char* JURISDICTION_FILE = "--jurisdictionFile"; + const char* jurisdictionFile = getCmdOption(_argc, _argv, JURISDICTION_FILE); + if (jurisdictionFile) { + printf("jurisdictionFile=%s\n", jurisdictionFile); + + printf("about to readFromFile().... jurisdictionFile=%s\n", jurisdictionFile); + jurisdiction = new JurisdictionMap(jurisdictionFile); + printf("after readFromFile().... jurisdictionFile=%s\n", jurisdictionFile); + } else { + const char* JURISDICTION_ROOT = "--jurisdictionRoot"; + const char* jurisdictionRoot = getCmdOption(_argc, _argv, JURISDICTION_ROOT); + if (jurisdictionRoot) { + printf("jurisdictionRoot=%s\n", jurisdictionRoot); + } + + const char* JURISDICTION_ENDNODES = "--jurisdictionEndNodes"; + const char* jurisdictionEndNodes = getCmdOption(_argc, _argv, JURISDICTION_ENDNODES); + if (jurisdictionEndNodes) { + printf("jurisdictionEndNodes=%s\n", jurisdictionEndNodes); + } + + if (jurisdictionRoot || jurisdictionEndNodes) { + ::jurisdiction = new JurisdictionMap(jurisdictionRoot, jurisdictionEndNodes); + } + } + + // should we send environments? Default is yes, but this command line suppresses sending + const char* DUMP_VOXELS_ON_MOVE = "--dumpVoxelsOnMove"; + ::dumpVoxelsOnMove = cmdOptionExists(_argc, _argv, DUMP_VOXELS_ON_MOVE); + printf("dumpVoxelsOnMove=%s\n", debug::valueOf(::dumpVoxelsOnMove)); + + // should we send environments? Default is yes, but this command line suppresses sending + const char* DONT_SEND_ENVIRONMENTS = "--dontSendEnvironments"; + bool dontSendEnvironments = getCmdOption(_argc, _argv, DONT_SEND_ENVIRONMENTS); + if (dontSendEnvironments) { + printf("Sending environments suppressed...\n"); + ::sendEnvironments = false; + } else { + // should we send environments? Default is yes, but this command line suppresses sending + const char* MINIMAL_ENVIRONMENT = "--MinimalEnvironment"; + ::sendMinimalEnvironment = getCmdOption(_argc, _argv, MINIMAL_ENVIRONMENT); + printf("Using Minimal Environment=%s\n", debug::valueOf(::sendMinimalEnvironment)); + } + printf("Sending environments=%s\n", debug::valueOf(::sendEnvironments)); + + NodeList* nodeList = NodeList::createInstance(NODE_TYPE_VOXEL_SERVER, listenPort); + setvbuf(stdout, NULL, _IOLBF, 0); + + // tell our NodeList about our desire to get notifications + nodeList->addHook(&nodeWatcher); + + // Handle Local Domain testing with the --local command line + const char* local = "--local"; + ::wantLocalDomain = getCmdOption(_argc, _argv,local); + if (::wantLocalDomain) { + printf("Local Domain MODE!\n"); + nodeList->setDomainIPToLocalhost(); + } else { + const char* domainIP = getCmdOption(_argc, _argv, "--domain"); + if (domainIP) { + NodeList::getInstance()->setDomainHostname(domainIP); + } + } + + nodeList->linkedDataCreateCallback = &attachVoxelNodeDataToNode; + nodeList->startSilentNodeRemovalThread(); + + srand((unsigned)time(0)); + + const char* DISPLAY_VOXEL_STATS = "--displayVoxelStats"; + ::displayVoxelStats = getCmdOption(_argc, _argv, DISPLAY_VOXEL_STATS); + printf("displayVoxelStats=%s\n", debug::valueOf(::displayVoxelStats)); + + const char* DEBUG_VOXEL_SENDING = "--debugVoxelSending"; + ::debugVoxelSending = getCmdOption(_argc, _argv, DEBUG_VOXEL_SENDING); + printf("debugVoxelSending=%s\n", debug::valueOf(::debugVoxelSending)); + + const char* DEBUG_VOXEL_RECEIVING = "--debugVoxelReceiving"; + ::debugVoxelReceiving = getCmdOption(_argc, _argv, DEBUG_VOXEL_RECEIVING); + printf("debugVoxelReceiving=%s\n", debug::valueOf(::debugVoxelReceiving)); + + const char* WANT_ANIMATION_DEBUG = "--shouldShowAnimationDebug"; + ::shouldShowAnimationDebug = getCmdOption(_argc, _argv, WANT_ANIMATION_DEBUG); + printf("shouldShowAnimationDebug=%s\n", debug::valueOf(::shouldShowAnimationDebug)); + + // By default we will voxel persist, if you want to disable this, then pass in this parameter + const char* NO_VOXEL_PERSIST = "--NoVoxelPersist"; + if ( getCmdOption(_argc, _argv, NO_VOXEL_PERSIST)) { + ::wantVoxelPersist = false; + } + printf("wantVoxelPersist=%s\n", debug::valueOf(::wantVoxelPersist)); + + // if we want Voxel Persistence, load the local file now... + bool persistantFileRead = false; + if (::wantVoxelPersist) { + + // Check to see if the user passed in a command line option for setting packet send rate + const char* VOXELS_PERSIST_FILENAME = "--voxelsPersistFilename"; + const char* voxelsPersistFilenameParameter = getCmdOption(_argc, _argv, VOXELS_PERSIST_FILENAME); + if (voxelsPersistFilenameParameter) { + strcpy(voxelPersistFilename, voxelsPersistFilenameParameter); + } else { + strcpy(voxelPersistFilename, ::wantLocalDomain ? LOCAL_VOXELS_PERSIST_FILE : VOXELS_PERSIST_FILE); + } + + printf("loading voxels from file: %s...\n", voxelPersistFilename); + + persistantFileRead = ::serverTree.readFromSVOFile(::voxelPersistFilename); + if (persistantFileRead) { + PerformanceWarning warn(::shouldShowAnimationDebug, + "persistVoxelsWhenDirty() - reaverageVoxelColors()", ::shouldShowAnimationDebug); + + // after done inserting all these voxels, then reaverage colors + serverTree.reaverageVoxelColors(serverTree.rootNode); + printf("Voxels reAveraged\n"); + } + + ::serverTree.clearDirtyBit(); // the tree is clean since we just loaded it + printf("DONE loading voxels from file... fileRead=%s\n", debug::valueOf(persistantFileRead)); + unsigned long nodeCount = ::serverTree.rootNode->getSubTreeNodeCount(); + unsigned long internalNodeCount = ::serverTree.rootNode->getSubTreeInternalNodeCount(); + unsigned long leafNodeCount = ::serverTree.rootNode->getSubTreeLeafNodeCount(); + printf("Nodes after loading scene %lu nodes %lu internal %lu leaves\n", nodeCount, internalNodeCount, leafNodeCount); + + // now set up VoxelPersistThread + ::voxelPersistThread = new VoxelPersistThread(&::serverTree, ::voxelPersistFilename); + if (::voxelPersistThread) { + ::voxelPersistThread->initialize(true); + } + } + + // Check to see if the user passed in a command line option for loading an old style local + // Voxel File. If so, load it now. This is not the same as a voxel persist file + const char* INPUT_FILE = "-i"; + const char* voxelsFilename = getCmdOption(_argc, _argv, INPUT_FILE); + if (voxelsFilename) { + serverTree.readFromSVOFile(voxelsFilename); + } + + // Check to see if the user passed in a command line option for setting packet send rate + const char* PACKETS_PER_SECOND = "--packetsPerSecond"; + const char* packetsPerSecond = getCmdOption(_argc, _argv, PACKETS_PER_SECOND); + if (packetsPerSecond) { + PACKETS_PER_CLIENT_PER_INTERVAL = atoi(packetsPerSecond)/INTERVALS_PER_SECOND; + if (PACKETS_PER_CLIENT_PER_INTERVAL < 1) { + PACKETS_PER_CLIENT_PER_INTERVAL = 1; + } + printf("packetsPerSecond=%s PACKETS_PER_CLIENT_PER_INTERVAL=%d\n", packetsPerSecond, PACKETS_PER_CLIENT_PER_INTERVAL); + } + + // for now, initialize the environments with fixed values + environmentData[1].setID(1); + environmentData[1].setGravity(1.0f); + environmentData[1].setAtmosphereCenter(glm::vec3(0.5, 0.5, (0.25 - 0.06125)) * (float)TREE_SCALE); + environmentData[1].setAtmosphereInnerRadius(0.030625f * TREE_SCALE); + environmentData[1].setAtmosphereOuterRadius(0.030625f * TREE_SCALE * 1.05f); + environmentData[2].setID(2); + environmentData[2].setGravity(1.0f); + environmentData[2].setAtmosphereCenter(glm::vec3(0.5f, 0.5f, 0.5f) * (float)TREE_SCALE); + environmentData[2].setAtmosphereInnerRadius(0.1875f * TREE_SCALE); + environmentData[2].setAtmosphereOuterRadius(0.1875f * TREE_SCALE * 1.05f); + environmentData[2].setScatteringWavelengths(glm::vec3(0.475f, 0.570f, 0.650f)); // swaps red and blue + + sockaddr senderAddress; + + unsigned char *packetData = new unsigned char[MAX_PACKET_SIZE]; + ssize_t packetLength; + + timeval lastDomainServerCheckIn = {}; + + // set up our jurisdiction broadcaster... + ::jurisdictionSender = new JurisdictionSender(::jurisdiction); + if (::jurisdictionSender) { + ::jurisdictionSender->initialize(true); + } + + // set up our VoxelServerPacketProcessor + ::voxelServerPacketProcessor = new VoxelServerPacketProcessor(); + if (::voxelServerPacketProcessor) { + ::voxelServerPacketProcessor->initialize(true); + } + + // loop to send to nodes requesting data + while (true) { + + // send a check in packet to the domain server if DOMAIN_SERVER_CHECK_IN_USECS has elapsed + if (usecTimestampNow() - usecTimestamp(&lastDomainServerCheckIn) >= DOMAIN_SERVER_CHECK_IN_USECS) { + gettimeofday(&lastDomainServerCheckIn, NULL); + NodeList::getInstance()->sendDomainServerCheckIn(); + } + + if (nodeList->getNodeSocket()->receive(&senderAddress, packetData, &packetLength) && + packetVersionMatch(packetData)) { + + int numBytesPacketHeader = numBytesForPacketHeader(packetData); + + if (packetData[0] == PACKET_TYPE_HEAD_DATA) { + // If we got a PACKET_TYPE_HEAD_DATA, then we're talking to an NODE_TYPE_AVATAR, and we + // need to make sure we have it in our nodeList. + uint16_t nodeID = 0; + unpackNodeId(packetData + numBytesPacketHeader, &nodeID); + Node* node = NodeList::getInstance()->addOrUpdateNode(&senderAddress, + &senderAddress, + NODE_TYPE_AGENT, + nodeID); + + NodeList::getInstance()->updateNodeWithData(node, packetData, packetLength); + } else if (packetData[0] == PACKET_TYPE_PING) { + // If the packet is a ping, let processNodeData handle it. + NodeList::getInstance()->processNodeData(&senderAddress, packetData, packetLength); + } else if (packetData[0] == PACKET_TYPE_DOMAIN) { + NodeList::getInstance()->processNodeData(&senderAddress, packetData, packetLength); + } else if (packetData[0] == PACKET_TYPE_VOXEL_JURISDICTION_REQUEST) { + if (::jurisdictionSender) { + ::jurisdictionSender->queueReceivedPacket(senderAddress, packetData, packetLength); + } + } else if (::voxelServerPacketProcessor) { + ::voxelServerPacketProcessor->queueReceivedPacket(senderAddress, packetData, packetLength); + } else { + printf("unknown packet ignored... packetData[0]=%c\n", packetData[0]); + } + } + } + + if (::jurisdiction) { + delete ::jurisdiction; + } + + 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); + + pthread_mutex_destroy(&::treeLock); +} + + diff --git a/voxel-server/src/VoxelServer.h b/libraries/voxel-server-library/src/VoxelServer.h similarity index 84% rename from voxel-server/src/VoxelServer.h rename to libraries/voxel-server-library/src/VoxelServer.h index 0f4c8577db..a778e96296 100644 --- a/voxel-server/src/VoxelServer.h +++ b/libraries/voxel-server-library/src/VoxelServer.h @@ -53,6 +53,20 @@ extern JurisdictionSender* jurisdictionSender; extern VoxelServerPacketProcessor* voxelServerPacketProcessor; extern pthread_mutex_t treeLock; +/// Handles assignments of type VoxelServer - sending voxels to various clients. +class VoxelServer { +public: + /// runs the voxel server assignment + static void run(); + + /// allows setting of run arguments + static void setArguments(int argc, char** argv); + +private: + static int _argc; + static char** _argv; +}; + #endif // __voxel_server__VoxelServer__ diff --git a/voxel-server/src/VoxelServerPacketProcessor.cpp b/libraries/voxel-server-library/src/VoxelServerPacketProcessor.cpp similarity index 100% rename from voxel-server/src/VoxelServerPacketProcessor.cpp rename to libraries/voxel-server-library/src/VoxelServerPacketProcessor.cpp diff --git a/voxel-server/src/VoxelServerPacketProcessor.h b/libraries/voxel-server-library/src/VoxelServerPacketProcessor.h similarity index 100% rename from voxel-server/src/VoxelServerPacketProcessor.h rename to libraries/voxel-server-library/src/VoxelServerPacketProcessor.h diff --git a/voxel-server/CMakeLists.txt b/voxel-server/CMakeLists.txt index c401a8033c..f759db0d89 100644 --- a/voxel-server/CMakeLists.txt +++ b/voxel-server/CMakeLists.txt @@ -26,3 +26,5 @@ link_hifi_library(voxels ${TARGET_NAME} ${ROOT_DIR}) # link in the hifi avatars library link_hifi_library(avatars ${TARGET_NAME} ${ROOT_DIR}) +# link in the hifi voxel-server-library +link_hifi_library(voxel-server-library ${TARGET_NAME} ${ROOT_DIR}) diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index 56ea5003e1..0e26de1f52 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -6,334 +6,11 @@ // Copyright (c) 2012 High Fidelity, Inc. All rights reserved. // -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include "VoxelNodeData.h" -#include -#include -#include -#include -#include - -#include "NodeWatcher.h" -#include "VoxelPersistThread.h" -#include "VoxelSendThread.h" -#include "VoxelServerPacketProcessor.h" - -#ifdef _WIN32 -#include "Syssocket.h" -#include "Systime.h" -#else -#include -#include -#include -#endif - -#include "VoxelServer.h" - -const char* LOCAL_VOXELS_PERSIST_FILE = "resources/voxels.svo"; -const char* VOXELS_PERSIST_FILE = "/etc/highfidelity/voxel-server/resources/voxels.svo"; -char voxelPersistFilename[MAX_FILENAME_LENGTH]; -int PACKETS_PER_CLIENT_PER_INTERVAL = 10; -VoxelTree serverTree(true); // this IS a reaveraging tree -bool wantVoxelPersist = true; -bool wantLocalDomain = false; -bool debugVoxelSending = false; -bool shouldShowAnimationDebug = false; -bool displayVoxelStats = false; -bool debugVoxelReceiving = false; -bool sendEnvironments = true; -bool sendMinimalEnvironment = false; -bool dumpVoxelsOnMove = false; -EnvironmentData environmentData[3]; -int receivedPacketCount = 0; -JurisdictionMap* jurisdiction = NULL; -JurisdictionSender* jurisdictionSender = NULL; -VoxelServerPacketProcessor* voxelServerPacketProcessor = NULL; -VoxelPersistThread* voxelPersistThread = NULL; -pthread_mutex_t treeLock; -NodeWatcher nodeWatcher; // used to cleanup AGENT data when agents are killed - -void attachVoxelNodeDataToNode(Node* newNode) { - if (newNode->getLinkedData() == NULL) { - newNode->setLinkedData(new VoxelNodeData(newNode)); - } -} +#include int main(int argc, const char * argv[]) { - pthread_mutex_init(&::treeLock, NULL); - - qInstallMessageHandler(sharedMessageHandler); - - int listenPort = VOXEL_LISTEN_PORT; - // Check to see if the user passed in a command line option for setting listen port - const char* PORT_PARAMETER = "--port"; - const char* portParameter = getCmdOption(argc, argv, PORT_PARAMETER); - if (portParameter) { - listenPort = atoi(portParameter); - if (listenPort < 1) { - listenPort = VOXEL_LISTEN_PORT; - } - printf("portParameter=%s listenPort=%d\n", portParameter, listenPort); - } - - const char* JURISDICTION_FILE = "--jurisdictionFile"; - const char* jurisdictionFile = getCmdOption(argc, argv, JURISDICTION_FILE); - if (jurisdictionFile) { - printf("jurisdictionFile=%s\n", jurisdictionFile); - - printf("about to readFromFile().... jurisdictionFile=%s\n", jurisdictionFile); - jurisdiction = new JurisdictionMap(jurisdictionFile); - printf("after readFromFile().... jurisdictionFile=%s\n", jurisdictionFile); - } else { - const char* JURISDICTION_ROOT = "--jurisdictionRoot"; - const char* jurisdictionRoot = getCmdOption(argc, argv, JURISDICTION_ROOT); - if (jurisdictionRoot) { - printf("jurisdictionRoot=%s\n", jurisdictionRoot); - } - - const char* JURISDICTION_ENDNODES = "--jurisdictionEndNodes"; - const char* jurisdictionEndNodes = getCmdOption(argc, argv, JURISDICTION_ENDNODES); - if (jurisdictionEndNodes) { - printf("jurisdictionEndNodes=%s\n", jurisdictionEndNodes); - } - - if (jurisdictionRoot || jurisdictionEndNodes) { - ::jurisdiction = new JurisdictionMap(jurisdictionRoot, jurisdictionEndNodes); - } - } - - // should we send environments? Default is yes, but this command line suppresses sending - const char* DUMP_VOXELS_ON_MOVE = "--dumpVoxelsOnMove"; - ::dumpVoxelsOnMove = cmdOptionExists(argc, argv, DUMP_VOXELS_ON_MOVE); - printf("dumpVoxelsOnMove=%s\n", debug::valueOf(::dumpVoxelsOnMove)); - - // should we send environments? Default is yes, but this command line suppresses sending - const char* DONT_SEND_ENVIRONMENTS = "--dontSendEnvironments"; - bool dontSendEnvironments = cmdOptionExists(argc, argv, DONT_SEND_ENVIRONMENTS); - if (dontSendEnvironments) { - printf("Sending environments suppressed...\n"); - ::sendEnvironments = false; - } else { - // should we send environments? Default is yes, but this command line suppresses sending - const char* MINIMAL_ENVIRONMENT = "--MinimalEnvironment"; - ::sendMinimalEnvironment = cmdOptionExists(argc, argv, MINIMAL_ENVIRONMENT); - printf("Using Minimal Environment=%s\n", debug::valueOf(::sendMinimalEnvironment)); - } - printf("Sending environments=%s\n", debug::valueOf(::sendEnvironments)); - - NodeList* nodeList = NodeList::createInstance(NODE_TYPE_VOXEL_SERVER, listenPort); - setvbuf(stdout, NULL, _IOLBF, 0); - - // tell our NodeList about our desire to get notifications - nodeList->addHook(&nodeWatcher); - - // Handle Local Domain testing with the --local command line - const char* local = "--local"; - ::wantLocalDomain = cmdOptionExists(argc, argv,local); - if (::wantLocalDomain) { - printf("Local Domain MODE!\n"); - nodeList->setDomainIPToLocalhost(); - } else { - const char* domainIP = getCmdOption(argc, argv, "--domain"); - if (domainIP) { - NodeList::getInstance()->setDomainHostname(domainIP); - } - } - - nodeList->linkedDataCreateCallback = &attachVoxelNodeDataToNode; - nodeList->startSilentNodeRemovalThread(); - - srand((unsigned)time(0)); - - const char* DISPLAY_VOXEL_STATS = "--displayVoxelStats"; - ::displayVoxelStats = cmdOptionExists(argc, argv, DISPLAY_VOXEL_STATS); - printf("displayVoxelStats=%s\n", debug::valueOf(::displayVoxelStats)); - - const char* DEBUG_VOXEL_SENDING = "--debugVoxelSending"; - ::debugVoxelSending = cmdOptionExists(argc, argv, DEBUG_VOXEL_SENDING); - printf("debugVoxelSending=%s\n", debug::valueOf(::debugVoxelSending)); - - const char* DEBUG_VOXEL_RECEIVING = "--debugVoxelReceiving"; - ::debugVoxelReceiving = cmdOptionExists(argc, argv, DEBUG_VOXEL_RECEIVING); - printf("debugVoxelReceiving=%s\n", debug::valueOf(::debugVoxelReceiving)); - - const char* WANT_ANIMATION_DEBUG = "--shouldShowAnimationDebug"; - ::shouldShowAnimationDebug = cmdOptionExists(argc, argv, WANT_ANIMATION_DEBUG); - printf("shouldShowAnimationDebug=%s\n", debug::valueOf(::shouldShowAnimationDebug)); - - // By default we will voxel persist, if you want to disable this, then pass in this parameter - const char* NO_VOXEL_PERSIST = "--NoVoxelPersist"; - if (cmdOptionExists(argc, argv, NO_VOXEL_PERSIST)) { - ::wantVoxelPersist = false; - } - printf("wantVoxelPersist=%s\n", debug::valueOf(::wantVoxelPersist)); - - // if we want Voxel Persistence, load the local file now... - bool persistantFileRead = false; - if (::wantVoxelPersist) { - - // Check to see if the user passed in a command line option for setting packet send rate - const char* VOXELS_PERSIST_FILENAME = "--voxelsPersistFilename"; - const char* voxelsPersistFilenameParameter = getCmdOption(argc, argv, VOXELS_PERSIST_FILENAME); - if (voxelsPersistFilenameParameter) { - strcpy(voxelPersistFilename, voxelsPersistFilenameParameter); - } else { - strcpy(voxelPersistFilename, ::wantLocalDomain ? LOCAL_VOXELS_PERSIST_FILE : VOXELS_PERSIST_FILE); - } - - printf("loading voxels from file: %s...\n", voxelPersistFilename); - - persistantFileRead = ::serverTree.readFromSVOFile(::voxelPersistFilename); - if (persistantFileRead) { - PerformanceWarning warn(::shouldShowAnimationDebug, - "persistVoxelsWhenDirty() - reaverageVoxelColors()", ::shouldShowAnimationDebug); - - // after done inserting all these voxels, then reaverage colors - serverTree.reaverageVoxelColors(serverTree.rootNode); - printf("Voxels reAveraged\n"); - } - - ::serverTree.clearDirtyBit(); // the tree is clean since we just loaded it - printf("DONE loading voxels from file... fileRead=%s\n", debug::valueOf(persistantFileRead)); - unsigned long nodeCount = ::serverTree.rootNode->getSubTreeNodeCount(); - unsigned long internalNodeCount = ::serverTree.rootNode->getSubTreeInternalNodeCount(); - unsigned long leafNodeCount = ::serverTree.rootNode->getSubTreeLeafNodeCount(); - printf("Nodes after loading scene %lu nodes %lu internal %lu leaves\n", nodeCount, internalNodeCount, leafNodeCount); - - // now set up VoxelPersistThread - ::voxelPersistThread = new VoxelPersistThread(&::serverTree, ::voxelPersistFilename); - if (::voxelPersistThread) { - ::voxelPersistThread->initialize(true); - } - } - - // Check to see if the user passed in a command line option for loading an old style local - // Voxel File. If so, load it now. This is not the same as a voxel persist file - const char* INPUT_FILE = "-i"; - const char* voxelsFilename = getCmdOption(argc, argv, INPUT_FILE); - if (voxelsFilename) { - serverTree.readFromSVOFile(voxelsFilename); - } - - // Check to see if the user passed in a command line option for setting packet send rate - const char* PACKETS_PER_SECOND = "--packetsPerSecond"; - const char* packetsPerSecond = getCmdOption(argc, argv, PACKETS_PER_SECOND); - if (packetsPerSecond) { - PACKETS_PER_CLIENT_PER_INTERVAL = atoi(packetsPerSecond)/INTERVALS_PER_SECOND; - if (PACKETS_PER_CLIENT_PER_INTERVAL < 1) { - PACKETS_PER_CLIENT_PER_INTERVAL = 1; - } - printf("packetsPerSecond=%s PACKETS_PER_CLIENT_PER_INTERVAL=%d\n", packetsPerSecond, PACKETS_PER_CLIENT_PER_INTERVAL); - } - - // for now, initialize the environments with fixed values - environmentData[1].setID(1); - environmentData[1].setGravity(1.0f); - environmentData[1].setAtmosphereCenter(glm::vec3(0.5, 0.5, (0.25 - 0.06125)) * (float)TREE_SCALE); - environmentData[1].setAtmosphereInnerRadius(0.030625f * TREE_SCALE); - environmentData[1].setAtmosphereOuterRadius(0.030625f * TREE_SCALE * 1.05f); - environmentData[2].setID(2); - environmentData[2].setGravity(1.0f); - environmentData[2].setAtmosphereCenter(glm::vec3(0.5f, 0.5f, 0.5f) * (float)TREE_SCALE); - environmentData[2].setAtmosphereInnerRadius(0.1875f * TREE_SCALE); - environmentData[2].setAtmosphereOuterRadius(0.1875f * TREE_SCALE * 1.05f); - environmentData[2].setScatteringWavelengths(glm::vec3(0.475f, 0.570f, 0.650f)); // swaps red and blue - - sockaddr senderAddress; - - unsigned char *packetData = new unsigned char[MAX_PACKET_SIZE]; - ssize_t packetLength; - - timeval lastDomainServerCheckIn = {}; - - // set up our jurisdiction broadcaster... - ::jurisdictionSender = new JurisdictionSender(::jurisdiction); - if (::jurisdictionSender) { - ::jurisdictionSender->initialize(true); - } - - // set up our VoxelServerPacketProcessor - ::voxelServerPacketProcessor = new VoxelServerPacketProcessor(); - if (::voxelServerPacketProcessor) { - ::voxelServerPacketProcessor->initialize(true); - } - - // loop to send to nodes requesting data - while (true) { - - // send a check in packet to the domain server if DOMAIN_SERVER_CHECK_IN_USECS has elapsed - if (usecTimestampNow() - usecTimestamp(&lastDomainServerCheckIn) >= DOMAIN_SERVER_CHECK_IN_USECS) { - gettimeofday(&lastDomainServerCheckIn, NULL); - NodeList::getInstance()->sendDomainServerCheckIn(); - } - - if (nodeList->getNodeSocket()->receive(&senderAddress, packetData, &packetLength) && - packetVersionMatch(packetData)) { - - int numBytesPacketHeader = numBytesForPacketHeader(packetData); - - if (packetData[0] == PACKET_TYPE_HEAD_DATA) { - // If we got a PACKET_TYPE_HEAD_DATA, then we're talking to an NODE_TYPE_AVATAR, and we - // need to make sure we have it in our nodeList. - uint16_t nodeID = 0; - unpackNodeId(packetData + numBytesPacketHeader, &nodeID); - Node* node = NodeList::getInstance()->addOrUpdateNode(&senderAddress, - &senderAddress, - NODE_TYPE_AGENT, - nodeID); - - NodeList::getInstance()->updateNodeWithData(node, packetData, packetLength); - } else if (packetData[0] == PACKET_TYPE_PING) { - // If the packet is a ping, let processNodeData handle it. - NodeList::getInstance()->processNodeData(&senderAddress, packetData, packetLength); - } else if (packetData[0] == PACKET_TYPE_DOMAIN) { - NodeList::getInstance()->processNodeData(&senderAddress, packetData, packetLength); - } else if (packetData[0] == PACKET_TYPE_VOXEL_JURISDICTION_REQUEST) { - if (::jurisdictionSender) { - ::jurisdictionSender->queueReceivedPacket(senderAddress, packetData, packetLength); - } - } else if (::voxelServerPacketProcessor) { - ::voxelServerPacketProcessor->queueReceivedPacket(senderAddress, packetData, packetLength); - } else { - printf("unknown packet ignored... packetData[0]=%c\n", packetData[0]); - } - } - } - - if (::jurisdiction) { - delete ::jurisdiction; - } - - 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); - - pthread_mutex_destroy(&::treeLock); - - return 0; + VoxelServer::setArguments(argc, argv[]); + VoxelServer::run(); } From 023892a4d00b911e19330051d36989793fc371f6 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 16 Sep 2013 16:02:05 -0700 Subject: [PATCH 2/7] command line options --- libraries/voxel-server-library/src/VoxelServer.cpp | 6 +++--- libraries/voxel-server-library/src/VoxelServer.h | 2 +- voxel-server/src/main.cpp | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libraries/voxel-server-library/src/VoxelServer.cpp b/libraries/voxel-server-library/src/VoxelServer.cpp index c4633ee1fe..c4f3d77dd9 100644 --- a/libraries/voxel-server-library/src/VoxelServer.cpp +++ b/libraries/voxel-server-library/src/VoxelServer.cpp @@ -63,7 +63,7 @@ pthread_mutex_t treeLock; NodeWatcher nodeWatcher; // used to cleanup AGENT data when agents are killed int VoxelServer::_argc = 0; -char** VoxelServer::_argv = NULL; +const char** VoxelServer::_argv = NULL; void attachVoxelNodeDataToNode(Node* newNode) { if (newNode->getLinkedData() == NULL) { @@ -73,7 +73,7 @@ void attachVoxelNodeDataToNode(Node* newNode) { void VoxelServer::setArguments(int argc, char** argv) { _argc = argc; - _argv = argv; + _argv = const_cast(argv); } @@ -86,7 +86,7 @@ void VoxelServer::run() { int listenPort = VOXEL_LISTEN_PORT; // Check to see if the user passed in a command line option for setting listen port const char* PORT_PARAMETER = "--port"; - const char* portParameter = getCmdOption(_argc, (const char*[])_argv, PORT_PARAMETER); + const char* portParameter = getCmdOption(_argc, _argv, PORT_PARAMETER); if (portParameter) { listenPort = atoi(portParameter); if (listenPort < 1) { diff --git a/libraries/voxel-server-library/src/VoxelServer.h b/libraries/voxel-server-library/src/VoxelServer.h index a778e96296..f9740e8c4b 100644 --- a/libraries/voxel-server-library/src/VoxelServer.h +++ b/libraries/voxel-server-library/src/VoxelServer.h @@ -64,7 +64,7 @@ public: private: static int _argc; - static char** _argv; + static const char** _argv; }; diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index 0e26de1f52..5a21b9fc76 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -9,7 +9,7 @@ #include int main(int argc, const char * argv[]) { - VoxelServer::setArguments(argc, argv[]); + VoxelServer::setArguments(argc, const_cast(argv)); VoxelServer::run(); } From 3f4245d5970cea19446a1a68513f8d6f5f3cc283 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 16 Sep 2013 16:19:24 -0700 Subject: [PATCH 3/7] fix local mode option --- libraries/voxel-server-library/src/VoxelServer.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/libraries/voxel-server-library/src/VoxelServer.cpp b/libraries/voxel-server-library/src/VoxelServer.cpp index c4f3d77dd9..e865037082 100644 --- a/libraries/voxel-server-library/src/VoxelServer.cpp +++ b/libraries/voxel-server-library/src/VoxelServer.cpp @@ -142,16 +142,17 @@ void VoxelServer::run() { NodeList* nodeList = NodeList::createInstance(NODE_TYPE_VOXEL_SERVER, listenPort); setvbuf(stdout, NULL, _IOLBF, 0); - + // tell our NodeList about our desire to get notifications nodeList->addHook(&nodeWatcher); + nodeList->linkedDataCreateCallback = &attachVoxelNodeDataToNode; // Handle Local Domain testing with the --local command line const char* local = "--local"; - ::wantLocalDomain = getCmdOption(_argc, _argv,local); + ::wantLocalDomain = cmdOptionExists(_argc, _argv, local); if (::wantLocalDomain) { printf("Local Domain MODE!\n"); - nodeList->setDomainIPToLocalhost(); + NodeList::getInstance()->setDomainIPToLocalhost(); } else { const char* domainIP = getCmdOption(_argc, _argv, "--domain"); if (domainIP) { @@ -159,9 +160,7 @@ void VoxelServer::run() { } } - nodeList->linkedDataCreateCallback = &attachVoxelNodeDataToNode; nodeList->startSilentNodeRemovalThread(); - srand((unsigned)time(0)); const char* DISPLAY_VOXEL_STATS = "--displayVoxelStats"; From b484951cc2e10570d5ad05c661aa39bf7173a6b5 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 16 Sep 2013 16:30:46 -0700 Subject: [PATCH 4/7] fix build buster? --- libraries/voxel-server-library/CMakeLists.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/libraries/voxel-server-library/CMakeLists.txt b/libraries/voxel-server-library/CMakeLists.txt index 8612f63c24..9eabb95508 100644 --- a/libraries/voxel-server-library/CMakeLists.txt +++ b/libraries/voxel-server-library/CMakeLists.txt @@ -25,3 +25,13 @@ link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR}) find_package(ZLIB) include_directories(${ZLIB_INCLUDE_DIRS}) target_link_libraries(${TARGET_NAME} ${ZLIB_LIBRARIES}) + +# link in the shared library +include(${MACRO_DIR}/LinkHifiLibrary.cmake) +link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR}) + +# link in the hifi voxels library +link_hifi_library(voxels ${TARGET_NAME} ${ROOT_DIR}) + +# link in the hifi avatars library +link_hifi_library(avatars ${TARGET_NAME} ${ROOT_DIR}) From 92fb393e14c932bc28c1ec34db72f93aa8634b31 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 16 Sep 2013 19:34:07 -0700 Subject: [PATCH 5/7] allow standalone voxel-server to specify port and domain, add VoxelServerType to assignment-client --- assignment-client/CMakeLists.txt | 3 +- assignment-client/src/main.cpp | 3 ++ domain-server/src/main.cpp | 20 +++++++ libraries/shared/src/Assignment.h | 1 + .../src/VoxelSendThread.cpp | 3 ++ .../voxel-server-library/src/VoxelServer.cpp | 54 +++++++++---------- .../voxel-server-library/src/VoxelServer.h | 51 +++--------------- .../src/VoxelServerPacketProcessor.cpp | 1 + voxel-server/src/main.cpp | 29 ++++++++++ 9 files changed, 92 insertions(+), 73 deletions(-) diff --git a/assignment-client/CMakeLists.txt b/assignment-client/CMakeLists.txt index 1315b0ce84..39d1eecca6 100644 --- a/assignment-client/CMakeLists.txt +++ b/assignment-client/CMakeLists.txt @@ -23,4 +23,5 @@ include_glm(${TARGET_NAME} ${ROOT_DIR}) include(${MACRO_DIR}/LinkHifiLibrary.cmake) link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR}) link_hifi_library(audio ${TARGET_NAME} ${ROOT_DIR}) -link_hifi_library(avatars ${TARGET_NAME} ${ROOT_DIR}) \ No newline at end of file +link_hifi_library(avatars ${TARGET_NAME} ${ROOT_DIR}) +link_hifi_library(voxel-server-library ${TARGET_NAME} ${ROOT_DIR}) \ No newline at end of file diff --git a/assignment-client/src/main.cpp b/assignment-client/src/main.cpp index 16522a2d87..63943c97b5 100644 --- a/assignment-client/src/main.cpp +++ b/assignment-client/src/main.cpp @@ -22,6 +22,7 @@ #include #include #include +#include const long long ASSIGNMENT_REQUEST_INTERVAL_USECS = 1 * 1000 * 1000; const char PARENT_TARGET_NAME[] = "assignment-client-monitor"; @@ -97,6 +98,8 @@ void childClient() { AudioMixer::run(); } else if (deployedAssignment.getType() == Assignment::AvatarMixerType) { AvatarMixer::run(); + } else if (deployedAssignment.getType() == Assignment::VoxelServerType) { + VoxelServer::run(); } else { // figure out the URL for the script for this agent assignment QString scriptURLString("http://%1:8080/assignment/%2"); diff --git a/domain-server/src/main.cpp b/domain-server/src/main.cpp index 959130833f..bfd0d3da21 100644 --- a/domain-server/src/main.cpp +++ b/domain-server/src/main.cpp @@ -142,6 +142,10 @@ int main(int argc, const char* argv[]) { Assignment avatarMixerAssignment(Assignment::CreateCommand, Assignment::AvatarMixerType, Assignment::LocalLocation); + + Assignment voxelServerAssignment(Assignment::CreateCommand, + Assignment::VoxelServerType, + Assignment::LocalLocation); // construct a local socket to send with our created assignments to the global AS sockaddr_in localSocket = {}; @@ -179,6 +183,22 @@ int main(int argc, const char* argv[]) { qDebug("Missing an audio mixer and assignment not in queue. Adding.\n"); ::assignmentQueue.push_front(&audioMixerAssignment); } + + // Now handle voxel servers, since there could be more than one, we look for any of them + int voxelServerCount = 0; + for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { + if (node->getType() == NODE_TYPE_VOXEL_SERVER) { + voxelServerCount++; + } + } + + if (voxelServerCount == 0 && + std::find(::assignmentQueue.begin(), ::assignmentQueue.end(), &voxelServerAssignment) == ::assignmentQueue.end()) { + qDebug("Missing an Voxel Server and assignment not in queue. Adding.\n"); + ::assignmentQueue.push_front(&voxelServerAssignment); + } + + ::assignmentQueueMutex.unlock(); while (nodeList->getNodeSocket()->receive((sockaddr *)&nodePublicAddress, packetData, &receivedBytes) && diff --git a/libraries/shared/src/Assignment.h b/libraries/shared/src/Assignment.h index 6985f21535..4fdbeed838 100644 --- a/libraries/shared/src/Assignment.h +++ b/libraries/shared/src/Assignment.h @@ -23,6 +23,7 @@ public: AudioMixerType, AvatarMixerType, AgentType, + VoxelServerType, AllTypes }; diff --git a/libraries/voxel-server-library/src/VoxelSendThread.cpp b/libraries/voxel-server-library/src/VoxelSendThread.cpp index 38f8c6f9b8..b9bb861349 100644 --- a/libraries/voxel-server-library/src/VoxelSendThread.cpp +++ b/libraries/voxel-server-library/src/VoxelSendThread.cpp @@ -11,9 +11,12 @@ #include #include #include +#include +extern EnvironmentData environmentData[3]; #include "VoxelSendThread.h" #include "VoxelServer.h" +#include "VoxelServerState.h" VoxelSendThread::VoxelSendThread(uint16_t nodeID) : _nodeID(nodeID) { diff --git a/libraries/voxel-server-library/src/VoxelServer.cpp b/libraries/voxel-server-library/src/VoxelServer.cpp index e865037082..f56232264f 100644 --- a/libraries/voxel-server-library/src/VoxelServer.cpp +++ b/libraries/voxel-server-library/src/VoxelServer.cpp @@ -38,6 +38,7 @@ #endif #include "VoxelServer.h" +#include "VoxelServerState.h" const char* LOCAL_VOXELS_PERSIST_FILE = "resources/voxels.svo"; const char* VOXELS_PERSIST_FILE = "/etc/highfidelity/voxel-server/resources/voxels.svo"; @@ -76,6 +77,21 @@ void VoxelServer::setArguments(int argc, char** argv) { _argv = const_cast(argv); } +void VoxelServer::setupDomainAndPort(const char* domain, int port) { + NodeList::createInstance(NODE_TYPE_VOXEL_SERVER, port); + + // Handle Local Domain testing with the --local command line + const char* local = "--local"; + ::wantLocalDomain = strcmp(domain, local) == 0; + if (::wantLocalDomain) { + printf("Local Domain MODE!\n"); + NodeList::getInstance()->setDomainIPToLocalhost(); + } else { + if (domain) { + NodeList::getInstance()->setDomainHostname(domain); + } + } +} //int main(int argc, const char * argv[]) { void VoxelServer::run() { @@ -83,18 +99,6 @@ void VoxelServer::run() { qInstallMessageHandler(sharedMessageHandler); - int listenPort = VOXEL_LISTEN_PORT; - // Check to see if the user passed in a command line option for setting listen port - const char* PORT_PARAMETER = "--port"; - const char* portParameter = getCmdOption(_argc, _argv, PORT_PARAMETER); - if (portParameter) { - listenPort = atoi(portParameter); - if (listenPort < 1) { - listenPort = VOXEL_LISTEN_PORT; - } - printf("portParameter=%s listenPort=%d\n", portParameter, listenPort); - } - const char* JURISDICTION_FILE = "--jurisdictionFile"; const char* jurisdictionFile = getCmdOption(_argc, _argv, JURISDICTION_FILE); if (jurisdictionFile) { @@ -140,26 +144,15 @@ void VoxelServer::run() { } printf("Sending environments=%s\n", debug::valueOf(::sendEnvironments)); - NodeList* nodeList = NodeList::createInstance(NODE_TYPE_VOXEL_SERVER, listenPort); + NodeList* nodeList = NodeList::getInstance(); + nodeList->setOwnerType(NODE_TYPE_VOXEL_SERVER); + setvbuf(stdout, NULL, _IOLBF, 0); // tell our NodeList about our desire to get notifications nodeList->addHook(&nodeWatcher); nodeList->linkedDataCreateCallback = &attachVoxelNodeDataToNode; - // Handle Local Domain testing with the --local command line - const char* local = "--local"; - ::wantLocalDomain = cmdOptionExists(_argc, _argv, local); - if (::wantLocalDomain) { - printf("Local Domain MODE!\n"); - NodeList::getInstance()->setDomainIPToLocalhost(); - } else { - const char* domainIP = getCmdOption(_argc, _argv, "--domain"); - if (domainIP) { - NodeList::getInstance()->setDomainHostname(domainIP); - } - } - nodeList->startSilentNodeRemovalThread(); srand((unsigned)time(0)); @@ -196,7 +189,8 @@ void VoxelServer::run() { if (voxelsPersistFilenameParameter) { strcpy(voxelPersistFilename, voxelsPersistFilenameParameter); } else { - strcpy(voxelPersistFilename, ::wantLocalDomain ? LOCAL_VOXELS_PERSIST_FILE : VOXELS_PERSIST_FILE); + //strcpy(voxelPersistFilename, ::wantLocalDomain ? LOCAL_VOXELS_PERSIST_FILE : VOXELS_PERSIST_FILE); + strcpy(voxelPersistFilename, LOCAL_VOXELS_PERSIST_FILE); } printf("loading voxels from file: %s...\n", voxelPersistFilename); @@ -278,7 +272,11 @@ void VoxelServer::run() { // loop to send to nodes requesting data while (true) { - + + if (NodeList::getInstance()->getNumNoReplyDomainCheckIns() == MAX_SILENT_DOMAIN_SERVER_CHECK_INS) { + break; + } + // send a check in packet to the domain server if DOMAIN_SERVER_CHECK_IN_USECS has elapsed if (usecTimestampNow() - usecTimestamp(&lastDomainServerCheckIn) >= DOMAIN_SERVER_CHECK_IN_USECS) { gettimeofday(&lastDomainServerCheckIn, NULL); diff --git a/libraries/voxel-server-library/src/VoxelServer.h b/libraries/voxel-server-library/src/VoxelServer.h index f9740e8c4b..bf9d3c798b 100644 --- a/libraries/voxel-server-library/src/VoxelServer.h +++ b/libraries/voxel-server-library/src/VoxelServer.h @@ -9,50 +9,6 @@ #ifndef __voxel_server__VoxelServer__ #define __voxel_server__VoxelServer__ -#include -#include // for MAX_PACKET_SIZE -#include -#include -#include - -#include "VoxelServerPacketProcessor.h" - - -const int MAX_FILENAME_LENGTH = 1024; -const int VOXEL_LISTEN_PORT = 40106; -const int VOXEL_SIZE_BYTES = 3 + (3 * sizeof(float)); -const int VOXELS_PER_PACKET = (MAX_PACKET_SIZE - 1) / VOXEL_SIZE_BYTES; -const int MIN_BRIGHTNESS = 64; -const float DEATH_STAR_RADIUS = 4.0; -const float MAX_CUBE = 0.05f; -const int VOXEL_SEND_INTERVAL_USECS = 17 * 1000; // approximately 60fps -const int SENDING_TIME_TO_SPARE = 5 * 1000; // usec of sending interval to spare for calculating voxels -const int INTERVALS_PER_SECOND = 1000 * 1000 / VOXEL_SEND_INTERVAL_USECS; -const int MAX_VOXEL_TREE_DEPTH_LEVELS = 4; -const int ENVIRONMENT_SEND_INTERVAL_USECS = 1000000; - -extern const char* LOCAL_VOXELS_PERSIST_FILE; -extern const char* VOXELS_PERSIST_FILE; -extern char voxelPersistFilename[MAX_FILENAME_LENGTH]; -extern int PACKETS_PER_CLIENT_PER_INTERVAL; - -extern VoxelTree serverTree; // this IS a reaveraging tree -extern bool wantVoxelPersist; -extern bool wantLocalDomain; -extern bool debugVoxelSending; -extern bool shouldShowAnimationDebug; -extern bool displayVoxelStats; -extern bool debugVoxelReceiving; -extern bool sendEnvironments; -extern bool sendMinimalEnvironment; -extern bool dumpVoxelsOnMove; -extern EnvironmentData environmentData[3]; -extern int receivedPacketCount; -extern JurisdictionMap* jurisdiction; -extern JurisdictionSender* jurisdictionSender; -extern VoxelServerPacketProcessor* voxelServerPacketProcessor; -extern pthread_mutex_t treeLock; - /// Handles assignments of type VoxelServer - sending voxels to various clients. class VoxelServer { public: @@ -61,6 +17,13 @@ public: /// allows setting of run arguments static void setArguments(int argc, char** argv); + + /// when VoxelServer class is used by voxel-server stand alone executable it calls this to specify the domain + /// and port it is handling. When called by assignment-client, this is not needed because assignment-client + /// handles ports and domains automatically. + /// \param const char* domain domain name, IP address, or local to specify the domain the voxel server is serving + /// \param int port port the voxel server will listen on + static void setupDomainAndPort(const char* domain, int port); private: static int _argc; diff --git a/libraries/voxel-server-library/src/VoxelServerPacketProcessor.cpp b/libraries/voxel-server-library/src/VoxelServerPacketProcessor.cpp index aaa347ee86..d283296e6f 100644 --- a/libraries/voxel-server-library/src/VoxelServerPacketProcessor.cpp +++ b/libraries/voxel-server-library/src/VoxelServerPacketProcessor.cpp @@ -12,6 +12,7 @@ #include #include "VoxelServer.h" +#include "VoxelServerState.h" #include "VoxelServerPacketProcessor.h" diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index 5a21b9fc76..f854df84cf 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -6,9 +6,38 @@ // Copyright (c) 2012 High Fidelity, Inc. All rights reserved. // +#include #include +const int VOXEL_LISTEN_PORT = 40106; + int main(int argc, const char * argv[]) { + + // Handle Local Domain testing with the --local command line + const char* local = "--local"; + bool wantLocalDomain = cmdOptionExists(argc, argv, local); + const char* domainIP = getCmdOption(argc, argv, "--domain"); + + int listenPort = VOXEL_LISTEN_PORT; + // Check to see if the user passed in a command line option for setting listen port + const char* PORT_PARAMETER = "--port"; + const char* portParameter = getCmdOption(argc, argv, PORT_PARAMETER); + if (portParameter) { + listenPort = atoi(portParameter); + if (listenPort < 1) { + listenPort = VOXEL_LISTEN_PORT; + } + printf("portParameter=%s listenPort=%d\n", portParameter, listenPort); + } + + if (wantLocalDomain) { + VoxelServer::setupDomainAndPort(local, listenPort); + } else { + if (domainIP) { + VoxelServer::setupDomainAndPort(domainIP, listenPort); + } + } + VoxelServer::setArguments(argc, const_cast(argv)); VoxelServer::run(); } From 100eda6960bb8ed2ed2c4291daf1b8008a9fdab0 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 16 Sep 2013 19:56:34 -0700 Subject: [PATCH 6/7] allow voxel servers in standalone mode to work with new domain server and assignment client --- domain-server/src/main.cpp | 18 +++++++++++++----- .../voxel-server-library/src/VoxelServer.cpp | 7 ++++++- .../voxel-server-library/src/VoxelServer.h | 1 + 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/domain-server/src/main.cpp b/domain-server/src/main.cpp index bfd0d3da21..a829b417ab 100644 --- a/domain-server/src/main.cpp +++ b/domain-server/src/main.cpp @@ -167,6 +167,9 @@ int main(int argc, const char* argv[]) { // Start the web server. ctx = mg_start(&callbacks, NULL, options); + // wait to check on voxel-servers till we've given our NodeList a chance to get a good list + int checkForVoxelServerAttempt = 0; + while (true) { ::assignmentQueueMutex.lock(); @@ -184,20 +187,25 @@ int main(int argc, const char* argv[]) { ::assignmentQueue.push_front(&audioMixerAssignment); } - // Now handle voxel servers, since there could be more than one, we look for any of them + // Now handle voxel servers. Couple of things are special about voxel servers. + // 1) They can run standalone, and so we want to wait to ask for an assignment until we've given them sufficient + // time to check in with us. So we will look for them, but we want actually add assignments unless we haven't + // seen one after a few tries. + // 2) They aren't soloNodeOfType() so we have to count them. int voxelServerCount = 0; for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { if (node->getType() == NODE_TYPE_VOXEL_SERVER) { voxelServerCount++; } } - - if (voxelServerCount == 0 && + const int MIN_VOXEL_SERVER_CHECKS = 10; + if (checkForVoxelServerAttempt > MIN_VOXEL_SERVER_CHECKS && + voxelServerCount == 0 && std::find(::assignmentQueue.begin(), ::assignmentQueue.end(), &voxelServerAssignment) == ::assignmentQueue.end()) { - qDebug("Missing an Voxel Server and assignment not in queue. Adding.\n"); + qDebug("Missing a Voxel Server and assignment not in queue. Adding.\n"); ::assignmentQueue.push_front(&voxelServerAssignment); } - + checkForVoxelServerAttempt++; ::assignmentQueueMutex.unlock(); diff --git a/libraries/voxel-server-library/src/VoxelServer.cpp b/libraries/voxel-server-library/src/VoxelServer.cpp index f56232264f..b239a180d9 100644 --- a/libraries/voxel-server-library/src/VoxelServer.cpp +++ b/libraries/voxel-server-library/src/VoxelServer.cpp @@ -65,6 +65,7 @@ NodeWatcher nodeWatcher; // used to cleanup AGENT data when agents are killed int VoxelServer::_argc = 0; const char** VoxelServer::_argv = NULL; +bool VoxelServer::_dontKillOnMissingDomain = false; void attachVoxelNodeDataToNode(Node* newNode) { if (newNode->getLinkedData() == NULL) { @@ -91,6 +92,9 @@ void VoxelServer::setupDomainAndPort(const char* domain, int port) { NodeList::getInstance()->setDomainHostname(domain); } } + + // If we're running in standalone mode, we don't want to kill ourselves when we haven't heard from a domain + _dontKillOnMissingDomain = true; } //int main(int argc, const char * argv[]) { @@ -273,7 +277,8 @@ void VoxelServer::run() { // loop to send to nodes requesting data while (true) { - if (NodeList::getInstance()->getNumNoReplyDomainCheckIns() == MAX_SILENT_DOMAIN_SERVER_CHECK_INS) { + if (!_dontKillOnMissingDomain && + NodeList::getInstance()->getNumNoReplyDomainCheckIns() == MAX_SILENT_DOMAIN_SERVER_CHECK_INS) { break; } diff --git a/libraries/voxel-server-library/src/VoxelServer.h b/libraries/voxel-server-library/src/VoxelServer.h index bf9d3c798b..d51870dbb1 100644 --- a/libraries/voxel-server-library/src/VoxelServer.h +++ b/libraries/voxel-server-library/src/VoxelServer.h @@ -28,6 +28,7 @@ public: private: static int _argc; static const char** _argv; + static bool _dontKillOnMissingDomain; }; From d96fe7a24e79b4a06685f281d62a4d8096005a6f Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 16 Sep 2013 23:36:27 -0700 Subject: [PATCH 7/7] added VoxelServerState.h --- .../src/VoxelServerState.h | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 libraries/voxel-server-library/src/VoxelServerState.h diff --git a/libraries/voxel-server-library/src/VoxelServerState.h b/libraries/voxel-server-library/src/VoxelServerState.h new file mode 100644 index 0000000000..2d00d4a046 --- /dev/null +++ b/libraries/voxel-server-library/src/VoxelServerState.h @@ -0,0 +1,53 @@ +// VoxelServer.h +// voxel-server +// +// Created by Brad Hefta-Gaub on 8/21/13 +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// +// + +#ifndef __voxel_server__VoxelServerState__ +#define __voxel_server__VoxelServerState__ + +#include +#include // for MAX_PACKET_SIZE +#include +#include + +#include "VoxelServerPacketProcessor.h" + + +const int MAX_FILENAME_LENGTH = 1024; +const int VOXEL_SIZE_BYTES = 3 + (3 * sizeof(float)); +const int VOXELS_PER_PACKET = (MAX_PACKET_SIZE - 1) / VOXEL_SIZE_BYTES; +const int MIN_BRIGHTNESS = 64; +const float DEATH_STAR_RADIUS = 4.0; +const float MAX_CUBE = 0.05f; +const int VOXEL_SEND_INTERVAL_USECS = 17 * 1000; // approximately 60fps +const int SENDING_TIME_TO_SPARE = 5 * 1000; // usec of sending interval to spare for calculating voxels +const int INTERVALS_PER_SECOND = 1000 * 1000 / VOXEL_SEND_INTERVAL_USECS; +const int MAX_VOXEL_TREE_DEPTH_LEVELS = 4; +const int ENVIRONMENT_SEND_INTERVAL_USECS = 1000000; + +extern const char* LOCAL_VOXELS_PERSIST_FILE; +extern const char* VOXELS_PERSIST_FILE; +extern char voxelPersistFilename[MAX_FILENAME_LENGTH]; +extern int PACKETS_PER_CLIENT_PER_INTERVAL; + +extern VoxelTree serverTree; // this IS a reaveraging tree +extern bool wantVoxelPersist; +extern bool wantLocalDomain; +extern bool debugVoxelSending; +extern bool shouldShowAnimationDebug; +extern bool displayVoxelStats; +extern bool debugVoxelReceiving; +extern bool sendEnvironments; +extern bool sendMinimalEnvironment; +extern bool dumpVoxelsOnMove; +extern int receivedPacketCount; +extern JurisdictionMap* jurisdiction; +extern JurisdictionSender* jurisdictionSender; +extern VoxelServerPacketProcessor* voxelServerPacketProcessor; +extern pthread_mutex_t treeLock; + +#endif // __voxel_server__VoxelServerState__