don't allow an AC monitor to take over other local ACs

This commit is contained in:
Stephen Birarda 2015-05-08 14:02:19 -07:00
parent df6ee4c7a5
commit 99a9f2df90
7 changed files with 42 additions and 46 deletions

View file

@ -40,11 +40,11 @@ const long long ASSIGNMENT_REQUEST_INTERVAL_MSECS = 1 * 1000;
int hifiSockAddrMeta = qRegisterMetaType<HifiSockAddr>("HifiSockAddr");
AssignmentClient::AssignmentClient(int ppid, Assignment::Type requestAssignmentType, QString assignmentPool,
QUuid walletUUID, QString assignmentServerHostname, quint16 assignmentServerPort) :
AssignmentClient::AssignmentClient(Assignment::Type requestAssignmentType, QString assignmentPool,
QUuid walletUUID, QString assignmentServerHostname, quint16 assignmentServerPort,
quint16 assignmentMonitorPort) :
_assignmentServerHostname(DEFAULT_ASSIGNMENT_SERVER_HOSTNAME),
_localASPortSharedMem(NULL),
_localACMPortSharedMem(NULL)
_localASPortSharedMem(NULL)
{
LogUtils::init();
@ -107,9 +107,16 @@ AssignmentClient::AssignmentClient(int ppid, Assignment::Type requestAssignmentT
// Create Singleton objects on main thread
NetworkAccessManager::getInstance();
// Hook up a timer to send this child's status to the Monitor once per second
setUpStatsToMonitor(ppid);
// did we get an assignment-client monitor port?
if (assignmentMonitorPort > 0) {
_assignmentClientMonitorSocket = HifiSockAddr(DEFAULT_ASSIGNMENT_CLIENT_MONITOR_HOSTNAME, assignmentMonitorPort);
qDebug() << "Assignment-client monitor socket is" << _assignmentClientMonitorSocket;
// Hook up a timer to send this child's status to the Monitor once per second
setUpStatsToMonitor();
}
}
@ -144,15 +151,7 @@ void AssignmentClient::aboutToQuit() {
}
void AssignmentClient::setUpStatsToMonitor(int ppid) {
// Figure out the address to send out stats to
quint16 localMonitorServerPort = DEFAULT_ASSIGNMENT_CLIENT_MONITOR_PORT;
auto nodeList = DependencyManager::get<NodeList>();
nodeList->getLocalServerPortFromSharedMemory(QString(ASSIGNMENT_CLIENT_MONITOR_LOCAL_PORT_SMEM_KEY) + "-" +
QString::number(ppid), _localACMPortSharedMem, localMonitorServerPort);
_assignmentClientMonitorSocket = HifiSockAddr(DEFAULT_ASSIGNMENT_CLIENT_MONITOR_HOSTNAME, localMonitorServerPort, true);
void AssignmentClient::setUpStatsToMonitor() {
// send a stats packet every 1 seconds
connect(&_statsTimerACM, &QTimer::timeout, this, &AssignmentClient::sendStatsPacketToACM);
_statsTimerACM.start(1000);
@ -208,6 +207,9 @@ void AssignmentClient::readPendingDatagrams() {
if (nodeList->packetVersionAndHashMatch(receivedPacket)) {
if (packetTypeForPacket(receivedPacket) == PacketTypeCreateAssignment) {
qDebug() << "Received a PacketTypeCreateAssignment - attempting to unpack.";
// construct the deployed assignment from the packet data
_currentAssignment = AssignmentFactory::unpackAssignment(receivedPacket);
@ -258,8 +260,8 @@ void AssignmentClient::readPendingDatagrams() {
} else if (packetTypeForPacket(receivedPacket) == PacketTypeStopNode) {
if (senderSockAddr.getAddress() == QHostAddress::LocalHost ||
senderSockAddr.getAddress() == QHostAddress::LocalHostIPv6) {
qDebug() << "Network told me to exit.";
emit stopAssignmentClient();
qDebug() << "AssignmentClientMonitor at" << senderSockAddr << "requested stop via PacketTypeStopNode.";
stopAssignmentClient();
} else {
qDebug() << "Got a stop packet from other than localhost.";
}

View file

@ -23,8 +23,9 @@ class AssignmentClient : public QObject {
Q_OBJECT
public:
AssignmentClient(int ppid, Assignment::Type requestAssignmentType, QString assignmentPool,
QUuid walletUUID, QString assignmentServerHostname, quint16 assignmentServerPort);
AssignmentClient(Assignment::Type requestAssignmentType, QString assignmentPool,
QUuid walletUUID, QString assignmentServerHostname, quint16 assignmentServerPort,
quint16 assignmentMonitorPort);
private slots:
void sendAssignmentRequest();
@ -38,13 +39,13 @@ public slots:
void aboutToQuit();
private:
void setUpStatsToMonitor(int ppid);
void setUpStatsToMonitor();
Assignment _requestAssignment;
QPointer<ThreadedAssignment> _currentAssignment;
QString _assignmentServerHostname;
HifiSockAddr _assignmentServerSocket;
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

View file

@ -79,9 +79,8 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) :
const QCommandLineOption maxChildsOption(ASSIGNMENT_MAX_FORKS_OPTION, "maximum number of children", "child-count");
parser.addOption(maxChildsOption);
const QCommandLineOption ppidOption(PARENT_PID_OPTION, "parent's process id", "pid");
parser.addOption(ppidOption);
const QCommandLineOption monitorPortOption(ASSIGNMENT_CLIENT_MONITOR_PORT_OPTION, "assignment-client monitor port", "port");
parser.addOption(monitorPortOption);
if (!parser.parse(QCoreApplication::arguments())) {
qCritical() << parser.errorText() << endl;
@ -113,9 +112,9 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) :
maxForks = parser.value(maxChildsOption).toInt();
}
int ppid = 0;
if (parser.isSet(ppidOption)) {
ppid = parser.value(ppidOption).toInt();
unsigned short monitorPort = 0;
if (parser.isSet(monitorPortOption)) {
monitorPort = parser.value(monitorPortOption).toUShort();
}
if (!numForks && minForks) {
@ -191,8 +190,8 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) :
connect(this, &QCoreApplication::aboutToQuit, &monitor, &AssignmentClientMonitor::aboutToQuit);
exec();
} else {
AssignmentClient client(ppid, requestAssignmentType, assignmentPool,
walletUUID, assignmentServerHostname, assignmentServerPort);
AssignmentClient client(requestAssignmentType, assignmentPool,
walletUUID, assignmentServerHostname, assignmentServerPort, monitorPort);
connect(this, &QCoreApplication::aboutToQuit, &client, &AssignmentClient::aboutToQuit);
exec();
}

View file

@ -23,7 +23,7 @@ const QString CUSTOM_ASSIGNMENT_SERVER_PORT_OPTION = "p";
const QString ASSIGNMENT_NUM_FORKS_OPTION = "n";
const QString ASSIGNMENT_MIN_FORKS_OPTION = "min";
const QString ASSIGNMENT_MAX_FORKS_OPTION = "max";
const QString PARENT_PID_OPTION = "ppid";
const QString ASSIGNMENT_CLIENT_MONITOR_PORT_OPTION = "monitor-port";
class AssignmentClientApp : public QCoreApplication {

View file

@ -48,15 +48,10 @@ AssignmentClientMonitor::AssignmentClientMonitor(const unsigned int numAssignmen
// create a NodeList so we can receive stats from children
DependencyManager::registerInheritance<LimitedNodeList, NodeList>();
auto addressManager = DependencyManager::set<AddressManager>();
auto nodeList = DependencyManager::set<LimitedNodeList>(DEFAULT_ASSIGNMENT_CLIENT_MONITOR_PORT);
auto nodeList = DependencyManager::set<LimitedNodeList>();
connect(&nodeList->getNodeSocket(), &QUdpSocket::readyRead, this, &AssignmentClientMonitor::readPendingDatagrams);
qint64 pid = QCoreApplication::applicationPid ();
nodeList->putLocalPortIntoSharedMemory(QString(ASSIGNMENT_CLIENT_MONITOR_LOCAL_PORT_SMEM_KEY) + "-" + QString::number(pid),
this, nodeList->getNodeSocket().localPort());
// use QProcess to fork off a process for each of the child assignment clients
for (unsigned int i = 0; i < _numAssignmentClientForks; i++) {
spawnChildClient();
@ -139,10 +134,10 @@ void AssignmentClientMonitor::spawnChildClient() {
_childArguments.append(QString::number(_requestAssignmentType));
}
// tell children which shared memory key to use
qint64 pid = QCoreApplication::applicationPid ();
_childArguments.append("--" + PARENT_PID_OPTION);
_childArguments.append(QString::number(pid));
// tell children which assignment monitor port to use
// for now they simply talk to us on localhost
_childArguments.append("--" + ASSIGNMENT_CLIENT_MONITOR_PORT_OPTION);
_childArguments.append(QString::number(DependencyManager::get<NodeList>()->getLocalSockAddr().getPort()));
// make sure that the output from the child process appears in our output
assignmentClient->setProcessChannelMode(QProcess::ForwardedChannels);
@ -183,6 +178,7 @@ void AssignmentClientMonitor::checkSpares() {
qDebug() << "asking child" << aSpareId << "to exit.";
SharedNodePointer childNode = nodeList->nodeWithUUID(aSpareId);
childNode->activateLocalSocket();
QByteArray diePacket = byteArrayWithPopulatedHeader(PacketTypeStopNode);
nodeList->writeUnverifiedDatagram(diePacket, childNode);
}

View file

@ -50,10 +50,8 @@ const unsigned short STUN_SERVER_PORT = 3478;
const QString DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY = "domain-server.local-port";
const QString DOMAIN_SERVER_LOCAL_HTTP_PORT_SMEM_KEY = "domain-server.local-http-port";
const QString DOMAIN_SERVER_LOCAL_HTTPS_PORT_SMEM_KEY = "domain-server.local-https-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 QHostAddress DEFAULT_ASSIGNMENT_CLIENT_MONITOR_HOSTNAME = QHostAddress::LocalHost;
const QString USERNAME_UUID_REPLACEMENT_STATS_KEY = "$username";

View file

@ -46,10 +46,10 @@ void ThreadedAssignment::setFinished(bool isFinished) {
// this ensures we won't process a domain list while we are going down
auto nodeList = DependencyManager::get<NodeList>();
disconnect(&nodeList->getNodeSocket(), 0, this, 0);
// call our virtual aboutToFinish method - this gives the ThreadedAssignment subclass a chance to cleanup
aboutToFinish();
// if we have a datagram processing thread, quit it and wait on it to make sure that
// the node socket is back on the same thread as the NodeList