mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 03:44:02 +02:00
Merge pull request #950 from ZappoMan/multi_VS_assigments
Make VoxelServer class run as multiple instances
This commit is contained in:
commit
b6548303d1
15 changed files with 305 additions and 237 deletions
|
@ -100,7 +100,6 @@ void childClient() {
|
|||
|
||||
// run the deployed assignment
|
||||
deployedAssignment->run();
|
||||
|
||||
} else {
|
||||
qDebug("Received a bad destination socket for assignment.\n");
|
||||
}
|
||||
|
@ -154,6 +153,7 @@ void sigchldHandler(int sig) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void parentMonitor() {
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
#include <QtCore/QCoreApplication>
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QMutex>
|
||||
|
||||
#include <civetweb.h>
|
||||
|
@ -58,7 +59,7 @@ unsigned char* addNodeToBroadcastPacket(unsigned char* currentPosition, Node* no
|
|||
}
|
||||
|
||||
static int mongooseRequestHandler(struct mg_connection *conn) {
|
||||
const struct mg_request_info *ri = mg_get_request_info(conn);
|
||||
const struct mg_request_info* ri = mg_get_request_info(conn);
|
||||
|
||||
if (strcmp(ri->uri, "/assignment") == 0 && strcmp(ri->request_method, "POST") == 0) {
|
||||
// return a 200
|
||||
|
@ -131,7 +132,7 @@ int main(int argc, const char* argv[]) {
|
|||
in_addr_t serverLocalAddress = getLocalAddress();
|
||||
|
||||
nodeList->startSilentNodeRemovalThread();
|
||||
|
||||
|
||||
timeval lastStatSendTime = {};
|
||||
const char ASSIGNMENT_SERVER_OPTION[] = "-a";
|
||||
|
||||
|
@ -159,6 +160,15 @@ int main(int argc, const char* argv[]) {
|
|||
Assignment voxelServerAssignment(Assignment::CreateCommand,
|
||||
Assignment::VoxelServerType,
|
||||
Assignment::LocalLocation);
|
||||
|
||||
// Handle Domain/Voxel Server configuration command line arguments
|
||||
const char VOXEL_CONFIG_OPTION[] = "--voxelServerConfig";
|
||||
const char* voxelServerConfig = getCmdOption(argc, argv, VOXEL_CONFIG_OPTION);
|
||||
if (voxelServerConfig) {
|
||||
qDebug("Reading Voxel Server Configuration.\n");
|
||||
qDebug() << " config: " << voxelServerConfig << "\n";
|
||||
voxelServerAssignment.setPayload((uchar*)voxelServerConfig, strlen(voxelServerConfig) + 1);
|
||||
}
|
||||
|
||||
// construct a local socket to send with our created assignments to the global AS
|
||||
sockaddr_in localSocket = {};
|
||||
|
@ -167,13 +177,13 @@ int main(int argc, const char* argv[]) {
|
|||
localSocket.sin_addr.s_addr = serverLocalAddress;
|
||||
|
||||
// setup the mongoose web server
|
||||
struct mg_context *ctx;
|
||||
struct mg_context* ctx;
|
||||
struct mg_callbacks callbacks = {};
|
||||
|
||||
QString documentRoot = QString("%1/resources/web").arg(QCoreApplication::applicationDirPath());
|
||||
|
||||
// list of options. Last element must be NULL.
|
||||
const char *options[] = {"listening_ports", "8080",
|
||||
const char* options[] = {"listening_ports", "8080",
|
||||
"document_root", documentRoot.toStdString().c_str(), NULL};
|
||||
|
||||
callbacks.begin_request = mongooseRequestHandler;
|
||||
|
@ -214,10 +224,9 @@ int main(int argc, const char* argv[]) {
|
|||
}
|
||||
}
|
||||
const int MIN_VOXEL_SERVER_CHECKS = 10;
|
||||
if (checkForVoxelServerAttempt > MIN_VOXEL_SERVER_CHECKS &&
|
||||
voxelServerCount == 0 &&
|
||||
if (checkForVoxelServerAttempt > MIN_VOXEL_SERVER_CHECKS && voxelServerCount == 0 &&
|
||||
std::find(::assignmentQueue.begin(), ::assignmentQueue.end(), &voxelServerAssignment) == ::assignmentQueue.end()) {
|
||||
qDebug("Missing a 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++;
|
||||
|
|
|
@ -165,12 +165,10 @@ int Assignment::packToBuffer(unsigned char* buffer) {
|
|||
|
||||
numPackedBytes += packSocket(buffer + numPackedBytes, socketToPack);
|
||||
}
|
||||
|
||||
if (_numPayloadBytes) {
|
||||
memcpy(buffer + numPackedBytes, _payload, _numPayloadBytes);
|
||||
numPackedBytes += _numPayloadBytes;
|
||||
}
|
||||
|
||||
return numPackedBytes;
|
||||
}
|
||||
|
||||
|
|
|
@ -72,7 +72,7 @@ public:
|
|||
|
||||
const sockaddr* getAttachedLocalSocket() { return _attachedLocalSocket; }
|
||||
void setAttachedLocalSocket(const sockaddr* attachedLocalSocket);
|
||||
|
||||
|
||||
/// Packs the assignment to the passed buffer
|
||||
/// \param buffer the buffer in which to pack the assignment
|
||||
/// \return number of bytes packed into buffer
|
||||
|
|
|
@ -28,14 +28,17 @@ VoxelNodeData::VoxelNodeData(Node* owningNode) :
|
|||
_voxelPacket = new unsigned char[MAX_VOXEL_PACKET_SIZE];
|
||||
_voxelPacketAt = _voxelPacket;
|
||||
resetVoxelPacket();
|
||||
|
||||
}
|
||||
|
||||
void VoxelNodeData::initializeVoxelSendThread(VoxelServer* voxelServer) {
|
||||
// Create voxel sending thread...
|
||||
uint16_t nodeID = getOwningNode()->getNodeID();
|
||||
_voxelSendThread = new VoxelSendThread(nodeID);
|
||||
_voxelSendThread = new VoxelSendThread(nodeID, voxelServer);
|
||||
_voxelSendThread->initialize(true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void VoxelNodeData::resetVoxelPacket() {
|
||||
// If we're moving, and the client asked for low res, then we force monochrome, otherwise, use
|
||||
// the clients requested color state.
|
||||
|
@ -57,8 +60,10 @@ void VoxelNodeData::writeToPacket(unsigned char* buffer, int bytes) {
|
|||
VoxelNodeData::~VoxelNodeData() {
|
||||
delete[] _voxelPacket;
|
||||
|
||||
_voxelSendThread->terminate();
|
||||
delete _voxelSendThread;
|
||||
if (_voxelSendThread) {
|
||||
_voxelSendThread->terminate();
|
||||
delete _voxelSendThread;
|
||||
}
|
||||
}
|
||||
|
||||
bool VoxelNodeData::updateCurrentViewFrustum() {
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <VoxelSceneStats.h>
|
||||
|
||||
class VoxelSendThread;
|
||||
class VoxelServer;
|
||||
|
||||
class VoxelNodeData : public AvatarData {
|
||||
public:
|
||||
|
@ -65,6 +66,9 @@ public:
|
|||
|
||||
VoxelSceneStats stats;
|
||||
|
||||
void initializeVoxelSendThread(VoxelServer* voxelServer);
|
||||
bool isVoxelSendThreadInitalized() { return _voxelSendThread; }
|
||||
|
||||
private:
|
||||
VoxelNodeData(const VoxelNodeData &);
|
||||
VoxelNodeData& operator= (const VoxelNodeData&);
|
||||
|
|
|
@ -16,10 +16,11 @@ extern EnvironmentData environmentData[3];
|
|||
|
||||
#include "VoxelSendThread.h"
|
||||
#include "VoxelServer.h"
|
||||
#include "VoxelServerState.h"
|
||||
#include "VoxelServerConsts.h"
|
||||
|
||||
VoxelSendThread::VoxelSendThread(uint16_t nodeID) :
|
||||
_nodeID(nodeID) {
|
||||
VoxelSendThread::VoxelSendThread(uint16_t nodeID, VoxelServer* myServer) :
|
||||
_nodeID(nodeID),
|
||||
_myServer(myServer) {
|
||||
}
|
||||
|
||||
bool VoxelSendThread::process() {
|
||||
|
@ -35,7 +36,7 @@ bool VoxelSendThread::process() {
|
|||
// Sometimes the node data has not yet been linked, in which case we can't really do anything
|
||||
if (nodeData) {
|
||||
bool viewFrustumChanged = nodeData->updateCurrentViewFrustum();
|
||||
if (::debugVoxelSending) {
|
||||
if (_myServer->wantsDebugVoxelSending()) {
|
||||
printf("nodeData->updateCurrentViewFrustum() changed=%s\n", debug::valueOf(viewFrustumChanged));
|
||||
}
|
||||
deepestLevelVoxelDistributor(node, nodeData, viewFrustumChanged);
|
||||
|
@ -47,7 +48,7 @@ bool VoxelSendThread::process() {
|
|||
if (usecToSleep > 0) {
|
||||
usleep(usecToSleep);
|
||||
} else {
|
||||
if (::debugVoxelSending) {
|
||||
if (_myServer->wantsDebugVoxelSending()) {
|
||||
std::cout << "Last send took too much time, not sleeping!\n";
|
||||
}
|
||||
}
|
||||
|
@ -94,7 +95,7 @@ void VoxelSendThread::handlePacketSend(Node* node, VoxelNodeData* nodeData, int&
|
|||
/// Version of voxel distributor that sends the deepest LOD level at once
|
||||
void VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* nodeData, bool viewFrustumChanged) {
|
||||
|
||||
pthread_mutex_lock(&::treeLock);
|
||||
_myServer->lockTree();
|
||||
|
||||
int truePacketsSent = 0;
|
||||
int trueBytesSent = 0;
|
||||
|
@ -113,7 +114,7 @@ void VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* no
|
|||
if (wantColor != nodeData->getCurrentPacketIsColor()) {
|
||||
|
||||
if (nodeData->isPacketWaiting()) {
|
||||
if (::debugVoxelSending) {
|
||||
if (_myServer->wantsDebugVoxelSending()) {
|
||||
printf("wantColor=%s --- SENDING PARTIAL PACKET! nodeData->getCurrentPacketIsColor()=%s\n",
|
||||
debug::valueOf(wantColor), debug::valueOf(nodeData->getCurrentPacketIsColor()));
|
||||
}
|
||||
|
@ -121,7 +122,7 @@ void VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* no
|
|||
handlePacketSend(node, nodeData, trueBytesSent, truePacketsSent);
|
||||
|
||||
} else {
|
||||
if (::debugVoxelSending) {
|
||||
if (_myServer->wantsDebugVoxelSending()) {
|
||||
printf("wantColor=%s --- FIXING HEADER! nodeData->getCurrentPacketIsColor()=%s\n",
|
||||
debug::valueOf(wantColor), debug::valueOf(nodeData->getCurrentPacketIsColor()));
|
||||
}
|
||||
|
@ -129,7 +130,7 @@ void VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* no
|
|||
}
|
||||
}
|
||||
|
||||
if (::debugVoxelSending) {
|
||||
if (_myServer->wantsDebugVoxelSending()) {
|
||||
printf("wantColor=%s getCurrentPacketIsColor()=%s, viewFrustumChanged=%s, getWantLowResMoving()=%s\n",
|
||||
debug::valueOf(wantColor), debug::valueOf(nodeData->getCurrentPacketIsColor()),
|
||||
debug::valueOf(viewFrustumChanged), debug::valueOf(nodeData->getWantLowResMoving()));
|
||||
|
@ -137,7 +138,7 @@ void VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* no
|
|||
|
||||
const ViewFrustum* lastViewFrustum = wantDelta ? &nodeData->getLastKnownViewFrustum() : NULL;
|
||||
|
||||
if (::debugVoxelSending) {
|
||||
if (_myServer->wantsDebugVoxelSending()) {
|
||||
printf("deepestLevelVoxelDistributor() viewFrustumChanged=%s, nodeBag.isEmpty=%s, viewSent=%s\n",
|
||||
debug::valueOf(viewFrustumChanged), debug::valueOf(nodeData->nodeBag.isEmpty()),
|
||||
debug::valueOf(nodeData->getViewSent())
|
||||
|
@ -148,7 +149,7 @@ void VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* no
|
|||
// the current view frustum for things to send.
|
||||
if (viewFrustumChanged || nodeData->nodeBag.isEmpty()) {
|
||||
uint64_t now = usecTimestampNow();
|
||||
if (::debugVoxelSending) {
|
||||
if (_myServer->wantsDebugVoxelSending()) {
|
||||
printf("(viewFrustumChanged=%s || nodeData->nodeBag.isEmpty() =%s)...\n",
|
||||
debug::valueOf(viewFrustumChanged), debug::valueOf(nodeData->nodeBag.isEmpty()));
|
||||
if (nodeData->getLastTimeBagEmpty() > 0) {
|
||||
|
@ -166,7 +167,7 @@ void VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* no
|
|||
|
||||
// if our view has changed, we need to reset these things...
|
||||
if (viewFrustumChanged) {
|
||||
if (::dumpVoxelsOnMove) {
|
||||
if (_myServer->wantDumpVoxelsOnMove()) {
|
||||
nodeData->nodeBag.deleteAll();
|
||||
}
|
||||
nodeData->map.erase();
|
||||
|
@ -180,7 +181,7 @@ void VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* no
|
|||
|
||||
nodeData->stats.sceneCompleted();
|
||||
|
||||
if (::displayVoxelStats) {
|
||||
if (_myServer->wantDisplayVoxelStats()) {
|
||||
nodeData->stats.printDebugDetails();
|
||||
}
|
||||
|
||||
|
@ -191,10 +192,10 @@ void VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* no
|
|||
if (isFullScene) {
|
||||
nodeData->nodeBag.deleteAll();
|
||||
}
|
||||
nodeData->stats.sceneStarted(isFullScene, viewFrustumChanged, ::serverTree.rootNode, ::jurisdiction);
|
||||
nodeData->stats.sceneStarted(isFullScene, viewFrustumChanged, _myServer->getServerTree().rootNode, _myServer->getJurisdiction());
|
||||
|
||||
// This is the start of "resending" the scene.
|
||||
nodeData->nodeBag.insert(serverTree.rootNode);
|
||||
nodeData->nodeBag.insert(_myServer->getServerTree().rootNode);
|
||||
}
|
||||
|
||||
// If we have something in our nodeBag, then turn them into packets and send them out...
|
||||
|
@ -203,8 +204,8 @@ void VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* no
|
|||
int packetsSentThisInterval = 0;
|
||||
uint64_t start = usecTimestampNow();
|
||||
|
||||
bool shouldSendEnvironments = ::sendEnvironments && shouldDo(ENVIRONMENT_SEND_INTERVAL_USECS, VOXEL_SEND_INTERVAL_USECS);
|
||||
while (packetsSentThisInterval < PACKETS_PER_CLIENT_PER_INTERVAL - (shouldSendEnvironments ? 1 : 0)) {
|
||||
bool shouldSendEnvironments = _myServer->wantSendEnvironments() && shouldDo(ENVIRONMENT_SEND_INTERVAL_USECS, VOXEL_SEND_INTERVAL_USECS);
|
||||
while (packetsSentThisInterval < _myServer->getPacketsPerClientPerInterval() - (shouldSendEnvironments ? 1 : 0)) {
|
||||
// Check to see if we're taking too long, and if so bail early...
|
||||
uint64_t now = usecTimestampNow();
|
||||
long elapsedUsec = (now - start);
|
||||
|
@ -212,7 +213,7 @@ void VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* no
|
|||
long usecRemaining = (VOXEL_SEND_INTERVAL_USECS - elapsedUsec);
|
||||
|
||||
if (elapsedUsecPerPacket + SENDING_TIME_TO_SPARE > usecRemaining) {
|
||||
if (::debugVoxelSending) {
|
||||
if (_myServer->wantsDebugVoxelSending()) {
|
||||
printf("packetLoop() usecRemaining=%ld bailing early took %ld usecs to generate %d bytes in %d packets (%ld usec avg), %d nodes still to send\n",
|
||||
usecRemaining, elapsedUsec, trueBytesSent, truePacketsSent, elapsedUsecPerPacket,
|
||||
nodeData->nodeBag.count());
|
||||
|
@ -234,10 +235,10 @@ void VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* no
|
|||
WANT_EXISTS_BITS, DONT_CHOP, wantDelta, lastViewFrustum,
|
||||
wantOcclusionCulling, coverageMap, boundaryLevelAdjust,
|
||||
nodeData->getLastTimeBagEmpty(),
|
||||
isFullScene, &nodeData->stats, ::jurisdiction);
|
||||
isFullScene, &nodeData->stats, _myServer->getJurisdiction());
|
||||
|
||||
nodeData->stats.encodeStarted();
|
||||
bytesWritten = serverTree.encodeTreeBitstream(subTree, _tempOutputBuffer, MAX_VOXEL_PACKET_SIZE - 1,
|
||||
bytesWritten = _myServer->getServerTree().encodeTreeBitstream(subTree, _tempOutputBuffer, MAX_VOXEL_PACKET_SIZE - 1,
|
||||
nodeData->nodeBag, params);
|
||||
nodeData->stats.encodeStopped();
|
||||
|
||||
|
@ -254,17 +255,17 @@ void VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* no
|
|||
handlePacketSend(node, nodeData, trueBytesSent, truePacketsSent);
|
||||
nodeData->resetVoxelPacket();
|
||||
}
|
||||
packetsSentThisInterval = PACKETS_PER_CLIENT_PER_INTERVAL; // done for now, no nodes left
|
||||
packetsSentThisInterval = _myServer->getPacketsPerClientPerInterval(); // done for now, no nodes left
|
||||
}
|
||||
}
|
||||
// send the environment packet
|
||||
if (shouldSendEnvironments) {
|
||||
int numBytesPacketHeader = populateTypeAndVersion(_tempOutputBuffer, PACKET_TYPE_ENVIRONMENT_DATA);
|
||||
int envPacketLength = numBytesPacketHeader;
|
||||
int environmentsToSend = ::sendMinimalEnvironment ? 1 : sizeof(environmentData) / sizeof(EnvironmentData);
|
||||
int environmentsToSend = _myServer->getSendMinimalEnvironment() ? 1 : _myServer->getEnvironmentDataCount();
|
||||
|
||||
for (int i = 0; i < environmentsToSend; i++) {
|
||||
envPacketLength += environmentData[i].getBroadcastData(_tempOutputBuffer + envPacketLength);
|
||||
envPacketLength += _myServer->getEnvironmentData(i)->getBroadcastData(_tempOutputBuffer + envPacketLength);
|
||||
}
|
||||
|
||||
NodeList::getInstance()->getNodeSocket()->send(node->getActiveSocket(), _tempOutputBuffer, envPacketLength);
|
||||
|
@ -283,7 +284,7 @@ void VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* no
|
|||
printf("WARNING! packetLoop() took %d milliseconds to generate %d bytes in %d packets, %d nodes still to send\n",
|
||||
elapsedmsec, trueBytesSent, truePacketsSent, nodeData->nodeBag.count());
|
||||
}
|
||||
} else if (::debugVoxelSending) {
|
||||
} else if (_myServer->wantsDebugVoxelSending()) {
|
||||
printf("packetLoop() took %d milliseconds to generate %d bytes in %d packets, %d nodes still to send\n",
|
||||
elapsedmsec, trueBytesSent, truePacketsSent, nodeData->nodeBag.count());
|
||||
}
|
||||
|
@ -293,7 +294,7 @@ void VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* no
|
|||
if (nodeData->nodeBag.isEmpty()) {
|
||||
nodeData->updateLastKnownViewFrustum();
|
||||
nodeData->setViewSent(true);
|
||||
if (::debugVoxelSending) {
|
||||
if (_myServer->wantsDebugVoxelSending()) {
|
||||
nodeData->map.printStats();
|
||||
}
|
||||
nodeData->map.erase(); // It would be nice if we could save this, and only reset it when the view frustum changes
|
||||
|
@ -301,6 +302,6 @@ void VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* no
|
|||
|
||||
} // end if bag wasn't empty, and so we sent stuff...
|
||||
|
||||
pthread_mutex_unlock(&::treeLock);
|
||||
_myServer->unlockTree();
|
||||
}
|
||||
|
||||
|
|
|
@ -16,17 +16,19 @@
|
|||
#include <VoxelTree.h>
|
||||
#include <VoxelNodeBag.h>
|
||||
#include "VoxelNodeData.h"
|
||||
#include "VoxelServer.h"
|
||||
|
||||
/// Threaded processor for sending voxel packets to a single client
|
||||
class VoxelSendThread : public virtual GenericThread {
|
||||
public:
|
||||
VoxelSendThread(uint16_t nodeID);
|
||||
VoxelSendThread(uint16_t nodeID, VoxelServer* myServer);
|
||||
protected:
|
||||
/// Implements generic processing behavior for this thread.
|
||||
virtual bool process();
|
||||
|
||||
private:
|
||||
uint16_t _nodeID;
|
||||
VoxelServer* _myServer;
|
||||
|
||||
void handlePacketSend(Node* node, VoxelNodeData* nodeData, int& trueBytesSent, int& truePacketsSent);
|
||||
void deepestLevelVoxelDistributor(Node* node, VoxelNodeData* nodeData, bool viewFrustumChanged);
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
#include <OctalCode.h>
|
||||
#include <NodeList.h>
|
||||
#include <NodeTypes.h>
|
||||
#include <EnvironmentData.h>
|
||||
#include <VoxelTree.h>
|
||||
#include "VoxelNodeData.h"
|
||||
#include <SharedUtil.h>
|
||||
|
@ -23,11 +22,6 @@
|
|||
#include <PerfStat.h>
|
||||
#include <JurisdictionSender.h>
|
||||
|
||||
#include "NodeWatcher.h"
|
||||
#include "VoxelPersistThread.h"
|
||||
#include "VoxelSendThread.h"
|
||||
#include "VoxelServerPacketProcessor.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "Syssocket.h"
|
||||
#include "Systime.h"
|
||||
|
@ -38,34 +32,10 @@
|
|||
#endif
|
||||
|
||||
#include "VoxelServer.h"
|
||||
#include "VoxelServerState.h"
|
||||
#include "VoxelServerConsts.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;
|
||||
const char** VoxelServer::_argv = NULL;
|
||||
bool VoxelServer::_dontKillOnMissingDomain = false;
|
||||
|
||||
void attachVoxelNodeDataToNode(Node* newNode) {
|
||||
if (newNode->getLinkedData() == NULL) {
|
||||
|
@ -74,12 +44,48 @@ void attachVoxelNodeDataToNode(Node* newNode) {
|
|||
}
|
||||
|
||||
VoxelServer::VoxelServer(Assignment::Command command, Assignment::Location location) :
|
||||
Assignment(command, Assignment::VoxelServerType, location) {
|
||||
|
||||
Assignment(command, Assignment::VoxelServerType, location),
|
||||
_serverTree(true) {
|
||||
_argc = 0;
|
||||
_argv = NULL;
|
||||
_dontKillOnMissingDomain = false;
|
||||
|
||||
_packetsPerClientPerInterval = 10;
|
||||
_wantVoxelPersist = true;
|
||||
_wantLocalDomain = false;
|
||||
_debugVoxelSending = false;
|
||||
_shouldShowAnimationDebug = false;
|
||||
_displayVoxelStats = false;
|
||||
_debugVoxelReceiving = false;
|
||||
_sendEnvironments = true;
|
||||
_sendMinimalEnvironment = false;
|
||||
_dumpVoxelsOnMove = false;
|
||||
_jurisdiction = NULL;
|
||||
_jurisdictionSender = NULL;
|
||||
_voxelServerPacketProcessor = NULL;
|
||||
_voxelPersistThread = NULL;
|
||||
}
|
||||
|
||||
VoxelServer::VoxelServer(const unsigned char* dataBuffer, int numBytes) : Assignment(dataBuffer, numBytes) {
|
||||
|
||||
VoxelServer::VoxelServer(const unsigned char* dataBuffer, int numBytes) : Assignment(dataBuffer, numBytes),
|
||||
_serverTree(true) {
|
||||
_argc = 0;
|
||||
_argv = NULL;
|
||||
_dontKillOnMissingDomain = false;
|
||||
|
||||
_packetsPerClientPerInterval = 10;
|
||||
_wantVoxelPersist = true;
|
||||
_wantLocalDomain = false;
|
||||
_debugVoxelSending = false;
|
||||
_shouldShowAnimationDebug = false;
|
||||
_displayVoxelStats = false;
|
||||
_debugVoxelReceiving = false;
|
||||
_sendEnvironments = true;
|
||||
_sendMinimalEnvironment = false;
|
||||
_dumpVoxelsOnMove = false;
|
||||
_jurisdiction = NULL;
|
||||
_jurisdictionSender = NULL;
|
||||
_voxelServerPacketProcessor = NULL;
|
||||
_voxelPersistThread = NULL;
|
||||
}
|
||||
|
||||
void VoxelServer::setArguments(int argc, char** argv) {
|
||||
|
@ -87,13 +93,13 @@ void VoxelServer::setArguments(int argc, char** argv) {
|
|||
_argv = const_cast<const char**>(argv);
|
||||
}
|
||||
|
||||
void VoxelServer::setupDomainAndPort(const char* domain, int port) {
|
||||
void VoxelServer::setupStandAlone(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) {
|
||||
_wantLocalDomain = strcmp(domain, local) == 0;
|
||||
if (_wantLocalDomain) {
|
||||
printf("Local Domain MODE!\n");
|
||||
NodeList::getInstance()->setDomainIPToLocalhost();
|
||||
} else {
|
||||
|
@ -108,7 +114,7 @@ void VoxelServer::setupDomainAndPort(const char* domain, int port) {
|
|||
|
||||
//int main(int argc, const char * argv[]) {
|
||||
void VoxelServer::run() {
|
||||
pthread_mutex_init(&::treeLock, NULL);
|
||||
pthread_mutex_init(&_treeLock, NULL);
|
||||
|
||||
qInstallMessageHandler(sharedMessageHandler);
|
||||
|
||||
|
@ -118,7 +124,7 @@ void VoxelServer::run() {
|
|||
printf("jurisdictionFile=%s\n", jurisdictionFile);
|
||||
|
||||
printf("about to readFromFile().... jurisdictionFile=%s\n", jurisdictionFile);
|
||||
jurisdiction = new JurisdictionMap(jurisdictionFile);
|
||||
_jurisdiction = new JurisdictionMap(jurisdictionFile);
|
||||
printf("after readFromFile().... jurisdictionFile=%s\n", jurisdictionFile);
|
||||
} else {
|
||||
const char* JURISDICTION_ROOT = "--jurisdictionRoot";
|
||||
|
@ -134,28 +140,28 @@ void VoxelServer::run() {
|
|||
}
|
||||
|
||||
if (jurisdictionRoot || jurisdictionEndNodes) {
|
||||
::jurisdiction = new JurisdictionMap(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));
|
||||
_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;
|
||||
_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));
|
||||
_sendMinimalEnvironment = getCmdOption(_argc, _argv, MINIMAL_ENVIRONMENT);
|
||||
printf("Using Minimal Environment=%s\n", debug::valueOf(_sendMinimalEnvironment));
|
||||
}
|
||||
printf("Sending environments=%s\n", debug::valueOf(::sendEnvironments));
|
||||
printf("Sending environments=%s\n", debug::valueOf(_sendEnvironments));
|
||||
|
||||
NodeList* nodeList = NodeList::getInstance();
|
||||
nodeList->setOwnerType(NODE_TYPE_VOXEL_SERVER);
|
||||
|
@ -163,72 +169,72 @@ void VoxelServer::run() {
|
|||
setvbuf(stdout, NULL, _IOLBF, 0);
|
||||
|
||||
// tell our NodeList about our desire to get notifications
|
||||
nodeList->addHook(&nodeWatcher);
|
||||
nodeList->addHook(&_nodeWatcher);
|
||||
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));
|
||||
_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));
|
||||
_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));
|
||||
_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));
|
||||
_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;
|
||||
if (getCmdOption(_argc, _argv, NO_VOXEL_PERSIST)) {
|
||||
_wantVoxelPersist = false;
|
||||
}
|
||||
printf("wantVoxelPersist=%s\n", debug::valueOf(::wantVoxelPersist));
|
||||
printf("wantVoxelPersist=%s\n", debug::valueOf(_wantVoxelPersist));
|
||||
|
||||
// if we want Voxel Persistence, load the local file now...
|
||||
bool persistantFileRead = false;
|
||||
if (::wantVoxelPersist) {
|
||||
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);
|
||||
strcpy(_voxelPersistFilename, voxelsPersistFilenameParameter);
|
||||
} else {
|
||||
//strcpy(voxelPersistFilename, ::wantLocalDomain ? LOCAL_VOXELS_PERSIST_FILE : VOXELS_PERSIST_FILE);
|
||||
strcpy(voxelPersistFilename, LOCAL_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);
|
||||
printf("loading voxels from file: %s...\n", _voxelPersistFilename);
|
||||
|
||||
persistantFileRead = ::serverTree.readFromSVOFile(::voxelPersistFilename);
|
||||
persistantFileRead = _serverTree.readFromSVOFile(_voxelPersistFilename);
|
||||
if (persistantFileRead) {
|
||||
PerformanceWarning warn(::shouldShowAnimationDebug,
|
||||
"persistVoxelsWhenDirty() - reaverageVoxelColors()", ::shouldShowAnimationDebug);
|
||||
PerformanceWarning warn(_shouldShowAnimationDebug,
|
||||
"persistVoxelsWhenDirty() - reaverageVoxelColors()", _shouldShowAnimationDebug);
|
||||
|
||||
// after done inserting all these voxels, then reaverage colors
|
||||
serverTree.reaverageVoxelColors(serverTree.rootNode);
|
||||
_serverTree.reaverageVoxelColors(_serverTree.rootNode);
|
||||
printf("Voxels reAveraged\n");
|
||||
}
|
||||
|
||||
::serverTree.clearDirtyBit(); // the tree is clean since we just loaded it
|
||||
_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();
|
||||
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);
|
||||
_voxelPersistThread = new VoxelPersistThread(&_serverTree, _voxelPersistFilename);
|
||||
if (_voxelPersistThread) {
|
||||
_voxelPersistThread->initialize(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -237,52 +243,52 @@ void VoxelServer::run() {
|
|||
const char* INPUT_FILE = "-i";
|
||||
const char* voxelsFilename = getCmdOption(_argc, _argv, INPUT_FILE);
|
||||
if (voxelsFilename) {
|
||||
serverTree.readFromSVOFile(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;
|
||||
_packetsPerClientPerInterval = atoi(packetsPerSecond) / INTERVALS_PER_SECOND;
|
||||
if (_packetsPerClientPerInterval < 1) {
|
||||
_packetsPerClientPerInterval = 1;
|
||||
}
|
||||
printf("packetsPerSecond=%s PACKETS_PER_CLIENT_PER_INTERVAL=%d\n", packetsPerSecond, PACKETS_PER_CLIENT_PER_INTERVAL);
|
||||
printf("packetsPerSecond=%s PACKETS_PER_CLIENT_PER_INTERVAL=%d\n", packetsPerSecond, _packetsPerClientPerInterval);
|
||||
}
|
||||
|
||||
// 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
|
||||
_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];
|
||||
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);
|
||||
_jurisdictionSender = new JurisdictionSender(_jurisdiction);
|
||||
if (_jurisdictionSender) {
|
||||
_jurisdictionSender->initialize(true);
|
||||
}
|
||||
|
||||
// set up our VoxelServerPacketProcessor
|
||||
::voxelServerPacketProcessor = new VoxelServerPacketProcessor();
|
||||
if (::voxelServerPacketProcessor) {
|
||||
::voxelServerPacketProcessor->initialize(true);
|
||||
_voxelServerPacketProcessor = new VoxelServerPacketProcessor(this);
|
||||
if (_voxelServerPacketProcessor) {
|
||||
_voxelServerPacketProcessor->initialize(true);
|
||||
}
|
||||
|
||||
|
||||
// loop to send to nodes requesting data
|
||||
while (true) {
|
||||
|
||||
|
@ -313,46 +319,50 @@ void VoxelServer::run() {
|
|||
nodeID);
|
||||
|
||||
NodeList::getInstance()->updateNodeWithData(node, packetData, packetLength);
|
||||
|
||||
VoxelNodeData* nodeData = (VoxelNodeData*) node->getLinkedData();
|
||||
if (nodeData && !nodeData->isVoxelSendThreadInitalized()) {
|
||||
nodeData->initializeVoxelSendThread(this);
|
||||
}
|
||||
|
||||
} 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);
|
||||
if (_jurisdictionSender) {
|
||||
_jurisdictionSender->queueReceivedPacket(senderAddress, packetData, packetLength);
|
||||
}
|
||||
} else if (::voxelServerPacketProcessor) {
|
||||
::voxelServerPacketProcessor->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;
|
||||
}
|
||||
delete _jurisdiction;
|
||||
|
||||
if (::jurisdictionSender) {
|
||||
::jurisdictionSender->terminate();
|
||||
delete ::jurisdictionSender;
|
||||
if (_jurisdictionSender) {
|
||||
_jurisdictionSender->terminate();
|
||||
delete _jurisdictionSender;
|
||||
}
|
||||
|
||||
if (::voxelServerPacketProcessor) {
|
||||
::voxelServerPacketProcessor->terminate();
|
||||
delete ::voxelServerPacketProcessor;
|
||||
if (_voxelServerPacketProcessor) {
|
||||
_voxelServerPacketProcessor->terminate();
|
||||
delete _voxelServerPacketProcessor;
|
||||
}
|
||||
|
||||
if (::voxelPersistThread) {
|
||||
::voxelPersistThread->terminate();
|
||||
delete ::voxelPersistThread;
|
||||
if (_voxelPersistThread) {
|
||||
_voxelPersistThread->terminate();
|
||||
delete _voxelPersistThread;
|
||||
}
|
||||
|
||||
// tell our NodeList we're done with notifications
|
||||
nodeList->removeHook(&nodeWatcher);
|
||||
nodeList->removeHook(&_nodeWatcher);
|
||||
|
||||
pthread_mutex_destroy(&::treeLock);
|
||||
pthread_mutex_destroy(&_treeLock);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -11,33 +11,79 @@
|
|||
#define __voxel_server__VoxelServer__
|
||||
|
||||
#include <Assignment.h>
|
||||
#include <EnvironmentData.h>
|
||||
|
||||
#include "NodeWatcher.h"
|
||||
#include "VoxelPersistThread.h"
|
||||
#include "VoxelSendThread.h"
|
||||
#include "VoxelServerConsts.h"
|
||||
#include "VoxelServerPacketProcessor.h"
|
||||
|
||||
/// Handles assignments of type VoxelServer - sending voxels to various clients.
|
||||
class VoxelServer : public Assignment {
|
||||
public:
|
||||
VoxelServer(Assignment::Command command,
|
||||
Assignment::Location location = Assignment::GlobalLocation);
|
||||
|
||||
VoxelServer(const unsigned char* dataBuffer, int numBytes);
|
||||
|
||||
/// runs the voxel server assignment
|
||||
void run();
|
||||
|
||||
/// allows setting of run arguments
|
||||
static void setArguments(int argc, char** argv);
|
||||
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);
|
||||
void setupStandAlone(const char* domain, int port);
|
||||
|
||||
bool wantsDebugVoxelSending() const { return _debugVoxelSending; }
|
||||
bool wantsDebugVoxelReceiving() const { return _debugVoxelReceiving; }
|
||||
bool wantShowAnimationDebug() const { return _shouldShowAnimationDebug; }
|
||||
bool wantSendEnvironments() const { return _sendEnvironments; }
|
||||
bool wantDumpVoxelsOnMove() const { return _dumpVoxelsOnMove; }
|
||||
bool wantDisplayVoxelStats() const { return _displayVoxelStats; }
|
||||
|
||||
VoxelTree& getServerTree() { return _serverTree; }
|
||||
JurisdictionMap* getJurisdiction() { return _jurisdiction; }
|
||||
|
||||
void lockTree() { pthread_mutex_lock(&_treeLock); }
|
||||
void unlockTree() { pthread_mutex_unlock(&_treeLock); }
|
||||
|
||||
int getPacketsPerClientPerInterval() const { return _packetsPerClientPerInterval; }
|
||||
bool getSendMinimalEnvironment() const { return _sendMinimalEnvironment; }
|
||||
EnvironmentData* getEnvironmentData(int i) { return &_environmentData[i]; }
|
||||
int getEnvironmentDataCount() const { return sizeof(_environmentData)/sizeof(EnvironmentData); }
|
||||
|
||||
private:
|
||||
static int _argc;
|
||||
static const char** _argv;
|
||||
static bool _dontKillOnMissingDomain;
|
||||
int _argc;
|
||||
const char** _argv;
|
||||
bool _dontKillOnMissingDomain;
|
||||
|
||||
char _voxelPersistFilename[MAX_FILENAME_LENGTH];
|
||||
int _packetsPerClientPerInterval;
|
||||
VoxelTree _serverTree; // this IS a reaveraging tree
|
||||
bool _wantVoxelPersist;
|
||||
bool _wantLocalDomain;
|
||||
bool _debugVoxelSending;
|
||||
bool _shouldShowAnimationDebug;
|
||||
bool _displayVoxelStats;
|
||||
bool _debugVoxelReceiving;
|
||||
bool _sendEnvironments;
|
||||
bool _sendMinimalEnvironment;
|
||||
bool _dumpVoxelsOnMove;
|
||||
JurisdictionMap* _jurisdiction;
|
||||
JurisdictionSender* _jurisdictionSender;
|
||||
VoxelServerPacketProcessor* _voxelServerPacketProcessor;
|
||||
VoxelPersistThread* _voxelPersistThread;
|
||||
pthread_mutex_t _treeLock;
|
||||
EnvironmentData _environmentData[3];
|
||||
|
||||
NodeWatcher _nodeWatcher; // used to cleanup AGENT data when agents are killed
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // __voxel_server__VoxelServer__
|
||||
|
|
31
libraries/voxel-server-library/src/VoxelServerConsts.h
Normal file
31
libraries/voxel-server-library/src/VoxelServerConsts.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
// VoxelServerConsts.h
|
||||
// voxel-server
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 8/21/13
|
||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
//
|
||||
|
||||
#ifndef __voxel_server__VoxelServerConsts__
|
||||
#define __voxel_server__VoxelServerConsts__
|
||||
|
||||
#include <SharedUtil.h>
|
||||
#include <NodeList.h> // for MAX_PACKET_SIZE
|
||||
#include <JurisdictionSender.h>
|
||||
#include <VoxelTree.h>
|
||||
|
||||
#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 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 ENVIRONMENT_SEND_INTERVAL_USECS = 1000000;
|
||||
|
||||
extern const char* LOCAL_VOXELS_PERSIST_FILE;
|
||||
extern const char* VOXELS_PERSIST_FILE;
|
||||
|
||||
#endif // __voxel_server__VoxelServerConsts__
|
|
@ -12,33 +12,39 @@
|
|||
#include <PerfStat.h>
|
||||
|
||||
#include "VoxelServer.h"
|
||||
#include "VoxelServerState.h"
|
||||
#include "VoxelServerConsts.h"
|
||||
#include "VoxelServerPacketProcessor.h"
|
||||
|
||||
|
||||
VoxelServerPacketProcessor::VoxelServerPacketProcessor(VoxelServer* myServer) :
|
||||
_myServer(myServer),
|
||||
_receivedPacketCount(0) {
|
||||
}
|
||||
|
||||
|
||||
void VoxelServerPacketProcessor::processPacket(sockaddr& senderAddress, unsigned char* packetData, ssize_t packetLength) {
|
||||
|
||||
int numBytesPacketHeader = numBytesForPacketHeader(packetData);
|
||||
|
||||
if (packetData[0] == PACKET_TYPE_SET_VOXEL || packetData[0] == PACKET_TYPE_SET_VOXEL_DESTRUCTIVE) {
|
||||
bool destructive = (packetData[0] == PACKET_TYPE_SET_VOXEL_DESTRUCTIVE);
|
||||
PerformanceWarning warn(::shouldShowAnimationDebug,
|
||||
PerformanceWarning warn(_myServer->wantShowAnimationDebug(),
|
||||
destructive ? "PACKET_TYPE_SET_VOXEL_DESTRUCTIVE" : "PACKET_TYPE_SET_VOXEL",
|
||||
::shouldShowAnimationDebug);
|
||||
_myServer->wantShowAnimationDebug());
|
||||
|
||||
::receivedPacketCount++;
|
||||
_receivedPacketCount++;
|
||||
|
||||
unsigned short int itemNumber = (*((unsigned short int*)(packetData + numBytesPacketHeader)));
|
||||
if (::shouldShowAnimationDebug) {
|
||||
if (_myServer->wantShowAnimationDebug()) {
|
||||
printf("got %s - command from client receivedBytes=%ld itemNumber=%d\n",
|
||||
destructive ? "PACKET_TYPE_SET_VOXEL_DESTRUCTIVE" : "PACKET_TYPE_SET_VOXEL",
|
||||
packetLength, itemNumber);
|
||||
}
|
||||
|
||||
if (::debugVoxelReceiving) {
|
||||
if (_myServer->wantsDebugVoxelReceiving()) {
|
||||
printf("got %s - %d command from client receivedBytes=%ld itemNumber=%d\n",
|
||||
destructive ? "PACKET_TYPE_SET_VOXEL_DESTRUCTIVE" : "PACKET_TYPE_SET_VOXEL",
|
||||
::receivedPacketCount, packetLength, itemNumber);
|
||||
_receivedPacketCount, packetLength, itemNumber);
|
||||
}
|
||||
int atByte = numBytesPacketHeader + sizeof(itemNumber);
|
||||
unsigned char* voxelData = (unsigned char*)&packetData[atByte];
|
||||
|
@ -48,7 +54,7 @@ void VoxelServerPacketProcessor::processPacket(sockaddr& senderAddress, unsigned
|
|||
int voxelDataSize = bytesRequiredForCodeLength(octets) + COLOR_SIZE_IN_BYTES;
|
||||
int voxelCodeSize = bytesRequiredForCodeLength(octets);
|
||||
|
||||
if (::shouldShowAnimationDebug) {
|
||||
if (_myServer->wantShowAnimationDebug()) {
|
||||
int red = voxelData[voxelCodeSize + 0];
|
||||
int green = voxelData[voxelCodeSize + 1];
|
||||
int blue = voxelData[voxelCodeSize + 2];
|
||||
|
@ -58,7 +64,7 @@ void VoxelServerPacketProcessor::processPacket(sockaddr& senderAddress, unsigned
|
|||
delete[] vertices;
|
||||
}
|
||||
|
||||
serverTree.readCodeColorBufferToTree(voxelData, destructive);
|
||||
_myServer->getServerTree().readCodeColorBufferToTree(voxelData, destructive);
|
||||
// skip to next
|
||||
voxelData += voxelDataSize;
|
||||
atByte += voxelDataSize;
|
||||
|
@ -73,9 +79,9 @@ void VoxelServerPacketProcessor::processPacket(sockaddr& senderAddress, unsigned
|
|||
} else if (packetData[0] == PACKET_TYPE_ERASE_VOXEL) {
|
||||
|
||||
// Send these bits off to the VoxelTree class to process them
|
||||
pthread_mutex_lock(&::treeLock);
|
||||
::serverTree.processRemoveVoxelBitstream((unsigned char*)packetData, packetLength);
|
||||
pthread_mutex_unlock(&::treeLock);
|
||||
_myServer->lockTree();
|
||||
_myServer->getServerTree().processRemoveVoxelBitstream((unsigned char*)packetData, packetLength);
|
||||
_myServer->unlockTree();
|
||||
|
||||
// Make sure our Node and NodeList knows we've heard from this node.
|
||||
Node* node = NodeList::getInstance()->nodeWithAddress(&senderAddress);
|
||||
|
|
|
@ -12,11 +12,20 @@
|
|||
#define __voxel_server__VoxelServerPacketProcessor__
|
||||
|
||||
#include <ReceivedPacketProcessor.h>
|
||||
class VoxelServer;
|
||||
|
||||
/// Handles processing of incoming network packets for the voxel-server. As with other ReceivedPacketProcessor classes
|
||||
/// the user is responsible for reading inbound packets and adding them to the processing queue by calling queueReceivedPacket()
|
||||
class VoxelServerPacketProcessor : public ReceivedPacketProcessor {
|
||||
|
||||
public:
|
||||
VoxelServerPacketProcessor(VoxelServer* myServer);
|
||||
|
||||
protected:
|
||||
virtual void processPacket(sockaddr& senderAddress, unsigned char* packetData, ssize_t packetLength);
|
||||
|
||||
private:
|
||||
VoxelServer* _myServer;
|
||||
int _receivedPacketCount;
|
||||
};
|
||||
#endif // __voxel_server__VoxelServerPacketProcessor__
|
||||
|
|
|
@ -1,53 +0,0 @@
|
|||
// 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 <SharedUtil.h>
|
||||
#include <NodeList.h> // for MAX_PACKET_SIZE
|
||||
#include <JurisdictionSender.h>
|
||||
#include <VoxelTree.h>
|
||||
|
||||
#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__
|
|
@ -29,19 +29,19 @@ int main(int argc, const char * argv[]) {
|
|||
}
|
||||
printf("portParameter=%s listenPort=%d\n", portParameter, listenPort);
|
||||
}
|
||||
|
||||
VoxelServer ourVoxelServer(Assignment::CreateCommand);
|
||||
|
||||
if (wantLocalDomain) {
|
||||
VoxelServer::setupDomainAndPort(local, listenPort);
|
||||
ourVoxelServer.setupStandAlone(local, listenPort);
|
||||
} else {
|
||||
if (domainIP) {
|
||||
VoxelServer::setupDomainAndPort(domainIP, listenPort);
|
||||
ourVoxelServer.setupStandAlone(domainIP, listenPort);
|
||||
}
|
||||
}
|
||||
|
||||
VoxelServer::setArguments(argc, const_cast<char**>(argv));
|
||||
|
||||
VoxelServer dummyAssignedVoxelServer(Assignment::CreateCommand);
|
||||
dummyAssignedVoxelServer.run();
|
||||
ourVoxelServer.setArguments(argc, const_cast<char**>(argv));
|
||||
ourVoxelServer.run();
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue