Merge branch 'assignment-client-keep-a-spare-again' of github.com:sethalves/hifi into assignment-client-keep-a-spare-x

This commit is contained in:
Seth Alves 2015-02-24 17:10:32 -08:00
commit 0c28e220d1
6 changed files with 196 additions and 66 deletions

View file

@ -18,7 +18,6 @@
#include <AccountManager.h> #include <AccountManager.h>
#include <AddressManager.h> #include <AddressManager.h>
#include <Assignment.h> #include <Assignment.h>
#include <HifiConfigVariantMap.h>
#include <LogHandler.h> #include <LogHandler.h>
#include <LogUtils.h> #include <LogUtils.h>
#include <LimitedNodeList.h> #include <LimitedNodeList.h>
@ -40,7 +39,9 @@ SharedAssignmentPointer AssignmentClient::_currentAssignment;
int hifiSockAddrMeta = qRegisterMetaType<HifiSockAddr>("HifiSockAddr"); int hifiSockAddrMeta = qRegisterMetaType<HifiSockAddr>("HifiSockAddr");
AssignmentClient::AssignmentClient(int &argc, char **argv) : AssignmentClient::AssignmentClient(int &argc, char **argv,
Assignment::Type requestAssignmentType, QString assignmentPool, QUuid walletUUID,
QString assignmentServerHostname, quint16 assignmentServerPort) :
QCoreApplication(argc, argv), QCoreApplication(argc, argv),
_assignmentServerHostname(DEFAULT_ASSIGNMENT_SERVER_HOSTNAME), _assignmentServerHostname(DEFAULT_ASSIGNMENT_SERVER_HOSTNAME),
_localASPortSharedMem(NULL), _localASPortSharedMem(NULL),
@ -73,51 +74,20 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) :
// set the logging target to the the CHILD_TARGET_NAME // set the logging target to the the CHILD_TARGET_NAME
LogHandler::getInstance().setTargetName(ASSIGNMENT_CLIENT_TARGET_NAME); LogHandler::getInstance().setTargetName(ASSIGNMENT_CLIENT_TARGET_NAME);
const QVariantMap argumentVariantMap = HifiConfigVariantMap::mergeCLParametersWithJSONConfig(arguments());
const QString ASSIGNMENT_TYPE_OVERRIDE_OPTION = "t";
const QString ASSIGNMENT_POOL_OPTION = "pool";
const QString ASSIGNMENT_WALLET_DESTINATION_ID_OPTION = "wallet";
const QString CUSTOM_ASSIGNMENT_SERVER_HOSTNAME_OPTION = "a";
const QString CUSTOM_ASSIGNMENT_SERVER_PORT_OPTION = "p";
Assignment::Type requestAssignmentType = Assignment::AllTypes;
// check for an assignment type passed on the command line or in the config
if (argumentVariantMap.contains(ASSIGNMENT_TYPE_OVERRIDE_OPTION)) {
requestAssignmentType = (Assignment::Type) argumentVariantMap.value(ASSIGNMENT_TYPE_OVERRIDE_OPTION).toInt();
}
QString assignmentPool;
// check for an assignment pool passed on the command line or in the config
if (argumentVariantMap.contains(ASSIGNMENT_POOL_OPTION)) {
assignmentPool = argumentVariantMap.value(ASSIGNMENT_POOL_OPTION).toString();
}
// setup our _requestAssignment member variable from the passed arguments // setup our _requestAssignment member variable from the passed arguments
_requestAssignment = Assignment(Assignment::RequestCommand, requestAssignmentType, assignmentPool); _requestAssignment = Assignment(Assignment::RequestCommand, requestAssignmentType, assignmentPool);
// check for a wallet UUID on the command line or in the config // check for a wallet UUID on the command line or in the config
// this would represent where the user running AC wants funds sent to // this would represent where the user running AC wants funds sent to
if (argumentVariantMap.contains(ASSIGNMENT_WALLET_DESTINATION_ID_OPTION)) { if (!walletUUID.isNull()) {
QUuid walletUUID = argumentVariantMap.value(ASSIGNMENT_WALLET_DESTINATION_ID_OPTION).toString();
qDebug() << "The destination wallet UUID for credits is" << uuidStringWithoutCurlyBraces(walletUUID); qDebug() << "The destination wallet UUID for credits is" << uuidStringWithoutCurlyBraces(walletUUID);
_requestAssignment.setWalletUUID(walletUUID); _requestAssignment.setWalletUUID(walletUUID);
} }
quint16 assignmentServerPort = DEFAULT_DOMAIN_SERVER_PORT;
// check for an overriden assignment server hostname // check for an overriden assignment server hostname
if (argumentVariantMap.contains(CUSTOM_ASSIGNMENT_SERVER_HOSTNAME_OPTION)) { if (assignmentServerHostname != "") {
// change the hostname for our assignment server // change the hostname for our assignment server
_assignmentServerHostname = argumentVariantMap.value(CUSTOM_ASSIGNMENT_SERVER_HOSTNAME_OPTION).toString(); _assignmentServerHostname = assignmentServerHostname;
}
// check for an overriden assignment server port
if (argumentVariantMap.contains(CUSTOM_ASSIGNMENT_SERVER_PORT_OPTION)) {
assignmentServerPort =
argumentVariantMap.value(CUSTOM_ASSIGNMENT_SERVER_PORT_OPTION).toString().toUInt();
} }
_assignmentServerSocket = HifiSockAddr(_assignmentServerHostname, assignmentServerPort, true); _assignmentServerSocket = HifiSockAddr(_assignmentServerHostname, assignmentServerPort, true);
@ -128,6 +98,10 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) :
// call a timer function every ASSIGNMENT_REQUEST_INTERVAL_MSECS to ask for assignment, if required // call a timer function every ASSIGNMENT_REQUEST_INTERVAL_MSECS to ask for assignment, if required
qDebug() << "Waiting for assignment -" << _requestAssignment; qDebug() << "Waiting for assignment -" << _requestAssignment;
if (_assignmentServerHostname != "localhost") {
qDebug () << "- will attempt to connect to domain-server on" << _assignmentServerSocket.getPort();
}
connect(&_requestTimer, SIGNAL(timeout()), SLOT(sendAssignmentRequest())); connect(&_requestTimer, SIGNAL(timeout()), SLOT(sendAssignmentRequest()));
_requestTimer.start(ASSIGNMENT_REQUEST_INTERVAL_MSECS); _requestTimer.start(ASSIGNMENT_REQUEST_INTERVAL_MSECS);
@ -199,9 +173,6 @@ void AssignmentClient::sendAssignmentRequest() {
nodeList->setAssignmentServerSocket(_assignmentServerSocket); nodeList->setAssignmentServerSocket(_assignmentServerSocket);
} }
} }
else {
qDebug () << "- will attempt to connect to domain-server on" << _assignmentServerSocket.getPort();
}
} }
nodeList->sendAssignment(_requestAssignment); nodeList->sendAssignment(_requestAssignment);

View file

@ -21,7 +21,9 @@ class QSharedMemory;
class AssignmentClient : public QCoreApplication { class AssignmentClient : public QCoreApplication {
Q_OBJECT Q_OBJECT
public: public:
AssignmentClient(int &argc, char **argv);
AssignmentClient(int &argc, char **argv, Assignment::Type requestAssignmentType, QString assignmentPool,
QUuid walletUUID, QString assignmentServerHostname, quint16 assignmentServerPort);
static const SharedAssignmentPointer& getCurrentAssignment() { return _currentAssignment; } static const SharedAssignmentPointer& getCurrentAssignment() { return _currentAssignment; }
private slots: private slots:

View file

@ -13,6 +13,7 @@
#include <LogHandler.h> #include <LogHandler.h>
#include <SharedUtil.h> #include <SharedUtil.h>
#include <HifiConfigVariantMap.h>
#include "Assignment.h" #include "Assignment.h"
#include "AssignmentClient.h" #include "AssignmentClient.h"
@ -37,9 +38,35 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) :
const QCommandLineOption helpOption = parser.addHelpOption(); const QCommandLineOption helpOption = parser.addHelpOption();
const QCommandLineOption numChildsOption("n", "number of children to fork", "child-count"); const QCommandLineOption clientTypeOption(ASSIGNMENT_TYPE_OVERRIDE_OPTION,
"run single assignment client of given type", "type");
parser.addOption(clientTypeOption);
const QCommandLineOption poolOption(ASSIGNMENT_POOL_OPTION, "set assignment pool", "pool-name");
parser.addOption(poolOption);
const QCommandLineOption walletDestinationOption(ASSIGNMENT_WALLET_DESTINATION_ID_OPTION,
"set wallet destination", "wallet-uuid");
parser.addOption(walletDestinationOption);
const QCommandLineOption assignmentServerHostnameOption(CUSTOM_ASSIGNMENT_SERVER_HOSTNAME_OPTION,
"set assignment-server hostname", "hostname");
parser.addOption(assignmentServerHostnameOption);
const QCommandLineOption assignmentServerPortOption(CUSTOM_ASSIGNMENT_SERVER_PORT_OPTION,
"set assignment-server port", "port");
parser.addOption(assignmentServerPortOption);
const QCommandLineOption numChildsOption(ASSIGNMENT_NUM_FORKS_OPTION, "number of children to fork", "child-count");
parser.addOption(numChildsOption); parser.addOption(numChildsOption);
const QCommandLineOption minChildsOption(ASSIGNMENT_MIN_FORKS_OPTION, "minimum number of children", "child-count");
parser.addOption(minChildsOption);
const QCommandLineOption maxChildsOption(ASSIGNMENT_MAX_FORKS_OPTION, "maximum number of children", "child-count");
parser.addOption(maxChildsOption);
if (!parser.parse(QCoreApplication::arguments())) { if (!parser.parse(QCoreApplication::arguments())) {
qCritical() << parser.errorText() << endl; qCritical() << parser.errorText() << endl;
parser.showHelp(); parser.showHelp();
@ -51,16 +78,99 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) :
Q_UNREACHABLE(); Q_UNREACHABLE();
} }
const QVariantMap argumentVariantMap = HifiConfigVariantMap::mergeCLParametersWithJSONConfig(arguments());
unsigned int numForks = 0; unsigned int numForks = 0;
if (parser.isSet(numChildsOption)) { if (parser.isSet(numChildsOption)) {
numForks = parser.value(numChildsOption).toInt(); numForks = parser.value(numChildsOption).toInt();
} }
if (numForks) { unsigned int minForks = 0;
AssignmentClientMonitor monitor(argc, argv, numForks); if (parser.isSet(minChildsOption)) {
minForks = parser.value(minChildsOption).toInt();
}
unsigned int maxForks = 0;
if (parser.isSet(maxChildsOption)) {
maxForks = parser.value(maxChildsOption).toInt();
}
Assignment::Type requestAssignmentType = Assignment::AllTypes;
if (argumentVariantMap.contains(ASSIGNMENT_TYPE_OVERRIDE_OPTION)) {
requestAssignmentType = (Assignment::Type) argumentVariantMap.value(ASSIGNMENT_TYPE_OVERRIDE_OPTION).toInt();
}
if (parser.isSet(clientTypeOption)) {
if (numForks || minForks || maxForks) {
qCritical() << "don't use -t with forking mode.";
parser.showHelp();
Q_UNREACHABLE();
}
requestAssignmentType = (Assignment::Type) parser.value(clientTypeOption).toInt();
}
QString assignmentPool;
// check for an assignment pool passed on the command line or in the config
if (argumentVariantMap.contains(ASSIGNMENT_POOL_OPTION)) {
assignmentPool = argumentVariantMap.value(ASSIGNMENT_POOL_OPTION).toString();
}
if (parser.isSet(poolOption)) {
assignmentPool = parser.value(poolOption);
}
QUuid walletUUID;
if (argumentVariantMap.contains(ASSIGNMENT_WALLET_DESTINATION_ID_OPTION)) {
walletUUID = argumentVariantMap.value(ASSIGNMENT_WALLET_DESTINATION_ID_OPTION).toString();
}
if (parser.isSet(walletDestinationOption)) {
walletUUID = parser.value(walletDestinationOption);
}
QString assignmentServerHostname;
if (argumentVariantMap.contains(ASSIGNMENT_WALLET_DESTINATION_ID_OPTION)) {
assignmentServerHostname = argumentVariantMap.value(CUSTOM_ASSIGNMENT_SERVER_HOSTNAME_OPTION).toString();
}
if (parser.isSet(assignmentServerHostnameOption)) {
assignmentServerHostname = parser.value(assignmentServerHostnameOption);
}
// check for an overriden assignment server port
quint16 assignmentServerPort = DEFAULT_DOMAIN_SERVER_PORT;
if (argumentVariantMap.contains(ASSIGNMENT_WALLET_DESTINATION_ID_OPTION)) {
assignmentServerPort = argumentVariantMap.value(CUSTOM_ASSIGNMENT_SERVER_PORT_OPTION).toString().toUInt();
}
if (parser.isSet(assignmentServerPortOption)) {
assignmentServerPort = parser.value(assignmentServerPortOption).toInt();
}
if (parser.isSet(numChildsOption)) {
if (minForks && minForks > numForks) {
qCritical() << "--min can't be more than -n";
parser.showHelp();
Q_UNREACHABLE();
}
if (maxForks && maxForks < numForks) {
qCritical() << "--max can't be less than -n";
parser.showHelp();
Q_UNREACHABLE();
}
}
if (numForks || minForks || maxForks) {
AssignmentClientMonitor monitor(argc, argv, numForks, minForks, maxForks, assignmentPool,
walletUUID, assignmentServerHostname, assignmentServerPort);
monitor.exec(); monitor.exec();
} else { } else {
AssignmentClient client(argc, argv); AssignmentClient client(argc, argv, requestAssignmentType, assignmentPool,
walletUUID, assignmentServerHostname, assignmentServerPort);
client.exec(); client.exec();
} }
} }

View file

@ -9,10 +9,26 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// //
#ifndef hifi_AssignmentClientApp_h
#define hifi_AssignmentClientApp_h
#include <QApplication> #include <QApplication>
const QString ASSIGNMENT_TYPE_OVERRIDE_OPTION = "t";
const QString ASSIGNMENT_POOL_OPTION = "pool";
const QString ASSIGNMENT_WALLET_DESTINATION_ID_OPTION = "wallet";
const QString CUSTOM_ASSIGNMENT_SERVER_HOSTNAME_OPTION = "a";
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";
class AssignmentClientApp : public QCoreApplication { class AssignmentClientApp : public QCoreApplication {
Q_OBJECT Q_OBJECT
public: public:
AssignmentClientApp(int argc, char* argv[]); AssignmentClientApp(int argc, char* argv[]);
}; };
#endif // hifi_AssignmentClientApp_h

View file

@ -16,6 +16,7 @@
#include <AddressManager.h> #include <AddressManager.h>
#include "AssignmentClientMonitor.h" #include "AssignmentClientMonitor.h"
#include "AssignmentClientApp.h"
#include "AssignmentClientChildData.h" #include "AssignmentClientChildData.h"
#include "PacketHeaders.h" #include "PacketHeaders.h"
#include "SharedUtil.h" #include "SharedUtil.h"
@ -24,8 +25,20 @@ const char* NUM_FORKS_PARAMETER = "-n";
const QString ASSIGNMENT_CLIENT_MONITOR_TARGET_NAME = "assignment-client-monitor"; const QString ASSIGNMENT_CLIENT_MONITOR_TARGET_NAME = "assignment-client-monitor";
AssignmentClientMonitor::AssignmentClientMonitor(int &argc, char **argv, const unsigned int numAssignmentClientForks) : AssignmentClientMonitor::AssignmentClientMonitor(int &argc, char **argv,
QCoreApplication(argc, argv) const unsigned int numAssignmentClientForks,
const unsigned int minAssignmentClientForks,
const unsigned int maxAssignmentClientForks,
QString assignmentPool, QUuid walletUUID, QString assignmentServerHostname,
quint16 assignmentServerPort) :
QCoreApplication(argc, argv),
_numAssignmentClientForks(numAssignmentClientForks),
_minAssignmentClientForks(minAssignmentClientForks),
_maxAssignmentClientForks(maxAssignmentClientForks),
_assignmentPool(assignmentPool),
_walletUUID(walletUUID),
_assignmentServerHostname(assignmentServerHostname),
_assignmentServerPort(assignmentServerPort)
{ {
// start the Logging class with the parent's target name // start the Logging class with the parent's target name
LogHandler::getInstance().setTargetName(ASSIGNMENT_CLIENT_MONITOR_TARGET_NAME); LogHandler::getInstance().setTargetName(ASSIGNMENT_CLIENT_MONITOR_TARGET_NAME);
@ -37,16 +50,6 @@ AssignmentClientMonitor::AssignmentClientMonitor(int &argc, char **argv, const u
ShutdownEventListener::getInstance(); ShutdownEventListener::getInstance();
#endif #endif
_childArguments = arguments();
// remove the parameter for the number of forks so it isn't passed to the child forked processes
int forksParameterIndex = _childArguments.indexOf(NUM_FORKS_PARAMETER);
// 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 // create a NodeList so we can receive stats from children
DependencyManager::registerInheritance<LimitedNodeList, NodeList>(); DependencyManager::registerInheritance<LimitedNodeList, NodeList>();
auto addressManager = DependencyManager::set<AddressManager>(); auto addressManager = DependencyManager::set<AddressManager>();
@ -58,7 +61,7 @@ AssignmentClientMonitor::AssignmentClientMonitor(int &argc, char **argv, const u
nodeList->putLocalPortIntoSharedMemory(ASSIGNMENT_CLIENT_MONITOR_LOCAL_PORT_SMEM_KEY, this); nodeList->putLocalPortIntoSharedMemory(ASSIGNMENT_CLIENT_MONITOR_LOCAL_PORT_SMEM_KEY, this);
// use QProcess to fork off a process for each of the child assignment clients // use QProcess to fork off a process for each of the child assignment clients
for (unsigned int i = 0; i < numAssignmentClientForks; i++) { for (unsigned int i = 0; i < _numAssignmentClientForks; i++) {
spawnChildClient(); spawnChildClient();
} }
@ -84,6 +87,25 @@ void AssignmentClientMonitor::stopChildProcesses() {
void AssignmentClientMonitor::spawnChildClient() { void AssignmentClientMonitor::spawnChildClient() {
QProcess *assignmentClient = new QProcess(this); QProcess *assignmentClient = new QProcess(this);
// unparse the parts of the command-line that the child cares about
QStringList _childArguments;
if (_assignmentPool != "") {
_childArguments.append("--" + ASSIGNMENT_POOL_OPTION);
_childArguments.append(_assignmentPool);
}
if (!_walletUUID.isNull()) {
_childArguments.append("--" + ASSIGNMENT_WALLET_DESTINATION_ID_OPTION);
_childArguments.append(_walletUUID.toString());
}
if (_assignmentServerHostname != "") {
_childArguments.append("--" + CUSTOM_ASSIGNMENT_SERVER_HOSTNAME_OPTION);
_childArguments.append(_assignmentServerHostname);
}
if (_assignmentServerPort != DEFAULT_DOMAIN_SERVER_PORT) {
_childArguments.append("--" + CUSTOM_ASSIGNMENT_SERVER_PORT_OPTION);
_childArguments.append(QString::number(_assignmentServerPort));
}
// make sure that the output from the child process appears in our output // make sure that the output from the child process appears in our output
assignmentClient->setProcessChannelMode(QProcess::ForwardedChannels); assignmentClient->setProcessChannelMode(QProcess::ForwardedChannels);
@ -98,26 +120,24 @@ void AssignmentClientMonitor::checkSpares() {
auto nodeList = DependencyManager::get<NodeList>(); auto nodeList = DependencyManager::get<NodeList>();
QUuid aSpareId = ""; QUuid aSpareId = "";
unsigned int spareCount = 0; unsigned int spareCount = 0;
unsigned int totalCount = 0;
nodeList->removeSilentNodes(); nodeList->removeSilentNodes();
nodeList->eachNode([&](const SharedNodePointer& node) { nodeList->eachNode([&](const SharedNodePointer& node) {
AssignmentClientChildData *childData = static_cast<AssignmentClientChildData*>(node->getLinkedData()); AssignmentClientChildData *childData = static_cast<AssignmentClientChildData*>(node->getLinkedData());
totalCount ++;
if (childData->getChildType() == "none") { if (childData->getChildType() == "none") {
spareCount ++; spareCount ++;
aSpareId = node->getUUID(); aSpareId = node->getUUID();
} }
}); });
if (spareCount != 1) { if (spareCount < 1 && totalCount < _maxAssignmentClientForks) {
qDebug() << "spare count is" << spareCount;
}
if (spareCount < 1) {
spawnChildClient(); spawnChildClient();
} }
if (spareCount > 1) { if (spareCount > 1 && totalCount > _minAssignmentClientForks) {
// kill aSpareId // kill aSpareId
qDebug() << "asking child" << aSpareId << "to exit."; qDebug() << "asking child" << aSpareId << "to exit.";
SharedNodePointer childNode = nodeList->nodeWithUUID(aSpareId); SharedNodePointer childNode = nodeList->nodeWithUUID(aSpareId);

View file

@ -27,7 +27,10 @@ extern const char* NUM_FORKS_PARAMETER;
class AssignmentClientMonitor : public QCoreApplication { class AssignmentClientMonitor : public QCoreApplication {
Q_OBJECT Q_OBJECT
public: public:
AssignmentClientMonitor(int &argc, char **argv, const unsigned int numAssignmentClientForks); AssignmentClientMonitor(int &argc, char **argv, const unsigned int numAssignmentClientForks,
const unsigned int minAssignmentClientForks, const unsigned int maxAssignmentClientForks,
QString assignmentPool, QUuid walletUUID, QString assignmentServerHostname,
quint16 assignmentServerPort);
~AssignmentClientMonitor(); ~AssignmentClientMonitor();
void stopChildProcesses(); void stopChildProcesses();
@ -37,8 +40,16 @@ private slots:
private: private:
void spawnChildClient(); void spawnChildClient();
QStringList _childArguments;
QTimer _checkSparesTimer; // every few seconds see if it need fewer or more spare children QTimer _checkSparesTimer; // every few seconds see if it need fewer or more spare children
const unsigned int _numAssignmentClientForks;
const unsigned int _minAssignmentClientForks;
const unsigned int _maxAssignmentClientForks;
QString _assignmentPool;
QUuid _walletUUID;
QString _assignmentServerHostname;
quint16 _assignmentServerPort;
}; };
#endif // hifi_AssignmentClientMonitor_h #endif // hifi_AssignmentClientMonitor_h