Use the existing session stuff for metavoxels rather than a separate system.

This commit is contained in:
Andrzej Kapolka 2014-02-13 10:25:10 -08:00
parent bb56e2847f
commit 9c91d3c2e7
6 changed files with 69 additions and 167 deletions

View file

@ -28,15 +28,16 @@ void MetavoxelServer::applyEdit(const MetavoxelEditMessage& edit) {
edit.apply(_data); edit.apply(_data);
} }
void MetavoxelServer::removeSession(const QUuid& sessionId) {
_sessions.take(sessionId)->deleteLater();
}
const char METAVOXEL_SERVER_LOGGING_NAME[] = "metavoxel-server"; const char METAVOXEL_SERVER_LOGGING_NAME[] = "metavoxel-server";
void MetavoxelServer::run() { void MetavoxelServer::run() {
commonInit(METAVOXEL_SERVER_LOGGING_NAME, NodeType::MetavoxelServer); commonInit(METAVOXEL_SERVER_LOGGING_NAME, NodeType::MetavoxelServer);
NodeList* nodeList = NodeList::getInstance();
nodeList->addNodeTypeToInterestSet(NodeType::Agent);
connect(nodeList, SIGNAL(nodeAdded(SharedNodePointer)), SLOT(maybeAttachSession(const SharedNodePointer&)));
_lastSend = QDateTime::currentMSecsSinceEpoch(); _lastSend = QDateTime::currentMSecsSinceEpoch();
_sendTimer.start(SEND_INTERVAL); _sendTimer.start(SEND_INTERVAL);
} }
@ -50,25 +51,31 @@ void MetavoxelServer::readPendingDatagrams() {
while (readAvailableDatagram(receivedPacket, senderSockAddr)) { while (readAvailableDatagram(receivedPacket, senderSockAddr)) {
if (nodeList->packetVersionAndHashMatch(receivedPacket)) { if (nodeList->packetVersionAndHashMatch(receivedPacket)) {
switch (packetTypeForPacket(receivedPacket)) { switch (packetTypeForPacket(receivedPacket)) {
case PacketTypeMetavoxelData: { case PacketTypeMetavoxelData:
SharedNodePointer matchingNode = nodeList->sendingNodeForPacket(receivedPacket); nodeList->findNodeAndUpdateWithDataFromPacket(receivedPacket);
if (matchingNode) {
processData(receivedPacket, matchingNode);
}
break; break;
}
default: default:
NodeList::getInstance()->processNodeData(senderSockAddr, receivedPacket); nodeList->processNodeData(senderSockAddr, receivedPacket);
break; break;
} }
} }
} }
} }
void MetavoxelServer::maybeAttachSession(const SharedNodePointer& node) {
if (node->getType() == NodeType::Agent) {
QMutexLocker locker(&node->getMutex());
node->setLinkedData(new MetavoxelSession(this, NodeList::getInstance()->nodeWithUUID(node->getUUID())));
}
}
void MetavoxelServer::sendDeltas() { void MetavoxelServer::sendDeltas() {
// send deltas for all sessions // send deltas for all sessions
foreach (MetavoxelSession* session, _sessions) { foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) {
session->sendDelta(); if (node->getType() == NodeType::Agent) {
static_cast<MetavoxelSession*>(node->getLinkedData())->sendDelta();
}
} }
// restart the send timer // restart the send timer
@ -79,35 +86,10 @@ void MetavoxelServer::sendDeltas() {
_sendTimer.start(qMax(0, 2 * SEND_INTERVAL - elapsed)); _sendTimer.start(qMax(0, 2 * SEND_INTERVAL - elapsed));
} }
void MetavoxelServer::processData(const QByteArray& data, const SharedNodePointer& sendingNode) { MetavoxelSession::MetavoxelSession(MetavoxelServer* server, const SharedNodePointer& node) :
// read the session id
int headerPlusIDSize;
QUuid sessionID = readSessionID(data, sendingNode, headerPlusIDSize);
if (sessionID.isNull()) {
return;
}
// forward to session, creating if necessary
MetavoxelSession*& session = _sessions[sessionID];
if (!session) {
session = new MetavoxelSession(this, sessionID, QByteArray::fromRawData(data.constData(), headerPlusIDSize),
sendingNode);
}
session->receivedData(data, sendingNode);
}
MetavoxelSession::MetavoxelSession(MetavoxelServer* server, const QUuid& sessionId,
const QByteArray& datagramHeader, const SharedNodePointer& sendingNode) :
QObject(server),
_server(server), _server(server),
_sessionId(sessionId), _sequencer(byteArrayWithPopluatedHeader(PacketTypeMetavoxelData)),
_sequencer(datagramHeader), _node(node) {
_sendingNode(sendingNode) {
const int TIMEOUT_INTERVAL = 30 * 1000;
_timeoutTimer.setInterval(TIMEOUT_INTERVAL);
_timeoutTimer.setSingleShot(true);
connect(&_timeoutTimer, SIGNAL(timeout()), SLOT(timedOut()));
connect(&_sequencer, SIGNAL(readyToWrite(const QByteArray&)), SLOT(sendData(const QByteArray&))); connect(&_sequencer, SIGNAL(readyToWrite(const QByteArray&)), SLOT(sendData(const QByteArray&)));
connect(&_sequencer, SIGNAL(readyToRead(Bitstream&)), SLOT(readPacket(Bitstream&))); connect(&_sequencer, SIGNAL(readyToRead(Bitstream&)), SLOT(readPacket(Bitstream&)));
@ -117,19 +99,15 @@ MetavoxelSession::MetavoxelSession(MetavoxelServer* server, const QUuid& session
// insert the baseline send record // insert the baseline send record
SendRecord record = { 0 }; SendRecord record = { 0 };
_sendRecords.append(record); _sendRecords.append(record);
qDebug() << "Opened session [sessionId=" << _sessionId << ", sendingNode=" << sendingNode << "]";
} }
void MetavoxelSession::receivedData(const QByteArray& data, const SharedNodePointer& sendingNode) { MetavoxelSession::~MetavoxelSession() {
// reset the timeout timer }
_timeoutTimer.start();
// save the most recent sender int MetavoxelSession::parseData(const QByteArray& packet) {
_sendingNode = sendingNode;
// process through sequencer // process through sequencer
_sequencer.receivedDatagram(data); _sequencer.receivedDatagram(packet);
return packet.size();
} }
void MetavoxelSession::sendDelta() { void MetavoxelSession::sendDelta() {
@ -143,13 +121,8 @@ void MetavoxelSession::sendDelta() {
_sendRecords.append(record); _sendRecords.append(record);
} }
void MetavoxelSession::timedOut() {
qDebug() << "Session timed out [sessionId=" << _sessionId << ", sendingNode=" << _sendingNode << "]";
_server->removeSession(_sessionId);
}
void MetavoxelSession::sendData(const QByteArray& data) { void MetavoxelSession::sendData(const QByteArray& data) {
NodeList::getInstance()->writeDatagram(data, _sendingNode); NodeList::getInstance()->writeDatagram(data, _node);
} }
void MetavoxelSession::readPacket(Bitstream& in) { void MetavoxelSession::readPacket(Bitstream& in) {
@ -164,11 +137,7 @@ void MetavoxelSession::clearSendRecordsBefore(int index) {
void MetavoxelSession::handleMessage(const QVariant& message) { void MetavoxelSession::handleMessage(const QVariant& message) {
int userType = message.userType(); int userType = message.userType();
if (userType == CloseSessionMessage::Type) { if (userType == ClientStateMessage::Type) {
qDebug() << "Session closed [sessionId=" << _sessionId << ", sendingNode=" << _sendingNode << "]";
_server->removeSession(_sessionId);
} else if (userType == ClientStateMessage::Type) {
ClientStateMessage state = message.value<ClientStateMessage>(); ClientStateMessage state = message.value<ClientStateMessage>();
_position = state.position; _position = state.position;

View file

@ -9,12 +9,9 @@
#ifndef __hifi__MetavoxelServer__ #ifndef __hifi__MetavoxelServer__
#define __hifi__MetavoxelServer__ #define __hifi__MetavoxelServer__
#include <QHash>
#include <QList> #include <QList>
#include <QTimer> #include <QTimer>
#include <QUuid>
#include <HifiSockAddr.h>
#include <ThreadedAssignment.h> #include <ThreadedAssignment.h>
#include <DatagramSequencer.h> #include <DatagramSequencer.h>
@ -35,45 +32,38 @@ public:
const MetavoxelData& getData() const { return _data; } const MetavoxelData& getData() const { return _data; }
void removeSession(const QUuid& sessionId);
virtual void run(); virtual void run();
virtual void readPendingDatagrams(); virtual void readPendingDatagrams();
private slots: private slots:
void maybeAttachSession(const SharedNodePointer& node);
void sendDeltas(); void sendDeltas();
private: private:
void processData(const QByteArray& data, const SharedNodePointer& sendingNode);
QTimer _sendTimer; QTimer _sendTimer;
qint64 _lastSend; qint64 _lastSend;
QHash<QUuid, MetavoxelSession*> _sessions;
MetavoxelData _data; MetavoxelData _data;
}; };
/// Contains the state of a single client session. /// Contains the state of a single client session.
class MetavoxelSession : public QObject { class MetavoxelSession : public NodeData {
Q_OBJECT Q_OBJECT
public: public:
MetavoxelSession(MetavoxelServer* server, const QUuid& sessionId, MetavoxelSession(MetavoxelServer* server, const SharedNodePointer& node);
const QByteArray& datagramHeader, const SharedNodePointer& sendingNode); virtual ~MetavoxelSession();
void receivedData(const QByteArray& data, const SharedNodePointer& sendingNode); virtual int parseData(const QByteArray& packet);
void sendDelta(); void sendDelta();
private slots: private slots:
void timedOut();
void sendData(const QByteArray& data); void sendData(const QByteArray& data);
void readPacket(Bitstream& in); void readPacket(Bitstream& in);
@ -91,12 +81,10 @@ private:
}; };
MetavoxelServer* _server; MetavoxelServer* _server;
QUuid _sessionId;
QTimer _timeoutTimer;
DatagramSequencer _sequencer; DatagramSequencer _sequencer;
SharedNodePointer _sendingNode; SharedNodePointer _node;
glm::vec3 _position; glm::vec3 _position;

View file

@ -94,7 +94,7 @@ void DatagramProcessor::processDatagrams() {
break; break;
} }
case PacketTypeMetavoxelData: case PacketTypeMetavoxelData:
application->_metavoxels.processData(incomingPacket, senderSockAddr); nodeList->findNodeAndUpdateWithDataFromPacket(incomingPacket);
break; break;
case PacketTypeBulkAvatarData: case PacketTypeBulkAvatarData:
case PacketTypeKillAvatar: case PacketTypeKillAvatar:

View file

@ -25,12 +25,6 @@ MetavoxelSystem::MetavoxelSystem() :
_buffer(QOpenGLBuffer::VertexBuffer) { _buffer(QOpenGLBuffer::VertexBuffer) {
} }
MetavoxelSystem::~MetavoxelSystem() {
for (QHash<QUuid, MetavoxelClient*>::const_iterator it = _clients.begin(); it != _clients.end(); it++) {
delete it.value();
}
}
void MetavoxelSystem::init() { void MetavoxelSystem::init() {
if (!_program.isLinked()) { if (!_program.isLinked()) {
switchToResourcesParentIfRequired(); switchToResourcesParentIfRequired();
@ -42,33 +36,35 @@ void MetavoxelSystem::init() {
// let the script cache know to use our common access manager // let the script cache know to use our common access manager
ScriptCache::getInstance()->setNetworkAccessManager(Application::getInstance()->getNetworkAccessManager()); ScriptCache::getInstance()->setNetworkAccessManager(Application::getInstance()->getNetworkAccessManager());
} }
NodeList* nodeList = NodeList::getInstance();
connect(nodeList, SIGNAL(nodeAdded(SharedNodePointer)), SLOT(nodeAdded(SharedNodePointer)));
connect(nodeList, SIGNAL(nodeKilled(SharedNodePointer)), SLOT(nodeKilled(SharedNodePointer)));
_buffer.setUsagePattern(QOpenGLBuffer::DynamicDraw); _buffer.setUsagePattern(QOpenGLBuffer::DynamicDraw);
_buffer.create(); _buffer.create();
connect(NodeList::getInstance(), SIGNAL(nodeAdded(SharedNodePointer)), SLOT(maybeAttachClient(const SharedNodePointer&)));
} }
void MetavoxelSystem::applyEdit(const MetavoxelEditMessage& edit) { void MetavoxelSystem::applyEdit(const MetavoxelEditMessage& edit) {
foreach (MetavoxelClient* client, _clients) { foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) {
client->applyEdit(edit); if (node->getType() == NodeType::MetavoxelServer) {
MetavoxelClient* client = static_cast<MetavoxelClient*>(node->getLinkedData());
if (client) {
client->applyEdit(edit);
}
}
} }
} }
void MetavoxelSystem::processData(const QByteArray& data, const HifiSockAddr& sender) {
QMetaObject::invokeMethod(this, "receivedData", Q_ARG(const QByteArray&, data), Q_ARG(const HifiSockAddr&, sender));
}
void MetavoxelSystem::simulate(float deltaTime) { void MetavoxelSystem::simulate(float deltaTime) {
// simulate the clients // simulate the clients
_points.clear(); _points.clear();
foreach (MetavoxelClient* client, _clients) { foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) {
client->simulate(deltaTime, _pointVisitor); if (node->getType() == NodeType::MetavoxelServer) {
MetavoxelClient* client = static_cast<MetavoxelClient*>(node->getLinkedData());
if (client) {
client->simulate(deltaTime, _pointVisitor);
}
}
} }
_buffer.bind(); _buffer.bind();
int bytes = _points.size() * sizeof(Point); int bytes = _points.size() * sizeof(Point);
if (_buffer.size() < bytes) { if (_buffer.size() < bytes) {
@ -120,39 +116,10 @@ void MetavoxelSystem::render() {
_program.release(); _program.release();
} }
void MetavoxelSystem::nodeAdded(SharedNodePointer node) { void MetavoxelSystem::maybeAttachClient(const SharedNodePointer& node) {
if (node->getType() == NodeType::MetavoxelServer) { if (node->getType() == NodeType::MetavoxelServer) {
QMetaObject::invokeMethod(this, "addClient", Q_ARG(const SharedNodePointer&, node)); QMutexLocker locker(&node->getMutex());
} node->setLinkedData(new MetavoxelClient(NodeList::getInstance()->nodeWithUUID(node->getUUID())));
}
void MetavoxelSystem::nodeKilled(SharedNodePointer node) {
if (node->getType() == NodeType::MetavoxelServer) {
QMetaObject::invokeMethod(this, "removeClient", Q_ARG(const QUuid&, node->getUUID()));
}
}
void MetavoxelSystem::addClient(const SharedNodePointer& node) {
MetavoxelClient* client = new MetavoxelClient(node);
_clients.insert(node->getUUID(), client);
_clientsBySessionID.insert(client->getSessionID(), client);
}
void MetavoxelSystem::removeClient(const QUuid& uuid) {
MetavoxelClient* client = _clients.take(uuid);
_clientsBySessionID.remove(client->getSessionID());
delete client;
}
void MetavoxelSystem::receivedData(const QByteArray& data, const SharedNodePointer& sendingNode) {
int headerPlusIDSize;
QUuid sessionID = readSessionID(data, sendingNode, headerPlusIDSize);
if (sessionID.isNull()) {
return;
}
MetavoxelClient* client = _clientsBySessionID.value(sessionID);
if (client) {
client->receivedData(data);
} }
} }
@ -179,16 +146,9 @@ bool MetavoxelSystem::PointVisitor::visit(MetavoxelInfo& info) {
return false; return false;
} }
static QByteArray createDatagramHeader(const QUuid& sessionID) {
QByteArray header = byteArrayWithPopluatedHeader(PacketTypeMetavoxelData);
header += sessionID.toRfc4122();
return header;
}
MetavoxelClient::MetavoxelClient(const SharedNodePointer& node) : MetavoxelClient::MetavoxelClient(const SharedNodePointer& node) :
_node(node), _node(node),
_sessionID(QUuid::createUuid()), _sequencer(byteArrayWithPopluatedHeader(PacketTypeMetavoxelData)) {
_sequencer(createDatagramHeader(_sessionID)) {
connect(&_sequencer, SIGNAL(readyToWrite(const QByteArray&)), SLOT(sendData(const QByteArray&))); connect(&_sequencer, SIGNAL(readyToWrite(const QByteArray&)), SLOT(sendData(const QByteArray&)));
connect(&_sequencer, SIGNAL(readyToRead(Bitstream&)), SLOT(readPacket(Bitstream&))); connect(&_sequencer, SIGNAL(readyToRead(Bitstream&)), SLOT(readPacket(Bitstream&)));
@ -223,9 +183,10 @@ void MetavoxelClient::simulate(float deltaTime, MetavoxelVisitor& visitor) {
_data.guide(visitor); _data.guide(visitor);
} }
void MetavoxelClient::receivedData(const QByteArray& data) { int MetavoxelClient::parseData(const QByteArray& packet) {
// process through sequencer // process through sequencer
_sequencer.receivedDatagram(data); QMetaObject::invokeMethod(&_sequencer, "receivedDatagram", Q_ARG(const QByteArray&, packet));
return packet.size();
} }
void MetavoxelClient::sendData(const QByteArray& data) { void MetavoxelClient::sendData(const QByteArray& data) {

View file

@ -23,8 +23,6 @@
#include "renderer/ProgramObject.h" #include "renderer/ProgramObject.h"
class MetavoxelClient;
/// Renders a metavoxel tree. /// Renders a metavoxel tree.
class MetavoxelSystem : public QObject { class MetavoxelSystem : public QObject {
Q_OBJECT Q_OBJECT
@ -32,28 +30,20 @@ class MetavoxelSystem : public QObject {
public: public:
MetavoxelSystem(); MetavoxelSystem();
~MetavoxelSystem();
void init(); void init();
void applyEdit(const MetavoxelEditMessage& edit); void applyEdit(const MetavoxelEditMessage& edit);
void processData(const QByteArray& data, const HifiSockAddr& sender);
void simulate(float deltaTime); void simulate(float deltaTime);
void render(); void render();
public slots: private slots:
void maybeAttachClient(const SharedNodePointer& node);
void nodeAdded(SharedNodePointer node);
void nodeKilled(SharedNodePointer node);
private: private:
Q_INVOKABLE void addClient(const SharedNodePointer& node);
Q_INVOKABLE void removeClient(const QUuid& uuid);
Q_INVOKABLE void receivedData(const QByteArray& data, const SharedNodePointer& sendingNode);
class Point { class Point {
public: public:
glm::vec4 vertex; glm::vec4 vertex;
@ -76,13 +66,10 @@ private:
QVector<Point> _points; QVector<Point> _points;
PointVisitor _pointVisitor; PointVisitor _pointVisitor;
QOpenGLBuffer _buffer; QOpenGLBuffer _buffer;
QHash<QUuid, MetavoxelClient*> _clients;
QHash<QUuid, MetavoxelClient*> _clientsBySessionID;
}; };
/// A client session associated with a single server. /// A client session associated with a single server.
class MetavoxelClient : public QObject { class MetavoxelClient : public NodeData {
Q_OBJECT Q_OBJECT
public: public:
@ -90,13 +77,11 @@ public:
MetavoxelClient(const SharedNodePointer& node); MetavoxelClient(const SharedNodePointer& node);
virtual ~MetavoxelClient(); virtual ~MetavoxelClient();
const QUuid& getSessionID() const { return _sessionID; }
void applyEdit(const MetavoxelEditMessage& edit); void applyEdit(const MetavoxelEditMessage& edit);
void simulate(float deltaTime, MetavoxelVisitor& visitor); void simulate(float deltaTime, MetavoxelVisitor& visitor);
void receivedData(const QByteArray& data); virtual int parseData(const QByteArray& packet);
private slots: private slots:
@ -117,7 +102,6 @@ private:
}; };
SharedNodePointer _node; SharedNodePointer _node;
QUuid _sessionID;
DatagramSequencer _sequencer; DatagramSequencer _sequencer;

View file

@ -70,7 +70,7 @@ public:
/// Processes a datagram received from the other party, emitting readyToRead when the entire packet /// Processes a datagram received from the other party, emitting readyToRead when the entire packet
/// has been successfully assembled. /// has been successfully assembled.
void receivedDatagram(const QByteArray& datagram); Q_INVOKABLE void receivedDatagram(const QByteArray& datagram);
signals: signals: