diff --git a/source/ArmarXGui/gui-plugins/ScenarioManager/ScenarioManagerWidgetController.cpp b/source/ArmarXGui/gui-plugins/ScenarioManager/ScenarioManagerWidgetController.cpp index a3dc0a5ac6b6dc2ec95cc08d6c6779fa2d548bc5..e70fe69e3093982b843f96af8a6fa0b89f105836 100644 --- a/source/ArmarXGui/gui-plugins/ScenarioManager/ScenarioManagerWidgetController.cpp +++ b/source/ArmarXGui/gui-plugins/ScenarioManager/ScenarioManagerWidgetController.cpp @@ -252,6 +252,11 @@ void ScenarioManagerWidgetController::onConnectComponent() } +void ScenarioManagerWidgetController::onExitComponent() +{ + scenarioListController.stopUpdateTask(); +} + void ScenarioManagerWidgetController::reparsePackages() { QSettings settings("KIT", "ScenarioManager"); diff --git a/source/ArmarXGui/gui-plugins/ScenarioManager/ScenarioManagerWidgetController.h b/source/ArmarXGui/gui-plugins/ScenarioManager/ScenarioManagerWidgetController.h index 254852d5a5179c31a259f5af1da077130f0cc1a7..852cac6fa086474ad6ca01d20e73c15887cdc253 100644 --- a/source/ArmarXGui/gui-plugins/ScenarioManager/ScenarioManagerWidgetController.h +++ b/source/ArmarXGui/gui-plugins/ScenarioManager/ScenarioManagerWidgetController.h @@ -104,6 +104,8 @@ namespace armarx */ void onConnectComponent() override; + void onExitComponent() override; + public slots: /* QT slot declarations */ void reparsePackages(); diff --git a/source/ArmarXGui/gui-plugins/ScenarioManager/controller/ApplicationDatabaseController.cpp b/source/ArmarXGui/gui-plugins/ScenarioManager/controller/ApplicationDatabaseController.cpp index 957e8f068899a043b33e9ff73a2db9927eb0ac99..c87e59be79a70ae8ea6c92c80693d74c96daf521 100644 --- a/source/ArmarXGui/gui-plugins/ScenarioManager/controller/ApplicationDatabaseController.cpp +++ b/source/ArmarXGui/gui-plugins/ScenarioManager/controller/ApplicationDatabaseController.cpp @@ -117,8 +117,8 @@ void ApplicationDatabaseController::on_itemClicked(const QModelIndex& index) //appItem = reinterpret_cast<ApplicationDatabaseItem*>(rootItem->child(index.parent().row())->child(index.row())); std::string cacheDir = Parser::IceParser::getCacheDir(); - executor->loadAndSetCachedProperties(appItem->getApplication(), cacheDir); - emit applicationClicked(appItem->getApplication()); + // executor->loadAndSetCachedProperties(appItem->getApplication(), cacheDir); + // emit applicationClicked(appItem->getApplication()); } else //scenario clicked { diff --git a/source/ArmarXGui/gui-plugins/ScenarioManager/controller/DetailedApplicationController.cpp b/source/ArmarXGui/gui-plugins/ScenarioManager/controller/DetailedApplicationController.cpp index 502dc939d8d981a5a3eb9b83e59b25c5f8408728..d2691693e08a1dcf28f2e76dcbec516a6e1b71b1 100644 --- a/source/ArmarXGui/gui-plugins/ScenarioManager/controller/DetailedApplicationController.cpp +++ b/source/ArmarXGui/gui-plugins/ScenarioManager/controller/DetailedApplicationController.cpp @@ -154,7 +154,7 @@ void DetailedApplicationController::setProperty(std::string name, std::string va } } -void DetailedApplicationController::setIceEnvVariable(string name, string value) +void DetailedApplicationController::setIceEnvVariable(std::string name, std::string value) { if (currentScenario.get() != nullptr) { @@ -178,7 +178,7 @@ void DetailedApplicationController::start() { startScenario(currentScenario); } - catch (IceGrid::ServerStartException ex) + catch (IceGrid::ServerStartException& ex) { showWarningDialog("Ice had an launching error. Please make sure your remote launch settings are correct"); } @@ -207,7 +207,7 @@ void DetailedApplicationController::startScenario(ScenarioPtr scenario) { executor->startScenario(scenario).get(); } - catch (IceGrid::ServerStartException ex) + catch (IceGrid::ServerStartException& ex) { showWarningDialog("Ice had an launching error. Please make sure your remote launch settings are correct"); } @@ -218,7 +218,7 @@ void DetailedApplicationController::startScenario(ScenarioPtr scenario) { executor->deployScenario(scenario).get(); } - catch (IceGrid::DeploymentException ex) + catch (IceGrid::DeploymentException& ex) { showWarningDialog(QString::fromStdString(ex.reason)); } @@ -265,7 +265,7 @@ void DetailedApplicationController::save() { executor->restartScenario(currentScenario); } - catch (IceGrid::ServerStartException ex) + catch (IceGrid::ServerStartException& ex) { showWarningDialog("Ice had an launching error. Please make sure your remote launch settings are correct"); } diff --git a/source/ArmarXGui/gui-plugins/ScenarioManager/controller/ScenarioListController.cpp b/source/ArmarXGui/gui-plugins/ScenarioManager/controller/ScenarioListController.cpp index 7ba11964db8a6471e0032a076eacb985fd983c50..7152376b3bc67ed61321f6afb5c97943ca912ee4 100644 --- a/source/ArmarXGui/gui-plugins/ScenarioManager/controller/ScenarioListController.cpp +++ b/source/ArmarXGui/gui-plugins/ScenarioManager/controller/ScenarioListController.cpp @@ -56,12 +56,19 @@ ScenarioListController::ScenarioListController(PackageVectorPtr packages, Execut model(new FilterableTreeModelSortFilterProxyModel()), packages(packages), executor(executor) { + qRegisterMetaType<ApplicationInstanceStatusMap>("ApplicationInstanceStatusMap"); qRegisterMetaType<FilterableTreeModelSortFilterProxyModelPtr>("FilterableTreeModelSortFilterProxyModelPtr"); QTimer* timer = new QTimer(this); QObject::connect(timer, SIGNAL(timeout()), this, SLOT(updateStati())); timer->start(UPDATE_TIMER); + updateTask = new armarx::SimplePeriodicTask<>([&] + { + fetchStati(); + }, 100, false, "ScenarioManagerUpdateStatusTask"); + updateTask->start(); + model->setDynamicSortFilter(true); model->setSourceModel(&treemodel); @@ -70,11 +77,12 @@ ScenarioListController::ScenarioListController(PackageVectorPtr packages, Execut QObject::connect(&treemodel, SIGNAL(applicationsDrop(QList<QPair<QString, ScenarioManager::Data_Structure::Application*>>, int, QModelIndex)), this, SLOT(addApplicationsToScenario(QList<QPair<QString, ScenarioManager::Data_Structure::Application*>>, int, QModelIndex))); + QObject::connect(this, SIGNAL(statusFetched(ApplicationInstanceStatusMap)), this, SLOT(updateStati(ApplicationInstanceStatusMap))); } ScenarioListController::~ScenarioListController() { - + updateTask->stop(); } FilterableTreeModelSortFilterProxyModelPtr ScenarioListController::getTreeModel() @@ -128,6 +136,11 @@ void ScenarioListController::stop(int row, int column, QModelIndex parent) } } +void ScenarioListController::stopUpdateTask() +{ + updateTask->stop(); +} + void ScenarioListController::start(int row, int column, QModelIndex parent, ScenarioStartModes mode) { ScenarioItem* item = model->data(model->index(row, column, parent), SCENARIOITEMSOURCE).value<ScenarioItem*>(); @@ -248,27 +261,26 @@ void ScenarioListController::startScenario(ScenarioItem* scenarioItem, ScenarioS } statusManager.setIceScenario(scenario, true); - if (executor->isScenarioDeployed(scenario)) - { - try - { - executor->startScenario(scenario).get(); - } - catch (IceGrid::ServerStartException ex) - { - showWarningDialog("Ice had an launching error. Please make sure your remote launch settings are correct"); - } - } - else + if (!executor->isScenarioDeployed(scenario)) { try { executor->deployScenario(scenario).get(); } - catch (IceGrid::DeploymentException ex) + catch (IceGrid::DeploymentException& ex) { showWarningDialog(QString::fromStdString(ex.reason)); } + + } + try + { + executor->startScenario(scenario).get(); + } + catch (IceGrid::ServerStartException& ex) + { + showWarningDialog("Ice had an launching error. Please make sure your remote launch settings are correct. Did you sync everything?\nId: " + QString::fromStdString(ex.id) + + "\nReason: " + QString::fromStdString(ex.reason)) ; } } } @@ -304,7 +316,7 @@ void ScenarioListController::restart(int row, int column, QModelIndex parent) { executor->restartScenario(item->getScenario()); } - catch (IceGrid::ServerStartException ex) + catch (IceGrid::ServerStartException& ex) { showWarningDialog("Ice had an launching error. Please make sure your remote launch settings are correct"); } @@ -440,7 +452,7 @@ void ScenarioListController::addApplicationsToScenario(QList<QPair<QString, Appl std::ofstream out(configPath); out.close(); - ApplicationInstancePtr appInstance(new ApplicationInstance(appName, app->getPathToExecutable(), instanceName, configPath, appPackage->getName(), scenario, "NodeMain", true, true)); + ApplicationInstancePtr appInstance(new ApplicationInstance(appName, app->getPathToExecutable(), instanceName, configPath, appPackage->getName(), scenario, "", true, true)); std::string cacheDir = Parser::IceParser::getCacheDir(); @@ -596,7 +608,7 @@ void ScenarioListController::createdScenario(std::string name, std::string packa return; } - if (parser.isScenarioExistend(name, package)) + if (parser.isScenarioexistent(name, package)) { QMessageBox box; QString message("The Scenario " + QString::fromStdString(name) + " already exists in Package " + QString::fromStdString(packageStr)); @@ -851,11 +863,38 @@ int ScenarioListController::findScenario(ScenarioItem* rootItem, std::string nam return -1; } -void ScenarioListController::updateStati() + +void ScenarioListController::fetchStati() { + std::vector<ApplicationInstancePtr> apps; + { + armarx::ScopedLock lock(applicationInstanceMutex); + apps.swap(applicationInstances); + } + if (apps.empty()) + { + return; + } + ApplicationInstanceStatusMap stati; IceUtil::Time start = IceUtil::Time ::now(); - bool changed = false; //update all app instances and scenarios + for (ApplicationInstancePtr appInst : apps) + { + std::string status = executor->getApplicationStatus(appInst); + stati[appInst] = status; + + } + ARMARX_DEBUG << deactivateSpam(5) << "Fetching scenario stati took " << (IceUtil::Time::now() - start).toMilliSecondsDouble() << " ms"; + emit statusFetched(stati); +} + + +void ScenarioListController::updateStati() +{ + //update all app instances and scenarios + // but this needs to be done async -> first get list of applications, + // then send these to other thread + std::vector<ApplicationInstancePtr> apps; for (ScenarioManager::Data_Structure::PackagePtr& package : *packages) { ScenarioVectorPtr scenarios = package->getScenarios(); @@ -864,16 +903,30 @@ void ScenarioListController::updateStati() ApplicationInstanceVectorPtr appInsts = scenario->getApplications(); for (ApplicationInstancePtr appInst : *appInsts) { - std::string status = executor->getApplicationStatus(appInst); - bool statusChanged = appInst->setStatus(status); - changed |= statusChanged; + apps.push_back(appInst); } } } - ARMARX_DEBUG << deactivateSpam(5) << "Updating scenarios took " << (IceUtil::Time::now() - start).toMilliSecondsDouble() << " ms"; + + { + armarx::ScopedLock lock(applicationInstanceMutex); + apps.swap(applicationInstances); + } +} + +void ScenarioListController::updateStati(ApplicationInstanceStatusMap stati) +{ + bool changed = false; + for (auto& pair : stati) + { + + bool statusChanged = pair.first->setStatus(pair.second); + changed |= statusChanged; + } + // ARMARX_DEBUG << deactivateSpam(5) << "Updating scenarios took " << (IceUtil::Time::now() - start).toMilliSecondsDouble() << " ms"; if (changed) { - start = IceUtil::Time ::now(); + auto start = IceUtil::Time ::now(); treemodel.update(); ARMARX_DEBUG << deactivateSpam(5) << "Updating scenario Model took " << (IceUtil::Time::now() - start).toMilliSecondsDouble() << " ms"; } diff --git a/source/ArmarXGui/gui-plugins/ScenarioManager/controller/ScenarioListController.h b/source/ArmarXGui/gui-plugins/ScenarioManager/controller/ScenarioListController.h index 28e2179ed086c0408afd26edc2c05fad61032854..55dcff633c67f57a965fc58abd1d70fca6bf1fa2 100644 --- a/source/ArmarXGui/gui-plugins/ScenarioManager/controller/ScenarioListController.h +++ b/source/ArmarXGui/gui-plugins/ScenarioManager/controller/ScenarioListController.h @@ -29,8 +29,10 @@ #include "../gui/scenariolistview.h" #include "../gui/createscenarioview.h" #include "../gui/filterabletreemodelsortfilterproxymodel.h" +#include <ArmarXCore/core/system/Synchronization.h> #include <ArmarXCore/core/IceManager.h> #include <ArmarXCore/core/IceGridAdmin.h> +#include <ArmarXCore/core/services/tasks/TaskUtil.h> #include <ArmarXCore/util/ScenarioManagerCommon/data_structure/Package.h> #include <ArmarXCore/util/ScenarioManagerCommon/executor/Executor.h> #include <ArmarXCore/util/ScenarioManagerCommon/data_structure/ApplicationInstance.h> @@ -43,6 +45,7 @@ namespace ScenarioManager { namespace Controller { + using ApplicationInstanceStatusMap = std::map<ApplicationInstancePtr, std::string>; /** * @class ScenarioListController * @ingroup controller @@ -76,6 +79,12 @@ namespace ScenarioManager */ FilterableTreeModelSortFilterProxyModelPtr getTreeModel(); + /** + * @brief fetches application stati over their designated strategy. + * This is potentially slow and should not be done in the GUI thread. + */ + void fetchStati(); + signals: /** * Gets emitted after changes have been made to the data structure. Other controllers should update their models. @@ -86,6 +95,7 @@ namespace ScenarioManager * Gets emitted after changes have been made to the States of the Applications. The DetailedApplicationView should update. */ void statusUpdated(); + void statusFetched(ApplicationInstanceStatusMap stati); /** * Gets emitted after an ApplicationInstance has been clicked. @@ -117,6 +127,8 @@ namespace ScenarioManager * Updates the statuses of all Applications and Scenarios. */ void updateStati(); + void updateStati(ApplicationInstanceStatusMap stati); + /** * Removes an item from the model. Can either be an ApplicationInstance or an Scenario @@ -139,6 +151,7 @@ namespace ScenarioManager */ void start(int row, int column, QModelIndex parent, ScenarioStartModes mode); void stop(int row, int column, QModelIndex parent); + void stopUpdateTask(); /** * Restarts the object in the specified location. @@ -185,6 +198,10 @@ namespace ScenarioManager ScenarioModel treemodel; FilterableTreeModelSortFilterProxyModelPtr model; Data_Structure::PackageVectorPtr packages; + // used for fetching application stati, list set before every update by gui thread + std::vector<ApplicationInstancePtr> applicationInstances; + armarx::Mutex applicationInstanceMutex; + armarx::SimplePeriodicTask<>::pointer_type updateTask; Exec::ExecutorPtr executor; IceGrid::AdminPrx iceAdmin; CreateScenarioView createScenarioView; diff --git a/source/ArmarXGui/gui-plugins/ScenarioManager/gui/detailedapplicationview.cpp b/source/ArmarXGui/gui-plugins/ScenarioManager/gui/detailedapplicationview.cpp index a04b16af3d0468732630736ea7b0d164f98e7910..5ac5478015ad2d6751e2adf898831e1c79a3bb49 100644 --- a/source/ArmarXGui/gui-plugins/ScenarioManager/gui/detailedapplicationview.cpp +++ b/source/ArmarXGui/gui-plugins/ScenarioManager/gui/detailedapplicationview.cpp @@ -288,7 +288,7 @@ void DetailedApplicationView::showApplicationInstance(ApplicationInstancePtr app } QtProperty* appIcePropertyTopItem = variantManager->addProperty(QtVariantPropertyManager::groupTypeId(), - QLatin1String("Ice Properties")); + QLatin1String("Ice Deployment Properties")); appInstanceTopItem->addSubProperty(appIcePropertyTopItem); QtVariantProperty* nodePropertyItem = variantManager->addProperty(QVariant::String, "Node Name"); @@ -440,7 +440,7 @@ void DetailedApplicationView::showScenario(ScenarioPtr scenario) } QtProperty* scenarioIcePropertyTopItem = variantManager->addProperty(QtVariantPropertyManager::groupTypeId(), - QLatin1String("Scenario Ice Properties")); + QLatin1String("Scenario Ice Deployment Properties")); scenarioTopItem->addSubProperty(scenarioIcePropertyTopItem); QtVariantProperty* scenarioDeploymentTypeItem = variantManager->addProperty(QtVariantPropertyManager::enumTypeId(), QString::fromStdString("Deployment Type")); @@ -448,6 +448,12 @@ void DetailedApplicationView::showScenario(ScenarioPtr scenario) scenarioDeploymentTypeItem->setToolTip("Describes if the Scenario should either use the Local build for Ice deployment or an Remote sync directory"); scenarioIcePropertyTopItem->addSubProperty(scenarioDeploymentTypeItem); + QtVariantProperty* nodePropertyItem = variantManager->addProperty(QVariant::String, "Node Name"); + nodePropertyItem->setValue(QString::fromStdString(scenario->getNodeName())); + nodePropertyItem->setToolTip("Describes on which Node the currently applications of the current scenario should be deployed on. Can be overwritten for each application."); + scenarioIcePropertyTopItem->addSubProperty(nodePropertyItem); + + QtProperty* scenarioIceEnvVarsTopItem = variantManager->addProperty(QtVariantPropertyManager::groupTypeId(), QLatin1String("Ice Enviroment Variables")); scenarioIcePropertyTopItem->addSubProperty(scenarioIceEnvVarsTopItem); @@ -553,6 +559,7 @@ void DetailedApplicationView::on_addParameterButton_clicked() void DetailedApplicationView::on_addIceEnvButton_clicked() { + ARMARX_INFO << "on_addIceEnvButton_clicked"; emit addIceEnvButtonClicked(); } @@ -670,6 +677,7 @@ void DetailedApplicationView::itemChanged(QtProperty* property, const QVariant& } else if (property->propertyName() == "Node Name") { + ARMARX_INFO << "Setting node name to " << property->valueText().toStdString(); lastAppInstance->setNodeName(property->valueText().toStdString()); updateTimer.start(UPDATE_TIMER_INTERVAL); } @@ -720,6 +728,10 @@ void DetailedApplicationView::itemChanged(QtProperty* property, const QVariant& updateTimer.start(UPDATE_TIMER_INTERVAL); } + else if (property->propertyName() == "Node Name") + { + lastScenario->setNodeName(property->valueText().toStdString()); + } else if (properties->getProperty(property->propertyName().toStdString()) != "" && properties->getProperty(property->propertyName().toStdString()).compare(value.toString().toStdString())) {