mirror of
https://github.com/overte-org/overte.git
synced 2025-04-19 12:23:24 +02:00
AssignmentClients accept an id on the command-line.
AssignmentClientMonitor now has a NodeList. It stores its local port in shared memory, like the DomainServer does. As it spawns children, it addes Nodes to the NodeList for each one. The children send status updates to the Monitor. The Monitor will notice if there are no spares and fork another child.
This commit is contained in:
parent
ac3b172dee
commit
4b3183d820
14 changed files with 389 additions and 77 deletions
|
@ -22,6 +22,7 @@
|
|||
#include <HifiConfigVariantMap.h>
|
||||
#include <LogHandler.h>
|
||||
#include <LogUtils.h>
|
||||
#include <LimitedNodeList.h>
|
||||
#include <NodeList.h>
|
||||
#include <PacketHeaders.h>
|
||||
#include <SharedUtil.h>
|
||||
|
@ -40,10 +41,11 @@ SharedAssignmentPointer AssignmentClient::_currentAssignment;
|
|||
|
||||
int hifiSockAddrMeta = qRegisterMetaType<HifiSockAddr>("HifiSockAddr");
|
||||
|
||||
AssignmentClient::AssignmentClient(int &argc, char **argv) :
|
||||
AssignmentClient::AssignmentClient(int &argc, char **argv, QUuid nodeUUID) :
|
||||
QCoreApplication(argc, argv),
|
||||
_assignmentServerHostname(DEFAULT_ASSIGNMENT_SERVER_HOSTNAME),
|
||||
_localASPortSharedMem(NULL)
|
||||
_localASPortSharedMem(NULL),
|
||||
_localACMPortSharedMem(NULL)
|
||||
{
|
||||
LogUtils::init();
|
||||
|
||||
|
@ -57,6 +59,8 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) :
|
|||
auto addressManager = DependencyManager::set<AddressManager>();
|
||||
auto nodeList = DependencyManager::set<NodeList>(NodeType::Unassigned);
|
||||
auto avatarHashMap = DependencyManager::set<AvatarHashMap>();
|
||||
|
||||
nodeList->setSessionUUID(nodeUUID);
|
||||
|
||||
// setup a shutdown event listener to handle SIGTERM or WM_CLOSE for us
|
||||
#ifdef _WIN32
|
||||
|
@ -123,9 +127,8 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) :
|
|||
// call a timer function every ASSIGNMENT_REQUEST_INTERVAL_MSECS to ask for assignment, if required
|
||||
qDebug() << "Waiting for assignment -" << _requestAssignment;
|
||||
|
||||
QTimer* timer = new QTimer(this);
|
||||
connect(timer, SIGNAL(timeout()), SLOT(sendAssignmentRequest()));
|
||||
timer->start(ASSIGNMENT_REQUEST_INTERVAL_MSECS);
|
||||
connect(&_requestTimer, SIGNAL(timeout()), SLOT(sendAssignmentRequest()));
|
||||
_requestTimer.start(ASSIGNMENT_REQUEST_INTERVAL_MSECS);
|
||||
|
||||
// connect our readPendingDatagrams method to the readyRead() signal of the socket
|
||||
connect(&nodeList->getNodeSocket(), &QUdpSocket::readyRead, this, &AssignmentClient::readPendingDatagrams);
|
||||
|
@ -136,6 +139,36 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) :
|
|||
|
||||
// Create Singleton objects on main thread
|
||||
NetworkAccessManager::getInstance();
|
||||
|
||||
setUpStatsToMonitor();
|
||||
}
|
||||
|
||||
|
||||
void AssignmentClient::setUpStatsToMonitor() {
|
||||
// Figure out the address to send out stats to
|
||||
quint16 localMonitorServerPort = DEFAULT_ASSIGNMENT_CLIENT_MONITOR_PORT;
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
|
||||
nodeList->getLocalPortFromSharedMemory(ASSIGNMENT_CLIENT_MONITOR_LOCAL_PORT_SMEM_KEY,
|
||||
_localACMPortSharedMem, localMonitorServerPort);
|
||||
_assignmentClientMonitorSocket = HifiSockAddr(DEFAULT_ASSIGNMENT_CLIENT_MONITOR_HOSTNAME, localMonitorServerPort, true);
|
||||
|
||||
// send a stats packet every 1 seconds
|
||||
connect(&_statsTimerACM, &QTimer::timeout, this, &AssignmentClient::sendStatsPacketToACM);
|
||||
_statsTimerACM.start(1000);
|
||||
}
|
||||
|
||||
void AssignmentClient::sendStatsPacketToACM() {
|
||||
// tell the assignment client monitor what this assignment client is doing (if anything)
|
||||
QJsonObject statsObject;
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
|
||||
if (_currentAssignment) {
|
||||
statsObject["assignment_type"] = _currentAssignment->getTypeName();
|
||||
} else {
|
||||
statsObject["assignment_type"] = "none";
|
||||
}
|
||||
nodeList->sendStats(statsObject, _assignmentClientMonitorSocket);
|
||||
}
|
||||
|
||||
void AssignmentClient::sendAssignmentRequest() {
|
||||
|
@ -145,34 +178,22 @@ void AssignmentClient::sendAssignmentRequest() {
|
|||
|
||||
if (_assignmentServerHostname == "localhost") {
|
||||
// we want to check again for the local domain-server port in case the DS has restarted
|
||||
if (!_localASPortSharedMem) {
|
||||
_localASPortSharedMem = new QSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, this);
|
||||
|
||||
if (!_localASPortSharedMem->attach(QSharedMemory::ReadOnly)) {
|
||||
qWarning() << "Could not attach to shared memory at key" << DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY
|
||||
<< "- will attempt to connect to domain-server on" << _assignmentServerSocket.getPort();
|
||||
}
|
||||
}
|
||||
|
||||
if (_localASPortSharedMem->isAttached()) {
|
||||
_localASPortSharedMem->lock();
|
||||
|
||||
quint16 localAssignmentServerPort;
|
||||
memcpy(&localAssignmentServerPort, _localASPortSharedMem->data(), sizeof(localAssignmentServerPort));
|
||||
|
||||
_localASPortSharedMem->unlock();
|
||||
|
||||
quint16 localAssignmentServerPort;
|
||||
if (nodeList->getLocalPortFromSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, _localASPortSharedMem,
|
||||
localAssignmentServerPort)) {
|
||||
if (localAssignmentServerPort != _assignmentServerSocket.getPort()) {
|
||||
qDebug() << "Port for local assignment server read from shared memory is"
|
||||
<< localAssignmentServerPort;
|
||||
<< localAssignmentServerPort;
|
||||
|
||||
_assignmentServerSocket.setPort(localAssignmentServerPort);
|
||||
nodeList->setAssignmentServerSocket(_assignmentServerSocket);
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
qDebug () << "- will attempt to connect to domain-server on" << _assignmentServerSocket.getPort();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
nodeList->sendAssignment(_requestAssignment);
|
||||
}
|
||||
}
|
||||
|
@ -227,10 +248,16 @@ void AssignmentClient::readPendingDatagrams() {
|
|||
} else {
|
||||
qDebug() << "Received an assignment that could not be unpacked. Re-requesting.";
|
||||
}
|
||||
} else if (packetTypeForPacket(receivedPacket) == PacketTypeStopNode) {
|
||||
qDebug() << "Network told me to exit";
|
||||
quit();
|
||||
} else {
|
||||
qDebug() << "punt";
|
||||
// have the NodeList attempt to handle it
|
||||
nodeList->processNodeData(senderSockAddr, receivedPacket);
|
||||
}
|
||||
} else {
|
||||
qDebug() << "packetVersionAndHashMatch said no";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ class QSharedMemory;
|
|||
class AssignmentClient : public QCoreApplication {
|
||||
Q_OBJECT
|
||||
public:
|
||||
AssignmentClient(int &argc, char **argv);
|
||||
AssignmentClient(int &argc, char **argv, QUuid nodeUUID);
|
||||
static const SharedAssignmentPointer& getCurrentAssignment() { return _currentAssignment; }
|
||||
|
||||
private slots:
|
||||
|
@ -29,13 +29,21 @@ private slots:
|
|||
void readPendingDatagrams();
|
||||
void assignmentCompleted();
|
||||
void handleAuthenticationRequest();
|
||||
void sendStatsPacketToACM();
|
||||
|
||||
private:
|
||||
void setUpStatsToMonitor();
|
||||
Assignment _requestAssignment;
|
||||
static SharedAssignmentPointer _currentAssignment;
|
||||
QString _assignmentServerHostname;
|
||||
HifiSockAddr _assignmentServerSocket;
|
||||
QSharedMemory* _localASPortSharedMem;
|
||||
QSharedMemory* _localASPortSharedMem; // memory shared with domain server
|
||||
QSharedMemory* _localACMPortSharedMem; // memory shared with assignment client monitor
|
||||
QTimer _requestTimer; // timer for requesting and assignment
|
||||
QTimer _statsTimerACM; // timer for sending stats to assignment client monitor
|
||||
|
||||
protected:
|
||||
HifiSockAddr _assignmentClientMonitorSocket;
|
||||
};
|
||||
|
||||
#endif // hifi_AssignmentClient_h
|
||||
|
|
84
assignment-client/src/AssignmentClientApp.cpp
Normal file
84
assignment-client/src/AssignmentClientApp.cpp
Normal file
|
@ -0,0 +1,84 @@
|
|||
//
|
||||
// AssignmentClientapp.cpp
|
||||
// assignment-client/src
|
||||
//
|
||||
// Created by Seth Alves on 2/19/15.
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <QCommandLineParser>
|
||||
|
||||
#include <LogHandler.h>
|
||||
#include <SharedUtil.h>
|
||||
|
||||
#include "Assignment.h"
|
||||
#include "AssignmentClient.h"
|
||||
#include "AssignmentClientMonitor.h"
|
||||
#include "AssignmentClientApp.h"
|
||||
|
||||
|
||||
AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) :
|
||||
QApplication(argc, argv)
|
||||
{
|
||||
# ifndef WIN32
|
||||
setvbuf(stdout, NULL, _IOLBF, 0);
|
||||
# endif
|
||||
|
||||
// use the verbose message handler in Logging
|
||||
qInstallMessageHandler(LogHandler::verboseMessageHandler);
|
||||
|
||||
// parse command-line
|
||||
QCommandLineParser parser;
|
||||
parser.setApplicationDescription("High Fidelity Assignment Client");
|
||||
parser.addHelpOption();
|
||||
|
||||
const QCommandLineOption helpOption = parser.addHelpOption();
|
||||
|
||||
const QCommandLineOption numChildsOption("n", "number of children to fork", "child-count");
|
||||
parser.addOption(numChildsOption);
|
||||
|
||||
const QCommandLineOption idOption("i", "assignment client id", "uuid");
|
||||
parser.addOption(idOption);
|
||||
|
||||
if (!parser.parse(QCoreApplication::arguments())) {
|
||||
qCritical() << parser.errorText() << endl;
|
||||
parser.showHelp();
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
|
||||
if (parser.isSet(helpOption)) {
|
||||
parser.showHelp();
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
|
||||
if (parser.isSet(numChildsOption) && parser.isSet(idOption)) {
|
||||
qCritical() << "using both -i and -n doesn't make sense.";
|
||||
parser.showHelp();
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
|
||||
unsigned int numForks = 0;
|
||||
if (parser.isSet(numChildsOption)) {
|
||||
numForks = parser.value(numChildsOption).toInt();
|
||||
}
|
||||
|
||||
QUuid nodeUUID = QUuid::createUuid();
|
||||
if (parser.isSet(idOption)) {
|
||||
nodeUUID = QUuid(parser.value(idOption));
|
||||
}
|
||||
|
||||
if (numForks) {
|
||||
AssignmentClientMonitor monitor(argc, argv, numForks);
|
||||
monitor.exec();
|
||||
} else {
|
||||
AssignmentClient client(argc, argv, nodeUUID);
|
||||
client.exec();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AssignmentClientApp::~AssignmentClientApp() {
|
||||
}
|
19
assignment-client/src/AssignmentClientApp.h
Normal file
19
assignment-client/src/AssignmentClientApp.h
Normal file
|
@ -0,0 +1,19 @@
|
|||
//
|
||||
// AssignmentClientapp.h
|
||||
// assignment-client/src
|
||||
//
|
||||
// Created by Seth Alves on 2/19/15.
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
class AssignmentClientApp : public QApplication {
|
||||
Q_OBJECT
|
||||
public:
|
||||
AssignmentClientApp(int argc, char* argv[]);
|
||||
~AssignmentClientApp();
|
||||
};
|
|
@ -14,13 +14,18 @@
|
|||
#include <LogHandler.h>
|
||||
#include <ShutdownEventListener.h>
|
||||
|
||||
|
||||
#include <AddressManager.h> // XXX need this?
|
||||
|
||||
|
||||
#include "AssignmentClientMonitor.h"
|
||||
#include "PacketHeaders.h"
|
||||
|
||||
const char* NUM_FORKS_PARAMETER = "-n";
|
||||
|
||||
const QString ASSIGNMENT_CLIENT_MONITOR_TARGET_NAME = "assignment-client-monitor";
|
||||
|
||||
AssignmentClientMonitor::AssignmentClientMonitor(int &argc, char **argv, int numAssignmentClientForks) :
|
||||
AssignmentClientMonitor::AssignmentClientMonitor(int &argc, char **argv, const unsigned int numAssignmentClientForks) :
|
||||
QCoreApplication(argc, argv)
|
||||
{
|
||||
// start the Logging class with the parent's target name
|
||||
|
@ -41,17 +46,38 @@ AssignmentClientMonitor::AssignmentClientMonitor(int &argc, char **argv, int num
|
|||
// this removes both the "-n" parameter and the number of forks passed
|
||||
_childArguments.removeAt(forksParameterIndex);
|
||||
_childArguments.removeAt(forksParameterIndex);
|
||||
|
||||
|
||||
// create a NodeList so we can receive stats from children
|
||||
DependencyManager::registerInheritance<LimitedNodeList, NodeList>();
|
||||
auto addressManager = DependencyManager::set<AddressManager>();
|
||||
// auto nodeList = DependencyManager::set<NodeList>(NodeType::Unassigned);
|
||||
auto nodeList = DependencyManager::set<LimitedNodeList>(DEFAULT_ASSIGNMENT_CLIENT_MONITOR_PORT,
|
||||
DEFAULT_ASSIGNMENT_CLIENT_MONITOR_DTLS_PORT);
|
||||
|
||||
connect(&nodeList->getNodeSocket(), &QUdpSocket::readyRead, this, &AssignmentClientMonitor::readPendingDatagrams);
|
||||
|
||||
nodeList->putLocalPortIntoSharedMemory(ASSIGNMENT_CLIENT_MONITOR_LOCAL_PORT_SMEM_KEY, this);
|
||||
|
||||
// use QProcess to fork off a process for each of the child assignment clients
|
||||
for (int i = 0; i < numAssignmentClientForks; i++) {
|
||||
for (unsigned int i = 0; i < numAssignmentClientForks; i++) {
|
||||
spawnChildClient();
|
||||
}
|
||||
|
||||
connect(&_checkSparesTimer, SIGNAL(timeout()), SLOT(checkSpares()));
|
||||
_checkSparesTimer.start(5000);
|
||||
}
|
||||
|
||||
AssignmentClientMonitor::~AssignmentClientMonitor() {
|
||||
stopChildProcesses();
|
||||
|
||||
foreach (AssignmentClientChildData* childStatus, _childStatus) {
|
||||
delete childStatus;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AssignmentClientMonitor::stopChildProcesses() {
|
||||
|
||||
QList<QPointer<QProcess> >::Iterator it = _childProcesses.begin();
|
||||
|
@ -74,11 +100,18 @@ void AssignmentClientMonitor::spawnChildClient() {
|
|||
QProcess *assignmentClient = new QProcess(this);
|
||||
|
||||
_childProcesses.append(QPointer<QProcess>(assignmentClient));
|
||||
|
||||
QUuid childUUID = QUuid::createUuid();
|
||||
|
||||
// create a Node for this child. this is done so we can idenitfy packets from unknown children
|
||||
DependencyManager::get<LimitedNodeList>()->addOrUpdateNode
|
||||
(childUUID, NodeType::Unassigned, HifiSockAddr("localhost", 0), HifiSockAddr("localhost", 0), false);
|
||||
|
||||
// make sure that the output from the child process appears in our output
|
||||
assignmentClient->setProcessChannelMode(QProcess::ForwardedChannels);
|
||||
|
||||
assignmentClient->start(applicationFilePath(), _childArguments);
|
||||
|
||||
QStringList idArgs = QStringList() << "-i" << childUUID.toString();
|
||||
assignmentClient->start(applicationFilePath(), _childArguments + idArgs);
|
||||
|
||||
// link the child processes' finished slot to our childProcessFinished slot
|
||||
connect(assignmentClient, SIGNAL(finished(int, QProcess::ExitStatus)), this,
|
||||
|
@ -96,3 +129,105 @@ void AssignmentClientMonitor::childProcessFinished(int exitCode, QProcess::ExitS
|
|||
|
||||
spawnChildClient();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AssignmentClientMonitor::checkSpares() {
|
||||
qDebug() << "check spares:";
|
||||
|
||||
QString aSpareId = "";
|
||||
unsigned int spareCount = 0;
|
||||
|
||||
QHash<QString, AssignmentClientChildData*>::const_iterator i = _childStatus.constBegin();
|
||||
while (i != _childStatus.constEnd()) {
|
||||
qDebug() << " " << i.key() << i.value()->getChildType();
|
||||
if (i.value()->getChildType() == "none") {
|
||||
spareCount ++;
|
||||
aSpareId = i.key();
|
||||
}
|
||||
++i;
|
||||
}
|
||||
|
||||
qDebug() << "spare count is" << spareCount;
|
||||
|
||||
if (spareCount < 1) {
|
||||
qDebug() << "FORK";
|
||||
spawnChildClient();
|
||||
}
|
||||
|
||||
if (spareCount > 1) {
|
||||
qDebug() << "KILL";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void AssignmentClientMonitor::readPendingDatagrams() {
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
|
||||
QByteArray receivedPacket;
|
||||
HifiSockAddr senderSockAddr;
|
||||
|
||||
while (nodeList->getNodeSocket().hasPendingDatagrams()) {
|
||||
receivedPacket.resize(nodeList->getNodeSocket().pendingDatagramSize());
|
||||
nodeList->getNodeSocket().readDatagram(receivedPacket.data(), receivedPacket.size(),
|
||||
senderSockAddr.getAddressPointer(), senderSockAddr.getPortPointer());
|
||||
|
||||
if (nodeList->packetVersionAndHashMatch(receivedPacket)) {
|
||||
if (packetTypeForPacket(receivedPacket) == PacketTypeNodeJsonStats) {
|
||||
|
||||
QUuid packetUUID = uuidFromPacketHeader(receivedPacket);
|
||||
// qDebug() << "packetUUID = " << packetUUID;
|
||||
|
||||
SharedNodePointer matchingNode = nodeList->sendingNodeForPacket(receivedPacket);
|
||||
if (!matchingNode) {
|
||||
qDebug() << "got packet from unknown child, id =" << packetUUID.toString();
|
||||
// tell unknown assignment-client child to exit.
|
||||
QByteArray diePacket = byteArrayWithPopulatedHeader(PacketTypeStopNode);
|
||||
nodeList->writeUnverifiedDatagram(diePacket, senderSockAddr);
|
||||
}
|
||||
|
||||
if (matchingNode) {
|
||||
// update our records about how to reach this child
|
||||
matchingNode->setLocalSocket(senderSockAddr);
|
||||
|
||||
// push past the packet header
|
||||
QDataStream packetStream(receivedPacket);
|
||||
packetStream.skipRawData(numBytesForPacketHeader(receivedPacket));
|
||||
|
||||
QVariantMap unpackedVariantMap;
|
||||
|
||||
packetStream >> unpackedVariantMap;
|
||||
|
||||
QJsonObject unpackedStatsJSON = QJsonObject::fromVariantMap(unpackedVariantMap);
|
||||
|
||||
// qDebug() << "ACM got stats packet, id =" << packetUUID.toString()
|
||||
// << "type =" << unpackedStatsJSON["assignment_type"];
|
||||
|
||||
QString key(QString(packetUUID.toString()));
|
||||
if (_childStatus.contains(key)) {
|
||||
delete _childStatus[ key ];
|
||||
}
|
||||
|
||||
QString childType = unpackedStatsJSON["assignment_type"].toString();
|
||||
auto childStatus = new AssignmentClientChildData(childType);
|
||||
_childStatus[ key ] = childStatus;
|
||||
|
||||
}
|
||||
} else {
|
||||
// have the NodeList attempt to handle it
|
||||
nodeList->processNodeData(senderSockAddr, receivedPacket);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AssignmentClientChildData::AssignmentClientChildData(QString childType) {
|
||||
_childType = childType;
|
||||
}
|
||||
|
||||
|
||||
AssignmentClientChildData::~AssignmentClientChildData() {
|
||||
}
|
||||
|
|
|
@ -20,20 +20,39 @@
|
|||
|
||||
extern const char* NUM_FORKS_PARAMETER;
|
||||
|
||||
class AssignmentClientChildData {
|
||||
public:
|
||||
AssignmentClientChildData(QString childType);
|
||||
~AssignmentClientChildData();
|
||||
|
||||
QString getChildType() { return _childType; }
|
||||
|
||||
private:
|
||||
QString _childType;
|
||||
// ... timestamp
|
||||
};
|
||||
|
||||
|
||||
class AssignmentClientMonitor : public QCoreApplication {
|
||||
Q_OBJECT
|
||||
public:
|
||||
AssignmentClientMonitor(int &argc, char **argv, int numAssignmentClientForks);
|
||||
AssignmentClientMonitor(int &argc, char **argv, const unsigned int numAssignmentClientForks);
|
||||
~AssignmentClientMonitor();
|
||||
|
||||
void stopChildProcesses();
|
||||
private slots:
|
||||
void childProcessFinished(int exitCode, QProcess::ExitStatus exitStatus);
|
||||
void readPendingDatagrams();
|
||||
void checkSpares();
|
||||
|
||||
private:
|
||||
void spawnChildClient();
|
||||
QList<QPointer<QProcess> > _childProcesses;
|
||||
|
||||
QStringList _childArguments;
|
||||
QHash<QString, AssignmentClientChildData*> _childStatus;
|
||||
|
||||
QTimer _checkSparesTimer; // every few seconds see if it need fewer or more spare children
|
||||
};
|
||||
|
||||
#endif // hifi_AssignmentClientMonitor_h
|
||||
|
|
|
@ -9,34 +9,10 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <LogHandler.h>
|
||||
#include <SharedUtil.h>
|
||||
|
||||
#include "Assignment.h"
|
||||
#include "AssignmentClient.h"
|
||||
#include "AssignmentClientMonitor.h"
|
||||
#include "AssignmentClientApp.h"
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
#ifndef WIN32
|
||||
setvbuf(stdout, NULL, _IOLBF, 0);
|
||||
#endif
|
||||
|
||||
// use the verbose message handler in Logging
|
||||
qInstallMessageHandler(LogHandler::verboseMessageHandler);
|
||||
|
||||
const char* numForksString = getCmdOption(argc, (const char**)argv, NUM_FORKS_PARAMETER);
|
||||
|
||||
int numForks = 0;
|
||||
|
||||
if (numForksString) {
|
||||
numForks = atoi(numForksString);
|
||||
}
|
||||
|
||||
if (numForks) {
|
||||
AssignmentClientMonitor monitor(argc, argv, numForks);
|
||||
return monitor.exec();
|
||||
} else {
|
||||
AssignmentClient client(argc, argv);
|
||||
return client.exec();
|
||||
}
|
||||
AssignmentClientApp app(argc, argv);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -244,21 +244,9 @@ void DomainServer::setupNodeListAndAssignments(const QUuid& sessionUUID) {
|
|||
populateStaticScriptedAssignmentsFromSettings();
|
||||
|
||||
auto nodeList = DependencyManager::set<LimitedNodeList>(domainServerPort, domainServerDTLSPort);
|
||||
|
||||
|
||||
// no matter the local port, save it to shared mem so that local assignment clients can ask what it is
|
||||
QSharedMemory* sharedPortMem = new QSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, this);
|
||||
quint16 localPort = nodeList->getNodeSocket().localPort();
|
||||
|
||||
// attempt to create the shared memory segment
|
||||
if (sharedPortMem->create(sizeof(localPort)) || sharedPortMem->attach()) {
|
||||
sharedPortMem->lock();
|
||||
memcpy(sharedPortMem->data(), &localPort, sizeof(localPort));
|
||||
sharedPortMem->unlock();
|
||||
|
||||
qDebug() << "Wrote local listening port" << localPort << "to shared memory at key" << DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY;
|
||||
} else {
|
||||
qWarning() << "Failed to create and attach to shared memory to share local port with assignment-client children.";
|
||||
}
|
||||
nodeList->putLocalPortIntoSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, this);
|
||||
|
||||
// set our LimitedNodeList UUID to match the UUID from our config
|
||||
// nodes will currently use this to add resources to data-web that relate to our domain
|
||||
|
|
|
@ -669,3 +669,41 @@ void LimitedNodeList::sendHeartbeatToIceServer(const HifiSockAddr& iceServerSock
|
|||
|
||||
writeUnverifiedDatagram(iceRequestByteArray, iceServerSockAddr);
|
||||
}
|
||||
|
||||
void LimitedNodeList::putLocalPortIntoSharedMemory(const QString key, QObject* parent) {
|
||||
// save our local port to shared memory so that assignment client children know how to talk to this parent
|
||||
QSharedMemory* sharedPortMem = new QSharedMemory(key, parent);
|
||||
quint16 localPort = getNodeSocket().localPort();
|
||||
|
||||
// attempt to create the shared memory segment
|
||||
if (sharedPortMem->create(sizeof(localPort)) || sharedPortMem->attach()) {
|
||||
sharedPortMem->lock();
|
||||
memcpy(sharedPortMem->data(), &localPort, sizeof(localPort));
|
||||
sharedPortMem->unlock();
|
||||
|
||||
qDebug() << "Wrote local listening port" << localPort << "to shared memory at key" << key;
|
||||
} else {
|
||||
qWarning() << "Failed to create and attach to shared memory to share local port with assignment-client children.";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool LimitedNodeList::getLocalPortFromSharedMemory(const QString key, QSharedMemory* &sharedMem,
|
||||
quint16& localPort) {
|
||||
if (!sharedMem) {
|
||||
sharedMem = new QSharedMemory(key, this);
|
||||
|
||||
if (!sharedMem->attach(QSharedMemory::ReadOnly)) {
|
||||
qWarning() << "Could not attach to shared memory at key" << key;
|
||||
}
|
||||
}
|
||||
|
||||
if (sharedMem->isAttached()) {
|
||||
sharedMem->lock();
|
||||
memcpy(&localPort, sharedMem->data(), sizeof(localPort));
|
||||
sharedMem->unlock();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
#include <qset.h>
|
||||
#include <qsharedpointer.h>
|
||||
#include <QtNetwork/qudpsocket.h>
|
||||
#include <QSharedMemory>
|
||||
|
||||
#include <QtNetwork/qhostaddress.h>
|
||||
|
||||
#include <tbb/concurrent_unordered_map.h>
|
||||
|
@ -49,6 +51,11 @@ const char STUN_SERVER_HOSTNAME[] = "stun.highfidelity.io";
|
|||
const unsigned short STUN_SERVER_PORT = 3478;
|
||||
|
||||
const QString DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY = "domain-server.local-port";
|
||||
const QString ASSIGNMENT_CLIENT_MONITOR_LOCAL_PORT_SMEM_KEY = "assignment-client-monitor.local-port";
|
||||
|
||||
const char DEFAULT_ASSIGNMENT_CLIENT_MONITOR_HOSTNAME[] = "localhost";
|
||||
const unsigned short DEFAULT_ASSIGNMENT_CLIENT_MONITOR_PORT = 40104;
|
||||
const unsigned short DEFAULT_ASSIGNMENT_CLIENT_MONITOR_DTLS_PORT = 40105;
|
||||
|
||||
class HifiSockAddr;
|
||||
|
||||
|
@ -168,6 +175,9 @@ public:
|
|||
|
||||
return SharedNodePointer();
|
||||
}
|
||||
|
||||
void putLocalPortIntoSharedMemory(const QString key, QObject* parent);
|
||||
bool getLocalPortFromSharedMemory(const QString key, QSharedMemory* &sharedMem, quint16& localPort);
|
||||
|
||||
public slots:
|
||||
void reset();
|
||||
|
|
|
@ -62,13 +62,17 @@ NodeList::NodeList(char newOwnerType, unsigned short socketListenPort, unsigned
|
|||
connect(&AccountManager::getInstance(), &AccountManager::logoutComplete , this, &NodeList::reset);
|
||||
}
|
||||
|
||||
qint64 NodeList::sendStatsToDomainServer(const QJsonObject& statsObject) {
|
||||
qint64 NodeList::sendStats(const QJsonObject& statsObject, HifiSockAddr destination) {
|
||||
QByteArray statsPacket = byteArrayWithPopulatedHeader(PacketTypeNodeJsonStats);
|
||||
QDataStream statsPacketStream(&statsPacket, QIODevice::Append);
|
||||
|
||||
statsPacketStream << statsObject.toVariantMap();
|
||||
|
||||
return writeUnverifiedDatagram(statsPacket, _domainHandler.getSockAddr());
|
||||
return writeUnverifiedDatagram(statsPacket, destination);
|
||||
}
|
||||
|
||||
qint64 NodeList::sendStatsToDomainServer(const QJsonObject& statsObject) {
|
||||
return sendStats(statsObject, _domainHandler.getSockAddr());
|
||||
}
|
||||
|
||||
void NodeList::timePingReply(const QByteArray& packet, const SharedNodePointer& sendingNode) {
|
||||
|
|
|
@ -47,6 +47,7 @@ public:
|
|||
NodeType_t getOwnerType() const { return _ownerType; }
|
||||
void setOwnerType(NodeType_t ownerType) { _ownerType = ownerType; }
|
||||
|
||||
qint64 sendStats(const QJsonObject& statsObject, HifiSockAddr destination);
|
||||
qint64 sendStatsToDomainServer(const QJsonObject& statsObject);
|
||||
|
||||
int getNumNoReplyDomainCheckIns() const { return _numNoReplyDomainCheckIns; }
|
||||
|
|
|
@ -70,6 +70,8 @@ PacketVersion versionForPacketType(PacketType type) {
|
|||
return 2;
|
||||
case PacketTypeOctreeStats:
|
||||
return 1;
|
||||
case PacketTypeStopNode:
|
||||
return 1;
|
||||
case PacketTypeEntityAddOrEdit:
|
||||
case PacketTypeEntityData:
|
||||
return VERSION_MODEL_ENTITIES_SUPPORT_SHAPE_TYPE;
|
||||
|
@ -124,6 +126,7 @@ QString nameForPacketType(PacketType type) {
|
|||
PACKET_TYPE_NAME_LOOKUP(PacketTypeEntityErase);
|
||||
PACKET_TYPE_NAME_LOOKUP(PacketTypeEntityAddResponse);
|
||||
PACKET_TYPE_NAME_LOOKUP(PacketTypeOctreeDataNack);
|
||||
PACKET_TYPE_NAME_LOOKUP(PacketTypeStopNode);
|
||||
PACKET_TYPE_NAME_LOOKUP(PacketTypeAudioEnvironment);
|
||||
PACKET_TYPE_NAME_LOOKUP(PacketTypeEntityEditNack);
|
||||
PACKET_TYPE_NAME_LOOKUP(PacketTypeSignedTransactionPayment);
|
||||
|
|
|
@ -67,7 +67,7 @@ enum PacketType {
|
|||
PacketTypeEntityErase,
|
||||
PacketTypeEntityAddResponse,
|
||||
PacketTypeOctreeDataNack, // 45
|
||||
UNUSED_10,
|
||||
PacketTypeStopNode,
|
||||
PacketTypeAudioEnvironment,
|
||||
PacketTypeEntityEditNack,
|
||||
PacketTypeSignedTransactionPayment,
|
||||
|
@ -86,7 +86,7 @@ const QSet<PacketType> NON_VERIFIED_PACKETS = QSet<PacketType>()
|
|||
<< PacketTypeNodeJsonStats << PacketTypeEntityQuery
|
||||
<< PacketTypeOctreeDataNack << PacketTypeEntityEditNack
|
||||
<< PacketTypeIceServerHeartbeat << PacketTypeIceServerHeartbeatResponse
|
||||
<< PacketTypeUnverifiedPing << PacketTypeUnverifiedPingReply;
|
||||
<< PacketTypeUnverifiedPing << PacketTypeUnverifiedPingReply << PacketTypeStopNode;
|
||||
|
||||
const int NUM_BYTES_MD5_HASH = 16;
|
||||
const int NUM_STATIC_HEADER_BYTES = sizeof(PacketVersion) + NUM_BYTES_RFC4122_UUID;
|
||||
|
|
Loading…
Reference in a new issue