support piggybacking voxel and voxel stats messages into single packet

This commit is contained in:
ZappoMan 2013-07-19 15:59:47 -07:00
parent d9c8a59929
commit 2cc42f6773
4 changed files with 85 additions and 30 deletions

View file

@ -3339,12 +3339,6 @@ void* Application::networkReceive(void* args) {
if (packetVersionMatch(app->_incomingPacket)) {
// only process this packet if we have a match on the packet version
switch (app->_incomingPacket[0]) {
case PACKET_TYPE_VOXEL_STATS:{
VoxelSceneStats stats;
int statsMessageLength = stats.unpackFromMessage(app->_incomingPacket, bytesReceived);
stats.printDebugDetails();
break;
}
case PACKET_TYPE_TRANSMITTER_DATA_V2:
// V2 = IOS transmitter app
app->_myTransmitter.processIncomingData(app->_incomingPacket, bytesReceived);
@ -3357,16 +3351,39 @@ void* Application::networkReceive(void* args) {
case PACKET_TYPE_VOXEL_DATA_MONOCHROME:
case PACKET_TYPE_Z_COMMAND:
case PACKET_TYPE_ERASE_VOXEL:
case PACKET_TYPE_VOXEL_STATS:
case PACKET_TYPE_ENVIRONMENT_DATA: {
unsigned char* messageData = app->_incomingPacket;
ssize_t messageLength = bytesReceived;
// note: PACKET_TYPE_VOXEL_STATS can have PACKET_TYPE_VOXEL_DATA or PACKET_TYPE_VOXEL_DATA_MONOCHROME
// immediately following them inside the same packet. So, we process the PACKET_TYPE_VOXEL_STATS first
// then process any remaining bytes as if it was another packet
if (messageData[0] == PACKET_TYPE_VOXEL_STATS) {
VoxelSceneStats stats;
int statsMessageLength = stats.unpackFromMessage(messageData, messageLength);
stats.printDebugDetails();
if (messageLength > statsMessageLength) {
messageData += statsMessageLength;
messageLength -= statsMessageLength;
if (!packetVersionMatch(messageData)) {
break; // bail since piggyback data doesn't match our versioning
}
} else {
break; // bail since no piggyback data
}
} // fall through to piggyback message
if (app->_renderVoxels->isChecked()) {
Node* voxelServer = NodeList::getInstance()->soloNodeOfType(NODE_TYPE_VOXEL_SERVER);
if (voxelServer) {
voxelServer->lock();
if (app->_incomingPacket[0] == PACKET_TYPE_ENVIRONMENT_DATA) {
app->_environment.parseData(&senderAddress, app->_incomingPacket, bytesReceived);
if (messageData[0] == PACKET_TYPE_ENVIRONMENT_DATA) {
app->_environment.parseData(&senderAddress, messageData, messageLength);
} else {
app->_voxels.parseData(app->_incomingPacket, bytesReceived);
app->_voxels.parseData(messageData, messageLength);
}
voxelServer->unlock();

View file

@ -14,6 +14,7 @@
VoxelSceneStats::VoxelSceneStats() {
reset();
_readyToSend = false;
}
VoxelSceneStats::~VoxelSceneStats() {
@ -29,6 +30,9 @@ void VoxelSceneStats::sceneStarted(bool fullScene, bool moving) {
void VoxelSceneStats::sceneCompleted() {
_end = usecTimestampNow();
_elapsed = _end - _start;
_statsMessageLength = packIntoMessage(_statsMessage, sizeof(_statsMessage));
_readyToSend = true;
}
void VoxelSceneStats::encodeStarted() {

View file

@ -10,6 +10,7 @@
#define __hifi__VoxelSceneStats__
#include <stdint.h>
#include <NodeList.h>
class VoxelNode;
@ -20,6 +21,7 @@ public:
void reset();
void sceneStarted(bool fullScene, bool moving);
void sceneCompleted();
void printDebugDetails();
void packetSent(int bytes);
@ -41,8 +43,18 @@ public:
int packIntoMessage(unsigned char* destinationBuffer, int availableBytes);
int unpackFromMessage(unsigned char* sourceBuffer, int availableBytes);
bool readyToSend() const { return _readyToSend; }
void markAsSent() { _readyToSend = false; }
unsigned char* getStatsMessage() { return &_statsMessage[0]; }
int getStatsMessageLength() const { return _statsMessageLength; }
private:
bool _readyToSend;
unsigned char _statsMessage[MAX_PACKET_SIZE];
int _statsMessageLength;
// scene timing data in usecs
uint64_t _start;
uint64_t _end;

View file

@ -112,6 +112,44 @@ void eraseVoxelTreeAndCleanupNodeVisitData() {
pthread_mutex_t treeLock;
void handlePacketSend(NodeList* nodeList,
NodeList::iterator& node,
VoxelNodeData* nodeData,
int& trueBytesSent, int& truePacketsSent) {
// If we've got a stats message ready to send, then see if we can piggyback them together
if (nodeData->stats.readyToSend()) {
// Send the stats message to the client
unsigned char* statsMessage = nodeData->stats.getStatsMessage();
int statsMessageLength = nodeData->stats.getStatsMessageLength();
// If the size of the stats message and the voxel message will fit in a packet, then piggyback them
if (nodeData->getPacketLength() + statsMessageLength < MAX_PACKET_SIZE) {
// copy voxel message to back of stats message
memcpy(statsMessage + statsMessageLength, nodeData->getPacket(), nodeData->getPacketLength());
statsMessageLength += nodeData->getPacketLength();
// actually send it
nodeList->getNodeSocket()->send(node->getActiveSocket(), statsMessage, statsMessageLength);
} else {
// not enough room in the packet, send two packets
nodeList->getNodeSocket()->send(node->getActiveSocket(), statsMessage, statsMessageLength);
nodeList->getNodeSocket()->send(node->getActiveSocket(),
nodeData->getPacket(), nodeData->getPacketLength());
}
} else {
// just send the voxel packet
nodeList->getNodeSocket()->send(node->getActiveSocket(),
nodeData->getPacket(), nodeData->getPacketLength());
}
// remember to track our stats
nodeData->stats.packetSent(nodeData->getPacketLength());
trueBytesSent += nodeData->getPacketLength();
truePacketsSent++;
nodeData->resetVoxelPacket();
}
// Version of voxel distributor that sends the deepest LOD level at once
void deepestLevelVoxelDistributor(NodeList* nodeList,
NodeList::iterator& node,
@ -142,12 +180,9 @@ void deepestLevelVoxelDistributor(NodeList* nodeList,
printf("wantColor=%s --- SENDING PARTIAL PACKET! nodeData->getCurrentPacketIsColor()=%s\n",
debug::valueOf(wantColor), debug::valueOf(nodeData->getCurrentPacketIsColor()));
}
nodeList->getNodeSocket()->send(node->getActiveSocket(),
nodeData->getPacket(), nodeData->getPacketLength());
nodeData->stats.packetSent(nodeData->getPacketLength());
trueBytesSent += nodeData->getPacketLength();
truePacketsSent++;
nodeData->resetVoxelPacket();
handlePacketSend(nodeList, node, nodeData, trueBytesSent, truePacketsSent);
} else {
if (::debugVoxelSending) {
printf("wantColor=%s --- FIXING HEADER! nodeData->getCurrentPacketIsColor()=%s\n",
@ -209,11 +244,6 @@ void deepestLevelVoxelDistributor(NodeList* nodeList,
if (::displayVoxelStats) {
nodeData->stats.printDebugDetails();
}
// Send the stats message to the client
unsigned char statsMessage[MAX_PACKET_SIZE];
int statsMessageLength = nodeData->stats.packIntoMessage(statsMessage, sizeof(statsMessage));
nodeList->getNodeSocket()->send(node->getActiveSocket(), statsMessage, statsMessageLength);
// This is the start of "resending" the scene.
nodeData->nodeBag.insert(serverTree.rootNode);
@ -271,22 +301,14 @@ void deepestLevelVoxelDistributor(NodeList* nodeList,
if (nodeData->getAvailable() >= bytesWritten) {
nodeData->writeToPacket(&tempOutputBuffer[0], bytesWritten);
} else {
nodeList->getNodeSocket()->send(node->getActiveSocket(),
nodeData->getPacket(), nodeData->getPacketLength());
nodeData->stats.packetSent(nodeData->getPacketLength());
trueBytesSent += nodeData->getPacketLength();
truePacketsSent++;
handlePacketSend(nodeList, node, nodeData, trueBytesSent, truePacketsSent);
packetsSentThisInterval++;
nodeData->resetVoxelPacket();
nodeData->writeToPacket(&tempOutputBuffer[0], bytesWritten);
}
} else {
if (nodeData->isPacketWaiting()) {
nodeList->getNodeSocket()->send(node->getActiveSocket(),
nodeData->getPacket(), nodeData->getPacketLength());
nodeData->stats.packetSent(nodeData->getPacketLength());
trueBytesSent += nodeData->getPacketLength();
truePacketsSent++;
handlePacketSend(nodeList, node, nodeData, trueBytesSent, truePacketsSent);
nodeData->resetVoxelPacket();
}
packetsSentThisInterval = PACKETS_PER_CLIENT_PER_INTERVAL; // done for now, no nodes left