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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -20,6 +20,7 @@
#include "JurisdictionMap.h" #include "JurisdictionMap.h"
#include "OctreePacketData.h" #include "OctreePacketData.h"
#include "SequenceNumberStats.h" #include "SequenceNumberStats.h"
#include "OctalCode.h"
#define GREENISH 0x40ff40d0 #define GREENISH 0x40ff40d0
#define YELLOWISH 0xffef40c0 #define YELLOWISH 0xffef40c0
@ -143,10 +144,10 @@ public:
const char* getItemValue(Item item); const char* getItemValue(Item item);
/// Returns OctCode for root element of the jurisdiction of this particular octree server /// 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 /// 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 isMoving() const { return _isMoving; }
bool isFullScene() const { return _isFullScene; } bool isFullScene() const { return _isFullScene; }
@ -277,8 +278,8 @@ private:
static const int MAX_ITEM_VALUE_LENGTH = 128; static const int MAX_ITEM_VALUE_LENGTH = 128;
char _itemValueBuffer[MAX_ITEM_VALUE_LENGTH]; char _itemValueBuffer[MAX_ITEM_VALUE_LENGTH];
unsigned char* _jurisdictionRoot; OctalCodePtr _jurisdictionRoot;
std::vector<unsigned char*> _jurisdictionEndNodes; std::vector<OctalCodePtr> _jurisdictionEndNodes;
}; };
/// Map between element IDs and their reported OctreeSceneStats. Typically used by classes that need to know which elements sent /// 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; 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_NUMBER_BASE = 16;
const int HEX_BYTE_SIZE = 2; const int HEX_BYTE_SIZE = 2;
int stringIndex = 0; int stringIndex = 0;
int byteArrayIndex = 0; int byteArrayIndex = 0;
// allocate byte array based on half of string length // 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 // loop through the string - 2 bytes at a time converting
// it to decimal equivalent and store in byte array // it to decimal equivalent and store in byte array
@ -321,15 +321,14 @@ unsigned char* hexStringToOctalCode(const QString& input) {
if (!ok) { if (!ok) {
break; break;
} }
bytes[byteArrayIndex] = (unsigned char)value; bytes.get()[byteArrayIndex] = (unsigned char)value;
stringIndex += HEX_BYTE_SIZE; stringIndex += HEX_BYTE_SIZE;
byteArrayIndex++; byteArrayIndex++;
} }
// something went wrong // something went wrong
if (!ok) { if (!ok) {
delete[] bytes; return nullptr;
return NULL;
} }
return bytes; return bytes;
} }

View file

@ -12,9 +12,10 @@
#ifndef hifi_OctalCode_h #ifndef hifi_OctalCode_h
#define hifi_OctalCode_h #define hifi_OctalCode_h
#include <string.h>
#include <QString> #include <QString>
#include <memory>
const int BITS_IN_OCTAL = 3; const int BITS_IN_OCTAL = 3;
const int NUMBER_OF_COLORS = 3; // RGB! const int NUMBER_OF_COLORS = 3; // RGB!
const int SIZE_OF_COLOR_DATA = NUMBER_OF_COLORS * sizeof(unsigned char); // size in bytes 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 GREEN_INDEX = 1;
const int BLUE_INDEX = 2; const int BLUE_INDEX = 2;
using OctalCodePtr = std::shared_ptr<unsigned char>;
void printOctalCode(const unsigned char* octalCode); void printOctalCode(const unsigned char* octalCode);
size_t bytesRequiredForCodeLength(unsigned char threeBitCodes); size_t bytesRequiredForCodeLength(unsigned char threeBitCodes);
int branchIndexWithDescendant(const unsigned char* ancestorOctalCode, const unsigned char* descendantOctalCode); 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); OctalCodeComparison compareOctalCodes(const unsigned char* code1, const unsigned char* code2);
QString octalCodeToHexString(const unsigned char* octalCode); 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 #endif // hifi_OctalCode_h