diff --git a/source/ArmarXGui/gui-plugins/SystemStateMonitorPlugin/ArmarXManagerItem.cpp b/source/ArmarXGui/gui-plugins/SystemStateMonitorPlugin/ArmarXManagerItem.cpp index 1e24d8a628b4831ef7db070bf22a222c7c8d47d2..6d1c9b2c152f1acd4616307a493ce560da8107e8 100644 --- a/source/ArmarXGui/gui-plugins/SystemStateMonitorPlugin/ArmarXManagerItem.cpp +++ b/source/ArmarXGui/gui-plugins/SystemStateMonitorPlugin/ArmarXManagerItem.cpp @@ -50,7 +50,7 @@ void ArmarXManagerItem::clear(bool clearProxy) { data.proxy = 0; } - + data.connection = nullptr; data.online = false; } @@ -72,6 +72,16 @@ ArmarXManagerInterfacePrx ArmarXManagerItem::getManagerProxy() const return data.proxy; } +Ice::ConnectionPtr ArmarXManagerItem::getConnection() const +{ + return data.connection; +} + +QString ArmarXManagerItem::getEndpointStr() const +{ + return data.endpointStr; +} + ArmarXManagerItem::ObjectMap& ArmarXManagerItem::getObjects() { @@ -112,6 +122,16 @@ void ArmarXManagerItem::setAppProperties(const ObjectPropertyInfos& properties) data.appProperties = properties; } +void ArmarXManagerItem::setConnection(Ice::ConnectionPtr connection) +{ + this->data.connection = connection; +} + +void ArmarXManagerItem::setEndpointStr(const QString& endpointStr) +{ + this->data.endpointStr = endpointStr; +} + const ObjectPropertyInfos& ArmarXManagerItem::getAppProperties() const { return data.appProperties; diff --git a/source/ArmarXGui/gui-plugins/SystemStateMonitorPlugin/ArmarXManagerItem.h b/source/ArmarXGui/gui-plugins/SystemStateMonitorPlugin/ArmarXManagerItem.h index 2107c02e8f9612eab760c2eb053091b9b81e13af..906ba6f34428e8c7fcacce9c07fc1374cec462c3 100644 --- a/source/ArmarXGui/gui-plugins/SystemStateMonitorPlugin/ArmarXManagerItem.h +++ b/source/ArmarXGui/gui-plugins/SystemStateMonitorPlugin/ArmarXManagerItem.h @@ -50,6 +50,8 @@ namespace armarx ArmarXManagerInterfacePrx proxy; ObjectMap objects; ObjectPropertyInfos appProperties; + Ice::ConnectionPtr connection; + QString endpointStr; }; using ManagerDataMap = std::map<QString, ManagerData>; @@ -60,12 +62,16 @@ namespace armarx QString getName() const; bool isOnline() const; ArmarXManagerInterfacePrx getManagerProxy() const; + Ice::ConnectionPtr getConnection() const; + QString getEndpointStr() const; ObjectMap& getObjects(); void setName(QString name); void setOnline(bool online); void setManagerProxy(ArmarXManagerInterfacePrx proxy); void setAppProperties(const ObjectPropertyInfos& properties); + void setConnection(Ice::ConnectionPtr connection); + void setEndpointStr(const QString& endpointStr); const ObjectPropertyInfos& getAppProperties() const; /** * Clears the item data. diff --git a/source/ArmarXGui/gui-plugins/SystemStateMonitorPlugin/ArmarXManagerModel.cpp b/source/ArmarXGui/gui-plugins/SystemStateMonitorPlugin/ArmarXManagerModel.cpp index 1e6c93a0a77d3d598e4bcd2888d1aad087294192..53747527fc9e06292aa5322d9ca8a866726be64a 100644 --- a/source/ArmarXGui/gui-plugins/SystemStateMonitorPlugin/ArmarXManagerModel.cpp +++ b/source/ArmarXGui/gui-plugins/SystemStateMonitorPlugin/ArmarXManagerModel.cpp @@ -27,8 +27,11 @@ #include <QFileSystemModel> #include <ArmarXGui/libraries/ArmarXGuiBase/QtUtil.h> #include <ArmarXCore/observers/variant/Variant.h> - +#include <ArmarXCore/core/util/algorithm.h> +#include <fstream> +#include <boost/algorithm/string/replace.hpp> #include <Ice/Connection.h> +#include <ArmarXGui/libraries/ArmarXGuiBase/ArmarXWidgetController.h> #include "ArmarXManagerModel.h" #include "ManagedIceObjectItem.h" @@ -131,20 +134,31 @@ ManagerPrxMap ArmarXManagerModel::getManagerProxyMap(const QStringList& managerN void ArmarXManagerModel::updateManagerDetails(const ArmarXManagerItem::ManagerDataMap& managerDataMap, bool deactivateIfMissing) { CHECK_QT_THREAD(this); + dependenciesMap.clear(); IceUtil::Time start = IceUtil::Time::now(); - std::set<std::string> offeredTopics; + std::map<std::string, std::vector<QString> > offererMap; std::map<std::string, std::vector<QString> > listenerMap; // iterate over all manager items for (int i = 0; i < this->rowCount(); i++) { ArmarXManagerItem* item = this->getItem(i); - - + // ARMARX_DEBUG << deactivateSpam(1, item->getName().toStdString()) << "Checking " << item->getName().toStdString(); + // ARMARX_INFO << "Checking " << item->getName().toStdString(); + // for (auto& element : item->getObjects()) + // { + // DependencyMap depMap = element.connectivity.dependencies; + // // ARMARX_INFO << "Checking sub item " << element.name.toStdString() << " with " << depMap.size() << " dependencies"; + // if (depMap.size() > 0) + // { + // dependenciesMap[toStdString()] = depMap; + // } + // } auto it = managerDataMap.find(item->getName()); if (it == managerDataMap.end()) { + ARMARX_INFO << deactivateSpam(1, item->getName().toStdString()) << "Didnt find " << item->getName().toStdString(); if (deactivateIfMissing) { item->setOnline(false); @@ -156,6 +170,10 @@ void ArmarXManagerModel::updateManagerDetails(const ArmarXManagerItem::ManagerD item->setOnline(it->second.online); } + item->setConnection(it->second.connection); + item->setEndpointStr(it->second.endpointStr); + // ARMARX_DEBUG << deactivateSpam(1, item->getName().toStdString()) << "endpoint: " << it->second.endpointStr; + if (!item->getManagerProxy() && !it->second.proxy) { ARMARX_INFO << "Proxy for " << item->getName().toStdString() << " is null"; @@ -167,12 +185,6 @@ void ArmarXManagerModel::updateManagerDetails(const ArmarXManagerItem::ManagerD item->setManagerProxy(it->second.proxy); } item->setAppProperties(it->second.appProperties); - Ice::EndpointSeq endpoints = item->getManagerProxy()->ice_getEndpoints(); - ARMARX_IMPORTANT << item->getManagerProxy()->ice_getAdapterId(); - for (Ice::EndpointPtr endpoint : endpoints) - { - ARMARX_IMPORTANT << endpoint->toString(); - } const ArmarXManagerItem::ObjectMap& updates = it->second.objects; ArmarXManagerItem::ObjectMap& objects = item->getObjects(); @@ -188,16 +200,20 @@ void ArmarXManagerModel::updateManagerDetails(const ArmarXManagerItem::ManagerD for (const auto& topic : objItem.connectivity.offeredTopics) { offererMap[topic].push_back(objName); - offeredTopics.insert(topic); } for (const auto& topic : objItem.connectivity.usedTopics) { listenerMap[topic].push_back(objName); } + if (objItem.connectivity.dependencies.size() > 0) + { + dependenciesMap[objName.toStdString()] = objItem.connectivity.dependencies; + } } } - + // std::set<std::string> offeredTopics = armarx::getMapKeys(offererMap); + // ARMARX_INFO << deactivateSpam(10) << VAROUT(listenerMap) << "\n" << VAROUT(offererMap); // iterate over all manager items for (int i = 0; i < this->rowCount(); i++) { @@ -248,22 +264,6 @@ void ArmarXManagerModel::updateManagerDetails(const ArmarXManagerItem::ManagerD if (item->rowCount() == 0 && item->isOnline()) // only when app is coming (back) online { - ArmarXManagerInterfacePrx prx = item->getManagerProxy(); - try - { - Ice::ConnectionPtr connection = prx->ice_collocationOptimized(false)->ice_getConnection(); - QStandardItem* endpointItem = new QStandardItem(QString::fromStdString("Endpoint: " + connection->getEndpoint()->toString())); - endpointItem->setEditable(false); - endpointItem->setData((int)ApplicationRowType::Endpoint, (int)UserDataRoles::RowType); - item->appendRow(endpointItem); - } - catch (const IceUtil::Exception& ex) - { - QStandardItem* endpointItem = new QStandardItem(QString::fromStdString("Endpoint: ? (" + std::string(ex.ice_id()) + ")")); - endpointItem->setEditable(false); - item->appendRow(endpointItem); - } - auto applicationItem = new QStandardItem("Application Properties"); applicationItem->setData((int)ApplicationRowType::ApplicationProperties, (int)UserDataRoles::RowType); applicationItem->setEditable(false); @@ -298,68 +298,6 @@ void ArmarXManagerModel::updateManagerDetails(const ArmarXManagerItem::ManagerD addPropertiesToItem(properties, objItem.item); - if (objItem.connectivity.offeredTopics.size() > 0) - { - QStandardItem* offeredTopicsItem = new QStandardItem("Offered Topics"); - offeredTopicsItem->setEditable(false); - - QList<QStandardItem*> objectPropertiesRow; - - for (const auto& topic : objItem.connectivity.offeredTopics) - { - QStandardItem* offeredTopicItem = new QStandardItem(QString::fromStdString(topic)); - offeredTopicItem->setEditable(false); - - auto& listeners = listenerMap[topic]; - for (auto& listener : listeners) - { - QStandardItem* listenerItem = new QStandardItem(("Listener: " + listener)); - listenerItem->setEditable(false); - offeredTopicItem->appendRow(listenerItem); - } - - objectPropertiesRow.append(offeredTopicItem); - - } - - offeredTopicsItem->appendRows(objectPropertiesRow); - objItem.item->appendRow(offeredTopicsItem); - } - - if (objItem.connectivity.usedTopics.size() > 0) - { - QStandardItem* topicsItem = new QStandardItem("Used Topics"); - topicsItem->setEditable(false); - - QList<QStandardItem*> objectPropertiesRow; - - for (const auto& topic : objItem.connectivity.usedTopics) - { - QStandardItem* topicItem = new QStandardItem(QString::fromStdString(topic)); - if (offeredTopics.count(topic) == 0) - { - topicItem->setBackground(QBrush(QColor(255, 163, 33))); - topicItem->setToolTip("This topic not offered by any listed component - though not all components might be listed"); - } - else - { - auto& offerers = offererMap[topic]; - for (auto& offerer : offerers) - { - QStandardItem* offererItem = new QStandardItem(("Offerer: " + offerer)); - offererItem->setEditable(false); - topicItem->appendRow(offererItem); - } - - } - topicItem->setEditable(false); - objectPropertiesRow.append(topicItem); - } - - topicsItem->appendRows(objectPropertiesRow); - objItem.item->appendRow(topicsItem); - } - QStandardItem* metaInfoItem = new QStandardItem(LiveMetaInfoDescriptionString); metaInfoItem->setEditable(false); for (auto& pair : objItem.metaInfoMap) @@ -384,11 +322,13 @@ void ArmarXManagerModel::updateManagerDetails(const ArmarXManagerItem::ManagerD { depObjItem->setData(true, (int)UserDataRoles::ResolvedDependency); depObjItem->setBackground(QBrush(QColor(50, 205, 50))); + depObjItem->setToolTip("Dependency resolved"); } else { depObjItem->setData(false, (int)UserDataRoles::ResolvedDependency); depObjItem->setBackground(QBrush(QColor(255, 106, 106))); + depObjItem->setToolTip("Dependency missing"); } objItem.item->appendRow(depObjItem); @@ -398,6 +338,21 @@ void ArmarXManagerModel::updateManagerDetails(const ArmarXManagerItem::ManagerD } else { + + auto endpointItem = findItemByUserData(static_cast<Qt::ItemDataRole>(UserDataRoles::RowType), (int)ApplicationRowType::Endpoint, item); + auto endpointText = "Endpoint: " + item->getEndpointStr(); + if (!endpointItem) + { + endpointItem = new QStandardItem(endpointText); + endpointItem->setEditable(false); + endpointItem->setData((int)ApplicationRowType::Endpoint, (int)UserDataRoles::RowType); + item->appendRow(endpointItem); + } + else + { + endpointItem->setText(endpointText); + } + DependencyMap depMap = objItem.connectivity.dependencies; DependencyMap::iterator it = depMap.begin(); @@ -415,11 +370,13 @@ void ArmarXManagerModel::updateManagerDetails(const ArmarXManagerItem::ManagerD { depObjItem->setData(true, (int)UserDataRoles::ResolvedDependency); depObjItem->setBackground(QBrush(QColor(50, 205, 50))); + depObjItem->setToolTip("Dependency resolved"); } else { depObjItem->setData(false, (int)UserDataRoles::ResolvedDependency); depObjItem->setBackground(QBrush(QColor(255, 106, 106))); + depObjItem->setToolTip("Dependency missing"); } } @@ -427,6 +384,84 @@ void ArmarXManagerModel::updateManagerDetails(const ArmarXManagerItem::ManagerD ++it; } + if (objItem.connectivity.offeredTopics.size() > 0) + { + auto topicsItem = findItem(QString("Offered Topics"), objItem.item); + if (!topicsItem) + { + topicsItem = new QStandardItem(QString::fromStdString("Offered Topics")); + topicsItem->setEditable(false); + objItem.item->appendRow(topicsItem); + } + + for (const auto& topic : objItem.connectivity.offeredTopics) + { + auto topicItem = findItem(QString::fromStdString(topic), topicsItem); + if (!topicItem) + { + topicItem = new QStandardItem(QString::fromStdString(topic)); + topicItem->setEditable(false); + topicsItem->appendRow(topicItem); + } + auto& listeners = listenerMap[topic]; + syncStringListChildren(topicItem, listeners); + // topicItem->removeRows(0, topicItem->rowCount()); + // for (auto& listener : listeners) + // { + // QStandardItem* listenerItem = new QStandardItem(("Listener: " + listener)); + // listenerItem->setEditable(false); + // topicItem->appendRow(listenerItem); + // } + + } + } + + if (objItem.connectivity.usedTopics.size() > 0) + { + auto topicsItem = findItem(QString("Used Topics"), objItem.item); + if (!topicsItem) + { + topicsItem = new QStandardItem(QString::fromStdString("Used Topics")); + topicsItem->setEditable(false); + objItem.item->appendRow(topicsItem); + } + if (topicsItem) + { + // QList<QStandardItem*> objectPropertiesRow; + + for (const auto& topic : objItem.connectivity.usedTopics) + { + auto topicItem = findItem(QString::fromStdString(topic), topicsItem); + if (!topicItem) + { + topicItem = new QStandardItem(QString::fromStdString(topic)); + topicItem->setEditable(false); + topicsItem->appendRow(topicItem); + } + if (offererMap.count(topic) == 0) + { + topicItem->setBackground(QBrush(QColor(255, 163, 33))); + topicItem->setToolTip("The topic " + QString::fromStdString(topic) + " is not offered by any listed component - though not all components might be listed"); + } + else + { + topicItem->setBackground(QBrush()); + auto& offerers = offererMap[topic]; + syncStringListChildren(topicItem, offerers); + // topicItem->removeRows(0, topicItem->rowCount()); + // for (auto& offerer : offerers) + // { + // QStandardItem* offererItem = new QStandardItem(("Offerer: " + offerer)); + // offererItem->setEditable(false); + // topicItem->appendRow(offererItem); + // } + + } + topicItem->setEditable(false); + // objectPropertiesRow.append(topicItem); + } + } + } // update meta infos auto metaInfoItem = findItem(QString(LiveMetaInfoDescriptionString), objItem.item); @@ -443,9 +478,6 @@ void ArmarXManagerModel::updateManagerDetails(const ArmarXManagerItem::ManagerD } } - - - objItem.item->setBackground(getBrush(objItem.state)); auto stateBool = objItem.state == eManagedIceObjectStarted; // ARMARX_INFO << "Setting objItem: " << objItem.name.toStdString() << " with shown name " << objItem.item->text().toStdString() << " to " << stateBool; @@ -456,6 +488,10 @@ void ArmarXManagerModel::updateManagerDetails(const ArmarXManagerItem::ManagerD } ARMARX_DEBUG_S << "Updating SystemState model took " << (IceUtil::Time::now() - start).toMilliSecondsDouble() << " ms"; + + std::string dotString = GenerateDependencyGraph(dependenciesMap); + std::ofstream f("/tmp/dependencygraph.dot"); + f << dotString; } void ArmarXManagerModel::upsertManagerDetails(const ArmarXManagerItem::ManagerData& data) @@ -729,3 +765,60 @@ QStandardItem* ArmarXManagerModel::findItem(const QString& name, QStandardItem* return NULL; } +QStandardItem* ArmarXManagerModel::findItemByUserData(Qt::ItemDataRole role, const QVariant& data, QStandardItem* item) +{ + for (int i = 0; i < item->rowCount(); ++i) + { + QStandardItem* curItem = item->child(i); + if (curItem->data(role) == data) + { + return curItem; + } + } + return NULL; +} + +void ArmarXManagerModel::syncStringListChildren(QStandardItem* item, const std::vector<QString>& strings) +{ + for (int i = item->rowCount() - 1; i >= 0; i--) + { + QStandardItem* curItem = item->child(i); + if (std::find(strings.begin(), strings.end(), curItem->text()) == strings.end()) + { + item->removeRow(i); + } + } + for (auto s : strings) + { + auto child = findItem(s, item); + if (!child) + { + auto newChild = new QStandardItem(s); + newChild->setEditable(false); + item->appendRow(newChild); + } + } +} + +std::string ArmarXManagerModel::GenerateDependencyGraph(const std::map<std::string, DependencyMap>& dependenciesMap) +{ + std::stringstream ss; + ss << "digraph ArmarXDependencyGraph\n" + "{"; + for (auto& pair : dependenciesMap) + { + auto name = pair.first; + for (auto& pair2 : pair.second) + { + auto name2 = pair2.first; + boost::replace_all(name, "-", "_"); + boost::replace_all(name2, "-", "_"); + boost::replace_all(name, ">", "_"); + boost::replace_all(name2, ">", "_"); + ss << name << " -> " << name2 << ";\n"; + } + } + ss << "\n}"; + return ss.str(); +} + diff --git a/source/ArmarXGui/gui-plugins/SystemStateMonitorPlugin/ArmarXManagerModel.h b/source/ArmarXGui/gui-plugins/SystemStateMonitorPlugin/ArmarXManagerModel.h index b3bbd089e076eabe9e0c0f56607234abf9741da3..d10caf77f55c1ab39cb917874d635320cf3472ce 100644 --- a/source/ArmarXGui/gui-plugins/SystemStateMonitorPlugin/ArmarXManagerModel.h +++ b/source/ArmarXGui/gui-plugins/SystemStateMonitorPlugin/ArmarXManagerModel.h @@ -206,7 +206,10 @@ namespace armarx QBrush getBrush(armarx::ManagedIceObjectState state); QStandardItem* findItem(const QString& name, QStandardItem* item); + QStandardItem* findItemByUserData(Qt::ItemDataRole role, const QVariant& data, QStandardItem* item); + void syncStringListChildren(QStandardItem* item, const std::vector<QString>& strings); + static std::string GenerateDependencyGraph(const std::map<std::string, DependencyMap>& dependenciesMap); private: /** * Modification access mutex @@ -214,6 +217,7 @@ namespace armarx Mutex mutex; IceManagerPtr iceManager; + std::map<std::string, DependencyMap> dependenciesMap; }; diff --git a/source/ArmarXGui/gui-plugins/SystemStateMonitorPlugin/SystemStateMonitorWidget.cpp b/source/ArmarXGui/gui-plugins/SystemStateMonitorPlugin/SystemStateMonitorWidget.cpp index b236b465415981d6b0a51a7b8137cf828f6b17fb..72e7b57cd4e55791882b6fc3301d0dfc20674aa8 100644 --- a/source/ArmarXGui/gui-plugins/SystemStateMonitorPlugin/SystemStateMonitorWidget.cpp +++ b/source/ArmarXGui/gui-plugins/SystemStateMonitorPlugin/SystemStateMonitorWidget.cpp @@ -267,13 +267,26 @@ void SystemStateMonitorWidget::updateManagerStates(const ArmarXManagerItem::Man bool SystemStateMonitorWidget::retrieveManagerData(ArmarXManagerInterfacePrx prx, ArmarXManagerItem::ManagerData& managerData) { + CHECK_NOT_QT_THREAD(getWidget()); bool result = false; try { managerData.proxy = prx; + prx = prx->ice_timeout(1000); managerData.name = QString::fromStdString(prx->ice_getIdentity().name); - result &= retrieveManagerObjectsState(prx, managerData.objects); managerData.appProperties = prx->getApplicationPropertyInfos(); + result &= retrieveManagerObjectsState(prx, managerData.objects); + try + { + managerData.connection = prx->ice_collocationOptimized(false)->ice_getConnection(); + managerData.endpointStr = managerData.connection ? QString::fromStdString(managerData.connection->getEndpoint()->toString()) : "Endpoint: no connection data"; + } + + catch (const IceUtil::Exception& ex) + { + // ARMARX_INFO << deactivateSpam(5, managerData.name.toStdString()) << "Failed to get connection info for " << managerData.name.toStdString(); + managerData.endpointStr = QString::fromStdString("? (" + std::string(ex.ice_id()) + ")"); + } managerData.online = true; } catch (...) @@ -286,6 +299,7 @@ bool SystemStateMonitorWidget::retrieveManagerData(ArmarXManagerInterfacePrx prx bool SystemStateMonitorWidget::retrieveManagerObjectsState(ArmarXManagerInterfacePrx prx, ArmarXManagerItem::ObjectMap& objectStates) { + CHECK_NOT_QT_THREAD(getWidget()); // get proxy if not set // update existence state try @@ -346,6 +360,7 @@ void SystemStateMonitorWidget::updateManagerObjectsState() { managerDataMap[it->first].appProperties = it->second->getApplicationPropertyInfos(); } + retrieveManagerData(it->second, managerDataMap[it->first]); } ARMARX_DEBUG << "update duration: " << (IceUtil::Time::now() - start).toMilliSecondsDouble(); } diff --git a/source/ArmarXGui/gui-plugins/SystemStateMonitorPlugin/SystemStateMonitorWidget.h b/source/ArmarXGui/gui-plugins/SystemStateMonitorPlugin/SystemStateMonitorWidget.h index cf6851920ca3cfcb3b89ebcc19e81c983e463e77..2f6ac690590924b13d82c2939b2ceebc8a9c65e5 100644 --- a/source/ArmarXGui/gui-plugins/SystemStateMonitorPlugin/SystemStateMonitorWidget.h +++ b/source/ArmarXGui/gui-plugins/SystemStateMonitorPlugin/SystemStateMonitorWidget.h @@ -236,7 +236,7 @@ namespace armarx // ARMARX_INFO << "Checking entry: " << index0.data().toString() << " val: " << variant.toBool() << " param: " << hideResolvedComponents; if (variant.toBool()) { - ARMARX_INFO << "Hiding entry: " << index0.data().toString(); + ARMARX_VERBOSE << "Hiding entry: " << index0.data().toString(); return false; } }