From c9d6a44c3a5cc399d115738404e1e7acad332415 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 24 Feb 2015 16:56:13 -0800 Subject: [PATCH] fix up command-line parsing --- assignment-client/src/AssignmentClient.cpp | 49 ++------ assignment-client/src/AssignmentClient.h | 4 +- assignment-client/src/AssignmentClientApp.cpp | 118 +++++++++++++++++- assignment-client/src/AssignmentClientApp.h | 16 +++ .../src/AssignmentClientMonitor.cpp | 60 ++++++--- .../src/AssignmentClientMonitor.h | 15 ++- 6 files changed, 196 insertions(+), 66 deletions(-) diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index 2dfc3787de..cb2da51031 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -40,7 +39,9 @@ SharedAssignmentPointer AssignmentClient::_currentAssignment; int hifiSockAddrMeta = qRegisterMetaType("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), _assignmentServerHostname(DEFAULT_ASSIGNMENT_SERVER_HOSTNAME), _localASPortSharedMem(NULL), @@ -73,51 +74,20 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) : // set the logging target to the the CHILD_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 _requestAssignment = Assignment(Assignment::RequestCommand, requestAssignmentType, assignmentPool); // 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 - if (argumentVariantMap.contains(ASSIGNMENT_WALLET_DESTINATION_ID_OPTION)) { - QUuid walletUUID = argumentVariantMap.value(ASSIGNMENT_WALLET_DESTINATION_ID_OPTION).toString(); + if (!walletUUID.isNull()) { qDebug() << "The destination wallet UUID for credits is" << uuidStringWithoutCurlyBraces(walletUUID); _requestAssignment.setWalletUUID(walletUUID); } - quint16 assignmentServerPort = DEFAULT_DOMAIN_SERVER_PORT; - // check for an overriden assignment server hostname - if (argumentVariantMap.contains(CUSTOM_ASSIGNMENT_SERVER_HOSTNAME_OPTION)) { + if (assignmentServerHostname != "") { // change the hostname for our assignment server - _assignmentServerHostname = argumentVariantMap.value(CUSTOM_ASSIGNMENT_SERVER_HOSTNAME_OPTION).toString(); - } - - // 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(); + _assignmentServerHostname = assignmentServerHostname; } _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 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())); _requestTimer.start(ASSIGNMENT_REQUEST_INTERVAL_MSECS); @@ -199,9 +173,6 @@ void AssignmentClient::sendAssignmentRequest() { nodeList->setAssignmentServerSocket(_assignmentServerSocket); } } - else { - qDebug () << "- will attempt to connect to domain-server on" << _assignmentServerSocket.getPort(); - } } nodeList->sendAssignment(_requestAssignment); diff --git a/assignment-client/src/AssignmentClient.h b/assignment-client/src/AssignmentClient.h index e105309e10..67a5dc89a7 100644 --- a/assignment-client/src/AssignmentClient.h +++ b/assignment-client/src/AssignmentClient.h @@ -21,7 +21,9 @@ class QSharedMemory; class AssignmentClient : public QCoreApplication { Q_OBJECT 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; } private slots: diff --git a/assignment-client/src/AssignmentClientApp.cpp b/assignment-client/src/AssignmentClientApp.cpp index 477f1a2cf8..7f174f0833 100644 --- a/assignment-client/src/AssignmentClientApp.cpp +++ b/assignment-client/src/AssignmentClientApp.cpp @@ -13,6 +13,7 @@ #include #include +#include #include "Assignment.h" #include "AssignmentClient.h" @@ -37,9 +38,35 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) : 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); + 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())) { qCritical() << parser.errorText() << endl; parser.showHelp(); @@ -51,16 +78,99 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) : Q_UNREACHABLE(); } + + const QVariantMap argumentVariantMap = HifiConfigVariantMap::mergeCLParametersWithJSONConfig(arguments()); + + unsigned int numForks = 0; if (parser.isSet(numChildsOption)) { numForks = parser.value(numChildsOption).toInt(); } - if (numForks) { - AssignmentClientMonitor monitor(argc, argv, numForks); + unsigned int minForks = 0; + 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(); } else { - AssignmentClient client(argc, argv); + AssignmentClient client(argc, argv, requestAssignmentType, assignmentPool, + walletUUID, assignmentServerHostname, assignmentServerPort); client.exec(); } } diff --git a/assignment-client/src/AssignmentClientApp.h b/assignment-client/src/AssignmentClientApp.h index c5099ff25c..531035ef0e 100644 --- a/assignment-client/src/AssignmentClientApp.h +++ b/assignment-client/src/AssignmentClientApp.h @@ -9,10 +9,26 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#ifndef hifi_AssignmentClientApp_h +#define hifi_AssignmentClientApp_h + + #include +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 { Q_OBJECT public: AssignmentClientApp(int argc, char* argv[]); }; + +#endif // hifi_AssignmentClientApp_h diff --git a/assignment-client/src/AssignmentClientMonitor.cpp b/assignment-client/src/AssignmentClientMonitor.cpp index 803c7fd5c7..0f8e7adc17 100644 --- a/assignment-client/src/AssignmentClientMonitor.cpp +++ b/assignment-client/src/AssignmentClientMonitor.cpp @@ -16,6 +16,7 @@ #include #include "AssignmentClientMonitor.h" +#include "AssignmentClientApp.h" #include "AssignmentClientChildData.h" #include "PacketHeaders.h" #include "SharedUtil.h" @@ -24,8 +25,20 @@ const char* NUM_FORKS_PARAMETER = "-n"; const QString ASSIGNMENT_CLIENT_MONITOR_TARGET_NAME = "assignment-client-monitor"; -AssignmentClientMonitor::AssignmentClientMonitor(int &argc, char **argv, const unsigned int numAssignmentClientForks) : - QCoreApplication(argc, argv) +AssignmentClientMonitor::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) : + 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 LogHandler::getInstance().setTargetName(ASSIGNMENT_CLIENT_MONITOR_TARGET_NAME); @@ -36,16 +49,6 @@ AssignmentClientMonitor::AssignmentClientMonitor(int &argc, char **argv, const u #else ShutdownEventListener::getInstance(); #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 DependencyManager::registerInheritance(); @@ -58,7 +61,7 @@ AssignmentClientMonitor::AssignmentClientMonitor(int &argc, char **argv, const u 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 (unsigned int i = 0; i < numAssignmentClientForks; i++) { + for (unsigned int i = 0; i < _numAssignmentClientForks; i++) { spawnChildClient(); } @@ -83,7 +86,26 @@ void AssignmentClientMonitor::stopChildProcesses() { void AssignmentClientMonitor::spawnChildClient() { 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 assignmentClient->setProcessChannelMode(QProcess::ForwardedChannels); @@ -98,26 +120,24 @@ void AssignmentClientMonitor::checkSpares() { auto nodeList = DependencyManager::get(); QUuid aSpareId = ""; unsigned int spareCount = 0; + unsigned int totalCount = 0; nodeList->removeSilentNodes(); nodeList->eachNode([&](const SharedNodePointer& node) { AssignmentClientChildData *childData = static_cast(node->getLinkedData()); + totalCount ++; if (childData->getChildType() == "none") { spareCount ++; aSpareId = node->getUUID(); } }); - if (spareCount != 1) { - qDebug() << "spare count is" << spareCount; - } - - if (spareCount < 1) { + if (spareCount < 1 && totalCount < _maxAssignmentClientForks) { spawnChildClient(); } - if (spareCount > 1) { + if (spareCount > 1 && totalCount > _minAssignmentClientForks) { // kill aSpareId qDebug() << "asking child" << aSpareId << "to exit."; SharedNodePointer childNode = nodeList->nodeWithUUID(aSpareId); diff --git a/assignment-client/src/AssignmentClientMonitor.h b/assignment-client/src/AssignmentClientMonitor.h index 71ae34bc8c..e40a10014b 100644 --- a/assignment-client/src/AssignmentClientMonitor.h +++ b/assignment-client/src/AssignmentClientMonitor.h @@ -27,7 +27,10 @@ extern const char* NUM_FORKS_PARAMETER; class AssignmentClientMonitor : public QCoreApplication { Q_OBJECT 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(); void stopChildProcesses(); @@ -37,8 +40,16 @@ private slots: private: void spawnChildClient(); - QStringList _childArguments; 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