Fix JurisdictionMap multithreading issues

Make octal code pointers use shared_ptr, add locks around access.
This commit is contained in:
Ryan Huffman 2016-05-10 10:30:38 -07:00
parent 34e574c148
commit ef6d758e7f
9 changed files with 138 additions and 216 deletions

View file

@ -3656,11 +3656,11 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node
} else {
const JurisdictionMap& map = (jurisdictions)[nodeUUID];
unsigned char* rootCode = map.getRootOctalCode();
auto rootCode = map.getRootOctalCode();
if (rootCode) {
VoxelPositionSize rootDetails;
voxelDetailsForCode(rootCode, rootDetails);
voxelDetailsForCode(rootCode.get(), rootDetails);
AACube serverBounds(glm::vec3(rootDetails.x * TREE_SCALE,
rootDetails.y * TREE_SCALE,
rootDetails.z * TREE_SCALE) - glm::vec3(HALF_TREE_SCALE),
@ -3720,11 +3720,11 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node
} else {
const JurisdictionMap& map = (jurisdictions)[nodeUUID];
unsigned char* rootCode = map.getRootOctalCode();
auto rootCode = map.getRootOctalCode();
if (rootCode) {
VoxelPositionSize rootDetails;
voxelDetailsForCode(rootCode, rootDetails);
voxelDetailsForCode(rootCode.get(), rootDetails);
AACube serverBounds(glm::vec3(rootDetails.x * TREE_SCALE,
rootDetails.y * TREE_SCALE,
rootDetails.z * TREE_SCALE) - glm::vec3(HALF_TREE_SCALE),
@ -4251,9 +4251,9 @@ void Application::nodeKilled(SharedNodePointer node) {
return;
}
unsigned char* rootCode = _entityServerJurisdictions[nodeUUID].getRootOctalCode();
auto rootCode = _entityServerJurisdictions[nodeUUID].getRootOctalCode();
VoxelPositionSize rootDetails;
voxelDetailsForCode(rootCode, rootDetails);
voxelDetailsForCode(rootCode.get(), rootDetails);
qCDebug(interfaceapp, "model server going away...... v[%f, %f, %f, %f]",
(double)rootDetails.x, (double)rootDetails.y, (double)rootDetails.z, (double)rootDetails.s);
@ -4378,7 +4378,7 @@ int Application::processOctreeStats(ReceivedMessage& message, SharedNodePointer
}
VoxelPositionSize rootDetails;
voxelDetailsForCode(octreeStats.getJurisdictionRoot(), rootDetails);
voxelDetailsForCode(octreeStats.getJurisdictionRoot().get(), rootDetails);
qCDebug(interfaceapp, "stats from new %s server... [%f, %f, %f, %f]",
qPrintable(serverType),

View file

@ -433,13 +433,13 @@ void OctreeStatsDialog::showOctreeServersOfType(int& serverCount, NodeType_t ser
}
const JurisdictionMap& map = serverJurisdictions[nodeUUID];
unsigned char* rootCode = map.getRootOctalCode();
auto rootCode = map.getRootOctalCode();
if (rootCode) {
QString rootCodeHex = octalCodeToHexString(rootCode);
QString rootCodeHex = octalCodeToHexString(rootCode.get());
VoxelPositionSize rootDetails;
voxelDetailsForCode(rootCode, rootDetails);
voxelDetailsForCode(rootCode.get(), rootDetails);
AACube serverBounds(glm::vec3(rootDetails.x, rootDetails.y, rootDetails.z), rootDetails.s);
serverDetails << " jurisdiction: "
<< qPrintable(rootCodeHex)

View file

@ -17,90 +17,11 @@
#include <DependencyManager.h>
#include <NodeList.h>
#include <udt/PacketHeaders.h>
#include <OctalCode.h>
#include "OctreeLogging.h"
#include "JurisdictionMap.h"
// standard assignment
// copy assignment
JurisdictionMap& JurisdictionMap::operator=(const JurisdictionMap& other) {
copyContents(other);
return *this;
}
// Copy constructor
JurisdictionMap::JurisdictionMap(const JurisdictionMap& other) : _rootOctalCode(NULL) {
copyContents(other);
}
void JurisdictionMap::copyContents(unsigned char* rootCodeIn, const std::vector<unsigned char*>& endNodesIn) {
unsigned char* rootCode;
std::vector<unsigned char*> endNodes;
if (rootCodeIn) {
size_t bytes = bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(rootCodeIn));
rootCode = new unsigned char[bytes];
memcpy(rootCode, rootCodeIn, bytes);
} else {
rootCode = new unsigned char[1];
*rootCode = 0;
}
for (size_t i = 0; i < endNodesIn.size(); i++) {
if (endNodesIn[i]) {
size_t bytes = bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(endNodesIn[i]));
unsigned char* endNodeCode = new unsigned char[bytes];
memcpy(endNodeCode, endNodesIn[i], bytes);
endNodes.push_back(endNodeCode);
}
}
init(rootCode, endNodes);
}
void JurisdictionMap::copyContents(const JurisdictionMap& other) {
_nodeType = other._nodeType;
copyContents(other._rootOctalCode, other._endNodes);
}
JurisdictionMap::~JurisdictionMap() {
clear();
}
void JurisdictionMap::clear() {
if (_rootOctalCode) {
delete[] _rootOctalCode;
_rootOctalCode = NULL;
}
for (size_t i = 0; i < _endNodes.size(); i++) {
if (_endNodes[i]) {
delete[] _endNodes[i];
}
}
_endNodes.clear();
}
JurisdictionMap::JurisdictionMap(NodeType_t type) : _rootOctalCode(NULL) {
_nodeType = type;
unsigned char* rootCode = new unsigned char[1];
*rootCode = 0;
std::vector<unsigned char*> emptyEndNodes;
init(rootCode, emptyEndNodes);
}
JurisdictionMap::JurisdictionMap(const char* filename) : _rootOctalCode(NULL) {
clear(); // clean up our own memory
readFromFile(filename);
}
JurisdictionMap::JurisdictionMap(unsigned char* rootOctalCode, const std::vector<unsigned char*>& endNodes)
: _rootOctalCode(NULL) {
init(rootOctalCode, endNodes);
}
void myDebugoutputBits(unsigned char byte, bool withNewLine) {
void myDebugOutputBits(unsigned char byte, bool withNewLine) {
if (isalnum(byte)) {
printf("[ %d (%c): ", byte, byte);
} else {
@ -117,13 +38,12 @@ void myDebugoutputBits(unsigned char byte, bool withNewLine) {
}
}
void myDebugPrintOctalCode(const unsigned char* octalCode, bool withNewLine) {
if (!octalCode) {
printf("NULL");
printf("nullptr");
} else {
for (size_t i = 0; i < bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(octalCode)); i++) {
myDebugoutputBits(octalCode[i],false);
myDebugOutputBits(octalCode[i], false);
}
}
if (withNewLine) {
@ -131,16 +51,53 @@ void myDebugPrintOctalCode(const unsigned char* octalCode, bool withNewLine) {
}
}
// standard assignment
// copy assignment
JurisdictionMap& JurisdictionMap::operator=(const JurisdictionMap& other) {
copyContents(other);
return *this;
}
// Copy constructor
JurisdictionMap::JurisdictionMap(const JurisdictionMap& other) : _rootOctalCode(nullptr) {
copyContents(other);
}
void JurisdictionMap::copyContents(const OctalCodePtr& rootCodeIn, const std::vector<OctalCodePtr>& endNodesIn) {
init(rootCodeIn, endNodesIn);
}
void JurisdictionMap::copyContents(const JurisdictionMap& other) {
_nodeType = other._nodeType;
init(other.getRootOctalCode(), other.getEndNodeOctalCodes());
}
JurisdictionMap::~JurisdictionMap() {
}
JurisdictionMap::JurisdictionMap(NodeType_t type) : _rootOctalCode(nullptr) {
_nodeType = type;
auto rootCode = std::shared_ptr<unsigned char>(new unsigned char[1], std::default_delete<unsigned char[]>());
*rootCode = 0;
std::vector<OctalCodePtr> emptyEndNodes;
init(rootCode, emptyEndNodes);
}
JurisdictionMap::JurisdictionMap(const char* filename) : _rootOctalCode(nullptr) {
readFromFile(filename);
}
JurisdictionMap::JurisdictionMap(const char* rootHexCode, const char* endNodesHexCodes) {
qCDebug(octree, "JurisdictionMap::JurisdictionMap(const char* rootHexCode=[%p] %s, const char* endNodesHexCodes=[%p] %s)",
rootHexCode, rootHexCode, endNodesHexCodes, endNodesHexCodes);
_rootOctalCode = hexStringToOctalCode(QString(rootHexCode));
_rootOctalCode = std::shared_ptr<unsigned char>(hexStringToOctalCode(QString(rootHexCode)));
qCDebug(octree, "JurisdictionMap::JurisdictionMap() _rootOctalCode=%p octalCode=", _rootOctalCode);
myDebugPrintOctalCode(_rootOctalCode, true);
qCDebug(octree, "JurisdictionMap::JurisdictionMap() _rootOctalCode=%p octalCode=", _rootOctalCode.get());
myDebugPrintOctalCode(_rootOctalCode.get(), true);
QString endNodesHexStrings(endNodesHexCodes);
QString delimiterPattern(",");
@ -149,7 +106,7 @@ JurisdictionMap::JurisdictionMap(const char* rootHexCode, const char* endNodesHe
for (int i = 0; i < endNodeList.size(); i++) {
QString endNodeHexString = endNodeList.at(i);
unsigned char* endNodeOctcode = hexStringToOctalCode(endNodeHexString);
auto endNodeOctcode = hexStringToOctalCode(endNodeHexString);
qCDebug(octree, "JurisdictionMap::JurisdictionMap() endNodeList(%d)=%s",
i, endNodeHexString.toLocal8Bit().constData());
@ -158,14 +115,14 @@ JurisdictionMap::JurisdictionMap(const char* rootHexCode, const char* endNodesHe
_endNodes.push_back(endNodeOctcode);
qCDebug(octree, "JurisdictionMap::JurisdictionMap() endNodeOctcode=%p octalCode=", endNodeOctcode);
myDebugPrintOctalCode(endNodeOctcode, true);
myDebugPrintOctalCode(endNodeOctcode.get(), true);
}
}
void JurisdictionMap::init(unsigned char* rootOctalCode, const std::vector<unsigned char*>& endNodes) {
clear(); // clean up our own memory
void JurisdictionMap::init(OctalCodePtr rootOctalCode, const std::vector<OctalCodePtr>& endNodes) {
std::lock_guard<std::mutex> lock(_octalCodeMutex);
_rootOctalCode = rootOctalCode;
_endNodes = endNodes;
}
@ -173,17 +130,19 @@ void JurisdictionMap::init(unsigned char* rootOctalCode, const std::vector<unsig
JurisdictionMap::Area JurisdictionMap::isMyJurisdiction(const unsigned char* nodeOctalCode, int childIndex) const {
// to be in our jurisdiction, we must be under the root...
std::lock_guard<std::mutex> lock(_octalCodeMutex);
// if the node is an ancestor of my root, then we return ABOVE
if (isAncestorOf(nodeOctalCode, _rootOctalCode)) {
if (isAncestorOf(nodeOctalCode, _rootOctalCode.get())) {
return ABOVE;
}
// otherwise...
bool isInJurisdiction = isAncestorOf(_rootOctalCode, nodeOctalCode, childIndex);
bool isInJurisdiction = isAncestorOf(_rootOctalCode.get(), nodeOctalCode, childIndex);
// if we're under the root, then we can't be under any of the endpoints
if (isInJurisdiction) {
for (size_t i = 0; i < _endNodes.size(); i++) {
bool isUnderEndNode = isAncestorOf(_endNodes[i], nodeOctalCode);
bool isUnderEndNode = isAncestorOf(_endNodes[i].get(), nodeOctalCode);
if (isUnderEndNode) {
isInJurisdiction = false;
break;
@ -200,8 +159,9 @@ bool JurisdictionMap::readFromFile(const char* filename) {
QString rootCode = settings.value("root","00").toString();
qCDebug(octree) << "rootCode=" << rootCode;
_rootOctalCode = hexStringToOctalCode(rootCode);
printOctalCode(_rootOctalCode);
std::lock_guard<std::mutex> lock(_octalCodeMutex);
_rootOctalCode = std::shared_ptr<unsigned char>(hexStringToOctalCode(rootCode));
printOctalCode(_rootOctalCode.get());
settings.beginGroup("endNodes");
const QStringList childKeys = settings.childKeys();
@ -211,8 +171,8 @@ bool JurisdictionMap::readFromFile(const char* filename) {
values.insert(childKey, childValue);
qCDebug(octree) << childKey << "=" << childValue;
unsigned char* octcode = hexStringToOctalCode(childValue);
printOctalCode(octcode);
auto octcode = hexStringToOctalCode(childValue);
printOctalCode(octcode.get());
_endNodes.push_back(octcode);
}
@ -221,30 +181,34 @@ bool JurisdictionMap::readFromFile(const char* filename) {
}
void JurisdictionMap::displayDebugDetails() const {
QString rootNodeValue = octalCodeToHexString(_rootOctalCode);
std::lock_guard<std::mutex> lock(_octalCodeMutex);
QString rootNodeValue = octalCodeToHexString(_rootOctalCode.get());
qCDebug(octree) << "root:" << rootNodeValue;
for (size_t i = 0; i < _endNodes.size(); i++) {
QString value = octalCodeToHexString(_endNodes[i]);
QString value = octalCodeToHexString(_endNodes[i].get());
qCDebug(octree) << "End node[" << i << "]: " << rootNodeValue;
}
}
bool JurisdictionMap::writeToFile(const char* filename) {
std::lock_guard<std::mutex> lock(_octalCodeMutex);
QString settingsFile(filename);
QSettings settings(settingsFile, QSettings::IniFormat);
QString rootNodeValue = octalCodeToHexString(_rootOctalCode);
QString rootNodeValue = octalCodeToHexString(_rootOctalCode.get());
settings.setValue("root", rootNodeValue);
settings.beginGroup("endNodes");
for (size_t i = 0; i < _endNodes.size(); i++) {
QString key = QString("endnode%1").arg(i);
QString value = octalCodeToHexString(_endNodes[i]);
QString value = octalCodeToHexString(_endNodes[i].get());
settings.setValue(key, value);
}
settings.endGroup();
@ -271,18 +235,19 @@ std::unique_ptr<NLPacket> JurisdictionMap::packIntoPacket() {
packet->writePrimitive(type);
// add the root jurisdiction
std::lock_guard<std::mutex> lock(_octalCodeMutex);
if (_rootOctalCode) {
size_t bytes = bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(_rootOctalCode));
size_t bytes = bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(_rootOctalCode.get()));
// No root or end node details to pack!
packet->writePrimitive(bytes);
packet->write(reinterpret_cast<char*>(_rootOctalCode), bytes);
packet->write(reinterpret_cast<char*>(_rootOctalCode.get()), bytes);
// if and only if there's a root jurisdiction, also include the end nodes
int endNodeCount = (int)_endNodes.size();
packet->writePrimitive(endNodeCount);
for (int i=0; i < endNodeCount; i++) {
unsigned char* endNodeCode = _endNodes[i];
auto endNodeCode = _endNodes[i].get();
size_t bytes = 0;
if (endNodeCode) {
bytes = bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(endNodeCode));
@ -299,15 +264,17 @@ std::unique_ptr<NLPacket> JurisdictionMap::packIntoPacket() {
}
int JurisdictionMap::unpackFromPacket(ReceivedMessage& message) {
clear();
// read the root jurisdiction
int bytes = 0;
message.readPrimitive(&bytes);
std::lock_guard<std::mutex> lock(_octalCodeMutex);
_rootOctalCode = nullptr;
_endNodes.clear();
if (bytes > 0 && bytes <= message.getBytesLeftToRead()) {
_rootOctalCode = new unsigned char[bytes];
message.read(reinterpret_cast<char*>(_rootOctalCode), bytes);
_rootOctalCode = std::shared_ptr<unsigned char>(new unsigned char[bytes], std::default_delete<unsigned char[]>());
message.read(reinterpret_cast<char*>(_rootOctalCode.get()), bytes);
// if and only if there's a root jurisdiction, also include the end nodes
int endNodeCount = 0;
@ -318,8 +285,8 @@ int JurisdictionMap::unpackFromPacket(ReceivedMessage& message) {
message.readPrimitive(&bytes);
if (bytes <= message.getBytesLeftToRead()) {
unsigned char* endNodeCode = new unsigned char[bytes];
message.read(reinterpret_cast<char*>(endNodeCode), bytes);
auto endNodeCode = std::shared_ptr<unsigned char>(new unsigned char[bytes], std::default_delete<unsigned char[]>());
message.read(reinterpret_cast<char*>(endNodeCode.get()), bytes);
// if the endNodeCode was 0 length then don't add it
if (bytes > 0) {

View file

@ -23,6 +23,7 @@
#include <NLPacket.h>
#include <Node.h>
#include <OctalCode.h>
class JurisdictionMap {
public:
@ -41,7 +42,7 @@ public:
// application constructors
JurisdictionMap(const char* filename);
JurisdictionMap(unsigned char* rootOctalCode, const std::vector<unsigned char*>& endNodes);
// JurisdictionMap(unsigned char* rootOctalCode, const std::vector<unsigned char*>& endNodes);
JurisdictionMap(const char* rootHextString, const char* endNodesHextString);
~JurisdictionMap();
@ -50,11 +51,10 @@ public:
bool writeToFile(const char* filename);
bool readFromFile(const char* filename);
unsigned char* getRootOctalCode() const { return _rootOctalCode; }
unsigned char* getEndNodeOctalCode(int index) const { return _endNodes[index]; }
int getEndNodeCount() const { return (int)_endNodes.size(); }
OctalCodePtr getRootOctalCode() const { return _rootOctalCode; }
std::vector<OctalCodePtr> getEndNodeOctalCodes() const { return _endNodes; }
void copyContents(unsigned char* rootCodeIn, const std::vector<unsigned char*>& endNodesIn);
void copyContents(const OctalCodePtr& rootCodeIn, const std::vector<OctalCodePtr>& endNodesIn);
int unpackFromPacket(ReceivedMessage& message);
std::unique_ptr<NLPacket> packIntoPacket();
@ -69,11 +69,11 @@ public:
private:
void copyContents(const JurisdictionMap& other); // use assignment instead
void clear();
void init(unsigned char* rootOctalCode, const std::vector<unsigned char*>& endNodes);
void init(OctalCodePtr rootOctalCode, const std::vector<OctalCodePtr>& endNodes);
unsigned char* _rootOctalCode;
std::vector<unsigned char*> _endNodes;
mutable std::mutex _octalCodeMutex;
OctalCodePtr _rootOctalCode { nullptr };
std::vector<OctalCodePtr> _endNodes;
NodeType_t _nodeType;
};

View file

@ -78,12 +78,12 @@ void OctreeHeadlessViewer::queryOctree() {
}
const JurisdictionMap& map = (jurisdictions)[nodeUUID];
unsigned char* rootCode = map.getRootOctalCode();
auto rootCode = map.getRootOctalCode();
if (!rootCode) {
return;
}
voxelDetailsForCode(rootCode, rootDetails);
voxelDetailsForCode(rootCode.get(), rootDetails);
foundRootDetails = true;
});
@ -146,7 +146,7 @@ void OctreeHeadlessViewer::queryOctree() {
}
const JurisdictionMap& map = (jurisdictions)[nodeUUID];
unsigned char* rootCode = map.getRootOctalCode();
auto rootCode = map.getRootOctalCode();
if (!rootCode) {
if (wantExtraDebugging) {
@ -154,7 +154,7 @@ void OctreeHeadlessViewer::queryOctree() {
}
return;
}
voxelDetailsForCode(rootCode, rootDetails);
voxelDetailsForCode(rootCode.get(), rootDetails);
foundRootDetails = true;
});

View file

@ -110,29 +110,21 @@ void OctreeSceneStats::copyFromOther(const OctreeSceneStats& other) {
_treesRemoved = other._treesRemoved;
// before copying the jurisdictions, delete any current values...
if (_jurisdictionRoot) {
delete[] _jurisdictionRoot;
_jurisdictionRoot = NULL;
}
for (size_t i = 0; i < _jurisdictionEndNodes.size(); i++) {
if (_jurisdictionEndNodes[i]) {
delete[] _jurisdictionEndNodes[i];
}
}
_jurisdictionRoot = nullptr;
_jurisdictionEndNodes.clear();
// Now copy the values from the other
if (other._jurisdictionRoot) {
auto bytes = bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(other._jurisdictionRoot));
_jurisdictionRoot = new unsigned char[bytes];
memcpy(_jurisdictionRoot, other._jurisdictionRoot, bytes);
auto bytes = bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(other._jurisdictionRoot.get()));
_jurisdictionRoot = OctalCodePtr(new unsigned char[bytes]);
memcpy(_jurisdictionRoot.get(), other._jurisdictionRoot.get(), bytes);
}
for (size_t i = 0; i < other._jurisdictionEndNodes.size(); i++) {
unsigned char* endNodeCode = other._jurisdictionEndNodes[i];
auto& endNodeCode = other._jurisdictionEndNodes[i];
if (endNodeCode) {
auto bytes = bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(endNodeCode));
unsigned char* endNodeCodeCopy = new unsigned char[bytes];
memcpy(endNodeCodeCopy, endNodeCode, bytes);
auto bytes = bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(endNodeCode.get()));
auto endNodeCodeCopy = OctalCodePtr(new unsigned char[bytes]);
memcpy(endNodeCodeCopy.get(), endNodeCode.get(), bytes);
_jurisdictionEndNodes.push_back(endNodeCodeCopy);
}
}
@ -162,37 +154,15 @@ void OctreeSceneStats::sceneStarted(bool isFullScene, bool isMoving, OctreeEleme
_isFullScene = isFullScene;
_isMoving = isMoving;
if (_jurisdictionRoot) {
delete[] _jurisdictionRoot;
_jurisdictionRoot = NULL;
}
_jurisdictionRoot = nullptr;
// clear existing endNodes before copying new ones...
for (size_t i=0; i < _jurisdictionEndNodes.size(); i++) {
if (_jurisdictionEndNodes[i]) {
delete[] _jurisdictionEndNodes[i];
}
}
_jurisdictionEndNodes.clear();
// setup jurisdictions
if (jurisdictionMap) {
unsigned char* jurisdictionRoot = jurisdictionMap->getRootOctalCode();
if (jurisdictionRoot) {
auto bytes = bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(jurisdictionRoot));
_jurisdictionRoot = new unsigned char[bytes];
memcpy(_jurisdictionRoot, jurisdictionRoot, bytes);
}
// copy new endNodes...
for (int i = 0; i < jurisdictionMap->getEndNodeCount(); i++) {
unsigned char* endNodeCode = jurisdictionMap->getEndNodeOctalCode(i);
if (endNodeCode) {
auto bytes = bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(endNodeCode));
unsigned char* endNodeCodeCopy = new unsigned char[bytes];
memcpy(endNodeCodeCopy, endNodeCode, bytes);
_jurisdictionEndNodes.push_back(endNodeCodeCopy);
}
}
_jurisdictionRoot = jurisdictionMap->getRootOctalCode();
_jurisdictionEndNodes = jurisdictionMap->getEndNodeOctalCodes();
}
}
@ -270,15 +240,7 @@ void OctreeSceneStats::reset() {
_existsInPacketBitsWritten = 0;
_treesRemoved = 0;
if (_jurisdictionRoot) {
delete[] _jurisdictionRoot;
_jurisdictionRoot = NULL;
}
for (size_t i = 0; i < _jurisdictionEndNodes.size(); i++) {
if (_jurisdictionEndNodes[i]) {
delete[] _jurisdictionEndNodes[i];
}
}
_jurisdictionRoot = nullptr;
_jurisdictionEndNodes.clear();
}
@ -418,9 +380,9 @@ int OctreeSceneStats::packIntoPacket() {
// add the root jurisdiction
if (_jurisdictionRoot) {
// copy the
int bytes = (int)bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(_jurisdictionRoot));
int bytes = (int)bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(_jurisdictionRoot.get()));
_statsPacket->writePrimitive(bytes);
_statsPacket->write(reinterpret_cast<char*>(_jurisdictionRoot), bytes);
_statsPacket->write(reinterpret_cast<char*>(_jurisdictionRoot.get()), bytes);
// if and only if there's a root jurisdiction, also include the end elements
int endNodeCount = (int)_jurisdictionEndNodes.size();
@ -428,10 +390,10 @@ int OctreeSceneStats::packIntoPacket() {
_statsPacket->writePrimitive(endNodeCount);
for (int i=0; i < endNodeCount; i++) {
unsigned char* endNodeCode = _jurisdictionEndNodes[i];
auto bytes = bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(endNodeCode));
auto& endNodeCode = _jurisdictionEndNodes[i];
auto bytes = bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(endNodeCode.get()));
_statsPacket->writePrimitive(bytes);
_statsPacket->write(reinterpret_cast<char*>(endNodeCode), bytes);
_statsPacket->write(reinterpret_cast<char*>(endNodeCode.get()), bytes);
}
} else {
int bytes = 0;
@ -500,17 +462,7 @@ int OctreeSceneStats::unpackFromPacket(ReceivedMessage& packet) {
packet.readPrimitive(&_existsInPacketBitsWritten);
packet.readPrimitive(&_treesRemoved);
// before allocating new juridiction, clean up existing ones
if (_jurisdictionRoot) {
delete[] _jurisdictionRoot;
_jurisdictionRoot = NULL;
}
// clear existing endNodes before copying new ones...
for (size_t i = 0; i < _jurisdictionEndNodes.size(); i++) {
if (_jurisdictionEndNodes[i]) {
delete[] _jurisdictionEndNodes[i];
}
}
_jurisdictionRoot = nullptr;
_jurisdictionEndNodes.clear();
// read the root jurisdiction
@ -518,11 +470,11 @@ int OctreeSceneStats::unpackFromPacket(ReceivedMessage& packet) {
packet.readPrimitive(&bytes);
if (bytes == 0) {
_jurisdictionRoot = NULL;
_jurisdictionRoot = nullptr;
_jurisdictionEndNodes.clear();
} else {
_jurisdictionRoot = new unsigned char[bytes];
packet.read(reinterpret_cast<char*>(_jurisdictionRoot), bytes);
_jurisdictionRoot = OctalCodePtr(new unsigned char[bytes]);
packet.read(reinterpret_cast<char*>(_jurisdictionRoot.get()), bytes);
// if and only if there's a root jurisdiction, also include the end elements
_jurisdictionEndNodes.clear();
@ -535,8 +487,8 @@ int OctreeSceneStats::unpackFromPacket(ReceivedMessage& packet) {
packet.readPrimitive(&bytes);
unsigned char* endNodeCode = new unsigned char[bytes];
packet.read(reinterpret_cast<char*>(endNodeCode), bytes);
auto endNodeCode = OctalCodePtr(new unsigned char[bytes]);
packet.read(reinterpret_cast<char*>(endNodeCode.get()), bytes);
_jurisdictionEndNodes.push_back(endNodeCode);
}

View file

@ -20,6 +20,7 @@
#include "JurisdictionMap.h"
#include "OctreePacketData.h"
#include "SequenceNumberStats.h"
#include "OctalCode.h"
#define GREENISH 0x40ff40d0
#define YELLOWISH 0xffef40c0
@ -143,10 +144,10 @@ public:
const char* getItemValue(Item item);
/// Returns OctCode for root element of the jurisdiction of this particular octree server
unsigned char* getJurisdictionRoot() const { return _jurisdictionRoot; }
OctalCodePtr getJurisdictionRoot() const { return _jurisdictionRoot; }
/// Returns list of OctCodes for end elements of the jurisdiction of this particular octree server
const std::vector<unsigned char*>& getJurisdictionEndNodes() const { return _jurisdictionEndNodes; }
const std::vector<OctalCodePtr>& getJurisdictionEndNodes() const { return _jurisdictionEndNodes; }
bool isMoving() const { return _isMoving; }
bool isFullScene() const { return _isFullScene; }
@ -277,8 +278,8 @@ private:
static const int MAX_ITEM_VALUE_LENGTH = 128;
char _itemValueBuffer[MAX_ITEM_VALUE_LENGTH];
unsigned char* _jurisdictionRoot;
std::vector<unsigned char*> _jurisdictionEndNodes;
OctalCodePtr _jurisdictionRoot;
std::vector<OctalCodePtr> _jurisdictionEndNodes;
};
/// Map between element IDs and their reported OctreeSceneStats. Typically used by classes that need to know which elements sent

View file

@ -304,14 +304,14 @@ bool isAncestorOf(const unsigned char* possibleAncestor, const unsigned char* po
return true;
}
unsigned char* hexStringToOctalCode(const QString& input) {
std::shared_ptr<unsigned char> hexStringToOctalCode(const QString& input) {
const int HEX_NUMBER_BASE = 16;
const int HEX_BYTE_SIZE = 2;
int stringIndex = 0;
int byteArrayIndex = 0;
// allocate byte array based on half of string length
unsigned char* bytes = new unsigned char[(input.length()) / HEX_BYTE_SIZE];
auto bytes = std::shared_ptr<unsigned char>(new unsigned char[(input.length()) / HEX_BYTE_SIZE]);
// loop through the string - 2 bytes at a time converting
// it to decimal equivalent and store in byte array
@ -321,15 +321,14 @@ unsigned char* hexStringToOctalCode(const QString& input) {
if (!ok) {
break;
}
bytes[byteArrayIndex] = (unsigned char)value;
bytes.get()[byteArrayIndex] = (unsigned char)value;
stringIndex += HEX_BYTE_SIZE;
byteArrayIndex++;
}
// something went wrong
if (!ok) {
delete[] bytes;
return NULL;
return nullptr;
}
return bytes;
}

View file

@ -12,9 +12,10 @@
#ifndef hifi_OctalCode_h
#define hifi_OctalCode_h
#include <string.h>
#include <QString>
#include <memory>
const int BITS_IN_OCTAL = 3;
const int NUMBER_OF_COLORS = 3; // RGB!
const int SIZE_OF_COLOR_DATA = NUMBER_OF_COLORS * sizeof(unsigned char); // size in bytes
@ -22,6 +23,8 @@ const int RED_INDEX = 0;
const int GREEN_INDEX = 1;
const int BLUE_INDEX = 2;
using OctalCodePtr = std::shared_ptr<unsigned char>;
void printOctalCode(const unsigned char* octalCode);
size_t bytesRequiredForCodeLength(unsigned char threeBitCodes);
int branchIndexWithDescendant(const unsigned char* ancestorOctalCode, const unsigned char* descendantOctalCode);
@ -58,6 +61,6 @@ typedef enum {
OctalCodeComparison compareOctalCodes(const unsigned char* code1, const unsigned char* code2);
QString octalCodeToHexString(const unsigned char* octalCode);
unsigned char* hexStringToOctalCode(const QString& input);
std::shared_ptr<unsigned char> hexStringToOctalCode(const QString& input);
#endif // hifi_OctalCode_h