SystemStateMonitorWidget.cpp
Go to the documentation of this file.
1/*
2 * This file is part of ArmarX.
3 *
4 * Copyright (C) 2011-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
5 *
6 * ArmarX is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * ArmarX is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * @package ArmarX::Gui
19 * @author Jan Issac ( jan.issac at gmail dot com)
20 * @date 2012
21 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22 * GNU General Public License
23 */
24
26
27#include <string>
28#include <vector>
29
30#include <QApplication>
31#include <QLineEdit>
32#include <QStyledItemDelegate>
33#include <QVector>
34
37#include <ArmarXCore/interface/core/ArmarXManagerInterface.h>
38
39#include <ArmarXGui/gui-plugins/SystemStateMonitorPlugin/ui_ArmarXManagerRepositoryDialog.h>
42
43namespace armarx
44{
45 class PropertyEditingDelegate : public QStyledItemDelegate
46 {
47 public:
48 PropertyEditingDelegate(armarx::ManagerPrxMap* managerPrxMap) : managerPrxMap(managerPrxMap)
49 {
50 }
51
52 // QAbstractItemDelegate interface
53 QWidget*
54 createEditor(QWidget* parent,
55 const QStyleOptionViewItem& option,
56 const QModelIndex& index) const override
57 {
58 return new QLineEdit(parent);
59 }
60
61 void
62 setEditorData(QWidget* editor, const QModelIndex& index) const override
63 {
64 QLineEdit* lineEdit = qobject_cast<QLineEdit*>(editor);
65 if (lineEdit)
66 {
67 QString propValue = index.data().toString();
68 propValue.remove(0, propValue.indexOf(":") + 2);
69 QString propName = index.data().toString();
70
71 propName.truncate(propName.indexOf(":") - 1);
72 lineEdit->setText(propValue);
73 lineEdit->setProperty("propertyName", propName);
74 }
75 }
76
77 void
78 setModelData(QWidget* editor,
79 QAbstractItemModel* model,
80 const QModelIndex& index) const override
81 {
82 QLineEdit* lineEdit = qobject_cast<QLineEdit*>(editor);
83 if (lineEdit)
84 {
85 model->setData(index,
86 lineEdit->property("propertyName").toString() + " : " +
87 lineEdit->text());
88 auto it = managerPrxMap->find(index.parent().parent().parent().data().toString());
89 if (it != managerPrxMap->end())
90 {
91 armarx::ArmarXManagerInterfacePrx prx = it->second;
92 prx->getPropertiesAdmin()->ice_collocationOptimized(false)->setProperties(
93 {{lineEdit->property("propertyName").toString().toStdString(),
94 lineEdit->text().toStdString()}});
95 }
96 }
97 }
98
99 private:
100 armarx::ManagerPrxMap* managerPrxMap;
101 };
102
104 {
105 setupModel();
106 setupView();
107 qRegisterMetaType<StateUpdateMap>("StateUpdateMap");
108 qRegisterMetaType<ArmarXManagerItem::ManagerDataMap>("ArmarXManagerItem::ManagerDataMap");
109 qRegisterMetaType<ArmarXManagerItem::ManagerData>("ArmarXManagerItem::ManagerData");
110 qRegisterMetaType<ManagerPrxMap>("ManagerPrxMap");
111
112
113 filterExpansionTimer.setSingleShot(true);
114 connect(&filterExpansionTimer, SIGNAL(timeout()), this, SLOT(delayedFilterExpansion()));
115 connect(ui.btnProblematicOnly,
116 SIGNAL(toggled(bool)),
117 this,
118 SLOT(on_btnProblematicOnly_toggled(bool)),
119 Qt::UniqueConnection);
120
121 fillLegendLayout(ui.colorLegendLayout, *monitoredManagerModel);
122 }
123
125 {
126 // stateUpdateTimer->stop();
127 if (stateUpdateTask)
128 {
129 stateUpdateTask->stop();
130 }
131
132 delete managerRepositoryModel;
133 delete monitoredManagerModel;
134 // delete stateUpdateTimer;
135 }
136
137 void
139 {
140 managerRepositoryModel = new ArmarXManagerModel();
141 monitoredManagerModel = new ArmarXManagerModel();
142 }
143
144 void
146 {
147 ui.setupUi(getWidget());
148
149 managerRepositoryDialog = new ArmarXManagerRepositoryDialog(
150 managerRepositoryModel, monitoredManagerModel, getWidget());
151 managerRepositoryDialog->setModal(true);
152 connect(managerRepositoryDialog, SIGNAL(accepted()), this, SLOT(acceptConfig()));
153 connect(managerRepositoryDialog,
154 SIGNAL(requestedManagerScan()),
155 this,
156 SLOT(retrieveOnlineManagers()));
157 ui.monitoredManagersTree->setItemDelegate(
158 new PropertyEditingDelegate(&currentManagerPrxMap));
159 filterModel = new InfixFilterModel(this);
160 filterModel->addCustomFilter(
161 [this](QAbstractItemModel* model, int source_row, const QModelIndex& source_parent)
162 {
163 QModelIndex index0 = model->index(source_row, 0, source_parent);
164 if (this->ui.btnProblematicOnly->isChecked())
165 {
166 auto variant =
168 auto variantDependency =
170 if (variant.isValid())
171 {
172 // ARMARX_INFO << "Checking entry: " << index0.data().toString() << " val: " << variant.toBool() << " param: " << hideResolvedComponents;
173 if (variant.toBool())
174 {
175 // ARMARX_INFO << "Resolve: Hiding " << index0.data().toString();
176 return false;
177 }
178 }
179 if (variantDependency.isValid())
180 {
181 if (variantDependency.toBool())
182 {
183 return false;
184 }
185 }
186 if (!variant.isValid() && !variantDependency.isValid())
187 {
188 return false;
189 }
190 // ARMARX_INFO << "Showing entry: " << index0.data().toString() << " state: " <<
191 // (variantDependency.isValid() ? std::to_string(variantDependency.toBool()) : "none")
192 // << " - " << (variant.isValid() ? std::to_string(variant.toBool()) : "none");
193 }
194
195 return true;
196 });
197 filterModel->setSourceModel(monitoredManagerModel);
198 filterModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
199 ui.monitoredManagersTree->setModel(filterModel);
200
201 connect(ui.lineEditFilter,
202 SIGNAL(textChanged(QString)),
203 filterModel,
204 SLOT(setFilterFixedString(QString)));
205 connect(ui.lineEditFilter,
206 SIGNAL(textChanged(QString)),
207 this,
208 SLOT(expandFilterSelection(QString)),
209 Qt::QueuedConnection);
210
211 connect(ui.configureButton, SIGNAL(clicked()), this, SLOT(openManagerRepositoryDialog()));
212
213 connect(this,
215 this,
217
218 // stateUpdateTimer->start();
219 }
220
221 void
223 {
224 managerRepositoryModel->populate(settings->value("ManagerRepository").toStringList());
225
226 monitoredManagerModel->populate(settings->value("MonitoredManagers").toStringList());
227 ui.monitoredManagersTree->expandToDepth(1);
228 }
229
230 void
232 {
233 settings->setValue("ManagerRepository", managerRepositoryModel->toStringList());
234
235 settings->setValue("MonitoredManagers", monitoredManagerModel->toStringList());
236 }
237
238 void
240 {
241 monitoredManagerModel->setIceManager(getIceManager());
242 managerRepositoryModel->setIceManager(getIceManager());
243 }
244
245 void
247 {
248 stateUpdateTask = new PeriodicTask<SystemStateMonitorWidget>(
249 this,
251 500,
252 false,
253 "SystemStateMonitorUpdate");
254 stateUpdateTask->setDelayWarningTolerance(5000);
255 stateUpdateTask->start();
256 if (monitoredManagerModel->empty()) // only if fresh connect without preconfig
257 {
258 prefillView();
259 }
260 else
261 {
262 std::unique_lock lock(managerPrxMapMutex);
263 currentManagerPrxMap = monitoredManagerModel->getManagerProxyMap();
264 }
265 }
266
267 void
269 {
270 if (stateUpdateTask)
271 {
272 stateUpdateTask->stop();
273 }
274 }
275
276 void
278 {
279 if (stateUpdateTask)
280 {
281 stateUpdateTask->stop();
282 }
283 }
284
285 void
287 const ArmarXManagerItem::ManagerDataMap& managerData)
288 {
290
291 std::unique_lock lock(monitoredManagerModel->getMutex());
292
293 monitoredManagerModel->updateManagerDetails(managerData);
294 filterModel->invalidate();
295 }
296
297 bool
300 {
302 bool result = false;
303 try
304 {
305 managerData.proxy = prx;
306 prx = prx->ice_timeout(1000);
307 managerData.name = QString::fromStdString(prx->ice_getIdentity().name);
308 managerData.appProperties = prx->getApplicationPropertyInfos();
309 result &= retrieveManagerObjectsState(prx, managerData.objects);
310 try
311 {
312 managerData.connection = prx->ice_collocationOptimized(false)->ice_getConnection();
313 managerData.endpointStr =
314 managerData.connection
315 ? QString::fromStdString(managerData.connection->getEndpoint()->toString())
316 : "Endpoint: no connection data";
317 }
318
319 catch (const IceUtil::Exception& ex)
320 {
321 // ARMARX_INFO << deactivateSpam(5, managerData.name.toStdString()) << "Failed to get connection info for " << managerData.name.toStdString();
322 managerData.endpointStr =
323 QString::fromStdString("? (" + std::string(ex.ice_id()) + ")");
324 }
325 managerData.online = true;
326 }
327 catch (...)
328 {
329 managerData.online = false;
330 result = false;
331 }
332 return result;
333 }
334
335 bool
337 ArmarXManagerInterfacePrx prx,
338 ArmarXManagerItem::ObjectMap& objectStates)
339 {
341 // get proxy if not set
342 // update existence state
343 try
344 {
345 prx->ice_timeout(200)->ice_ping();
346 // item->setOnline(true);
347 }
348 catch (...)
349 {
350 return false;
351 }
352
353 // actual retrieval
354 Ice::StringSeq objectNames = prx->getManagedObjectNames();
355
356 for (auto& objectName : objectNames)
357 {
358 ManagedIceObjectItem objEntry;
359 objEntry.name = objectName.c_str();
360 objEntry.state = prx->getObjectState(objectName);
361 objEntry.connectivity = prx->getObjectConnectivity(objectName);
362 objEntry.properties = prx->getObjectPropertyInfos(objectName);
363 try
364 {
365 objEntry.metaInfoMap = prx->getMetaInfo(objectName);
366 }
367 catch (...)
368 {
369 ARMARX_INFO << deactivateSpam(1000, objectName) << "Failed to get meta info for "
370 << objectName;
371 }
372 objectStates[objEntry.name] = (objEntry);
373 }
374
375 return true;
376 }
377
378 void
380 {
381
382 // std::unique_lock lock(monitoredManagerModel->getMutex());
383 // StateUpdateMap stateMap;
385 {
386 decltype(currentManagerPrxMap) proxies;
387 {
388 std::unique_lock lock(managerPrxMapMutex);
389 proxies = currentManagerPrxMap;
390 }
391 IceUtil::Time start = IceUtil::Time::now();
392 for (auto it = proxies.begin(); it != proxies.end(); it++)
393 {
395 bool online = retrieveManagerObjectsState(it->second, stateMap);
396 managerDataMap[it->first].online = online;
397 managerDataMap[it->first].name = it->first;
398 managerDataMap[it->first].objects = stateMap;
399 if (online)
400 {
401 managerDataMap[it->first].appProperties =
402 it->second->getApplicationPropertyInfos();
403 }
404 retrieveManagerData(it->second, managerDataMap[it->first]);
405 }
406 ARMARX_DEBUG << "update duration: "
407 << (IceUtil::Time::now() - start).toMilliSecondsDouble();
408 }
409
410 emit updateManagerStatesSignal(managerDataMap);
411 }
412
413 void
415 {
416 this->managerRepositoryModel->copyFrom(
417 managerRepositoryDialog->getManagerRepositoryModel());
418
419 this->monitoredManagerModel->copyFrom(managerRepositoryDialog->getMonitoredManagersModel());
420 ui.monitoredManagersTree->expandToDepth(1);
421 std::unique_lock lock(managerPrxMapMutex);
422 currentManagerPrxMap = monitoredManagerModel->getManagerProxyMap();
423 }
424
425 QStringList
426 SystemStateMonitorWidget::fetchOnlineManagers()
427 {
429 auto admin = getIceManager()->getIceGridSession()->getAdmin();
430 ARMARX_INFO << "Getting managers";
431 IceGrid::ObjectInfoSeq objects = admin->getAllObjectInfos("*Manager");
432 ARMARX_INFO << "Got new managers";
433
434 IceGrid::ObjectInfoSeq result;
435
436 for(const auto& objectInfo : objects)
437 {
438 Ice::ObjectPrx current = objectInfo.proxy;
439
440 ArmarXManagerInterfacePrx object;
441
442 bool isProxySane = false;
443 // if objects are hanging we might get connection refused
444 try
445 {
446 ARMARX_INFO << "Trying to ping proxy";
447
448 const std::string proxyName = current->ice_getIdentity().name;
449
450 ARMARX_INFO << VAROUT(proxyName);
451 object = ArmarXManagerInterfacePrx::checkedCast(current->ice_timeout(60));
452 ARMARX_INFO << "Ping received from " << VAROUT(proxyName);
453
454 isProxySane = true;
455 }
456 catch (...)
457 {
459 isProxySane = false;
460 }
461
462 if (not isProxySane)
463 {
464 try
465 {
466 ARMARX_INFO << "Removing dead object";
467
468 const auto identity = current->ice_getIdentity();
469 const std::string proxyName = identity.name;
470
471 ARMARX_INFO << VAROUT(proxyName);
472 // remove dead objects
473 admin->removeObject(identity);
474 ARMARX_INFO << "Removed dead object " << QUOTED(proxyName);
475 }
476 catch (...)
477 {
479 }
480 }
481
482
483 qApp->processEvents();
484
485 if (not isProxySane)
486 {
487 continue;
488 }
489
490 if (object)
491 {
492 result.push_back(objectInfo);
493 }
494
495 }
496 ARMARX_INFO << "Iterated through online managers";
498
499 QStringList managers;
500 for (const IceGrid::ObjectInfo& info : result)
501 {
502 managers.append(info.proxy->ice_getIdentity().name.c_str());
503 }
504
505 return managers;
506 }
507
508 void
510 {
511 managerRepositoryDialog->addOnlineManagers(fetchOnlineManagers());
512 }
513
514 void
516 {
517 managerRepositoryDialog->getManagerRepositoryModel()->copyFrom(managerRepositoryModel);
518
519 managerRepositoryDialog->getMonitoredManagersModel()->copyFrom(monitoredManagerModel);
520
522
523 managerRepositoryDialog->show();
524 }
525
526 void
527 SystemStateMonitorWidget::prefillView()
528 {
529 managerRepositoryModel->clear();
530 monitoredManagerModel->clear();
531
532 QStringList managers = fetchOnlineManagers();
533 // enableMainWidgetAsync(false);
534 // ARMARX_INFO << "Got managers";
535 // QMetaObject::invokeMethod(this, "addArmarXManagers", Q_ARG(QStringList, managers));
536 addArmarXManagers(managers);
537 QMetaObject::invokeMethod(ui.monitoredManagersTree, "expandToDepth", Q_ARG(int, 0));
538 std::unique_lock lock(managerPrxMapMutex);
539 currentManagerPrxMap = monitoredManagerModel->getManagerProxyMap(managers);
540 }
541
542 void
543 SystemStateMonitorWidget::addArmarXManagerEntries(ManagerPrxMap managers)
544 {
546
547 ARMARX_INFO << "Adding managers";
548 for (auto& pair : managers)
549 {
550 ArmarXManagerItem* item = new ArmarXManagerItem(pair.first);
551 item->setManagerProxy(pair.second);
552 monitoredManagerModel->appendRow(item);
553 }
554 ARMARX_INFO << "epanding managers";
555 ui.monitoredManagersTree->expandToDepth(1);
556 }
557
558 void
560 {
561 // ARMARX_IMPORTANT << this->rowCount();
562 for (auto& name : managerNames)
563 {
564 try
565 {
567 data.name = name;
568 ARMARX_DEBUG << name.toStdString();
569 auto proxy =
570 getIceManager()->getProxy<ArmarXManagerInterfacePrx>(name.toStdString());
572 QMetaObject::invokeMethod(monitoredManagerModel,
573 "upsertManagerDetails",
575 ARMARX_DEBUG << name.toStdString() << " done";
576 }
577 catch (...)
578 {
580 }
581 }
582 }
583
584 void
585 SystemStateMonitorWidget::expandFilterSelection(QString filterStr)
586 {
587 ARMARX_DEBUG_S << VAROUT(filterStr);
588 if (filterStr.length() == 0)
589 {
590 ui.monitoredManagersTree->collapseAll();
591 // ui.monitoredManagersTree->expandToDepth(1);
592 }
593 else
594 {
595 filterExpansionTimer.start(500);
596 }
597 }
598
599 void
600 SystemStateMonitorWidget::delayedFilterExpansion()
601 {
603
604 InfixFilterModel::ExpandFilterResults(ui.monitoredManagersTree);
605 }
606
607 void
608 armarx::SystemStateMonitorWidget::on_btnProblematicOnly_toggled(bool checked)
609 {
610 CHECK_QT_THREAD(getWidget());
611
612 // filterModel->setHideResolvedComponents(checked);
613 filterModel->invalidate();
614 InfixFilterModel::ExpandFilterResults(ui.monitoredManagersTree);
615 }
616
617 void
618 SystemStateMonitorWidget::fillLegendLayout(QHBoxLayout* layout, ArmarXManagerModel& model) const
619 {
620 auto addLegendEntry = [layout, &model](ManagedIceObjectState state, const QString& text)
621 {
622 QLabel* label = new QLabel(text);
623 {
624 QBrush brush = model.getBrush(state);
625 QPalette p = label->palette();
626 p.setColor(label->backgroundRole(), brush.color());
627 label->setPalette(p);
628 label->setAutoFillBackground(true);
629 }
630 {
631 QFont font = label->font();
632 font.setPointSize(10);
633 label->setFont(font);
634 }
635 layout->addWidget(label);
636 };
637
638 addLegendEntry(armarx::eManagedIceObjectCreated, "Created");
639 addLegendEntry(armarx::eManagedIceObjectInitializing, "Initializing");
640 addLegendEntry(armarx::eManagedIceObjectInitialized, "Initialized");
641 addLegendEntry(armarx::eManagedIceObjectInitializationFailed, "Initialization Failed");
642 addLegendEntry(armarx::eManagedIceObjectStarting, "Connecting");
643 addLegendEntry(armarx::eManagedIceObjectStarted, "Connected");
644 addLegendEntry(armarx::eManagedIceObjectStartingFailed, "Connecting Failed");
645 addLegendEntry(armarx::eManagedIceObjectExiting, "Exiting");
646 addLegendEntry(armarx::eManagedIceObjectExited, "Exited");
647 }
648
649 bool
654
655 void
660} // namespace armarx
uint8_t index
#define option(type, fn)
SpamFilterDataPtr deactivateSpam(SpamFilterDataPtr const &spamFilter, float deactivationDurationSec, const std::string &identifier, bool deactivate)
Definition Logging.cpp:75
#define CHECK_NOT_QT_THREAD(qtObject)
Definition QtUtil.h:36
#define CHECK_QT_THREAD(qtObject)
Macro to check whether the current function is executed in the thread of the given Qt object.
Definition QtUtil.h:30
#define VAROUT(x)
#define QUOTED(x)
std::map< QString, ManagerData > ManagerDataMap
QMap< QString, ManagedIceObjectItem > ObjectMap
ManagerPrxMap getManagerProxyMap() const
virtual QPointer< QWidget > getWidget()
getWidget returns a pointer to the a widget of this controller.
void enableMainWidgetAsync(bool enable)
This function enables/disables the main widget asynchronously (if called from a non qt thread).
This proxy model reimplements the filterAcceptsRow function with a new behavior: All elements that fi...
static void ExpandFilterResults(QTreeView *treeView)
Expands the treeview that all items that match the filterstring are expanded and directly visible.
ManagedIceObjectConnectivity connectivity
IceManagerPtr getIceManager() const
Returns the IceManager.
The periodic task executes one thread method repeatedly using the time period specified in the constr...
PropertyEditingDelegate(armarx::ManagerPrxMap *managerPrxMap)
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override
QWidget * createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override
void setEditorData(QWidget *editor, const QModelIndex &index) const override
void updateManagerStatesSignal(const ArmarXManagerItem::ManagerDataMap &)
bool retrieveManagerData(ArmarXManagerInterfacePrx prx, ArmarXManagerItem::ManagerData &managerData)
void onDisconnectComponent() override
Hook for subclass.
void loadSettings(QSettings *settings) override
Load stored manager models.
void updateManagerStates(const ArmarXManagerItem::ManagerDataMap &managerData)
Updates the states of the managers stated in the monitored list.
void saveSettings(QSettings *settings) override
Saves the manager models.
void openManagerRepositoryDialog()
Opens the config dialog.
void retrieveManagerObjectsState(ArmarXManagerItem *item)
void addArmarXManagers(QStringList managerNames)
void onExitComponent() override
Hook for subclass.
void acceptConfig()
Accept config changes.
void retrieveOnlineManagers()
Retrieves the online managers.
#define ARMARX_DEBUG_S
The logging level for output that is only interesting while debugging.
Definition Logging.h:205
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
#define ARMARX_DEBUG
The logging level for output that is only interesting while debugging.
Definition Logging.h:184
This file offers overloads of toIce() and fromIce() functions for STL container types.
std::string GetHandledExceptionString()
void handleExceptions()
std::map< QString, ArmarXManagerInterfacePrx > ManagerPrxMap