From 60b3ed65abcd74372ce02225d35c1164fd54c67d Mon Sep 17 00:00:00 2001 From: Klaus Basan Date: Sun, 12 Aug 2018 03:12:53 +0200 Subject: [PATCH] Ref T301, application contexts pings (by re-registering) identifiers again. By that it can be detected if the GUI is crashed * ping timer in proxy * utility function in timestamp list * adjusted UI component displaying identifiers in core --- src/blackcore/context/contextapplication.h | 2 ++ .../context/contextapplicationimpl.cpp | 21 +++++++++++++++---- .../context/contextapplicationimpl.h | 3 +++ .../context/contextapplicationproxy.cpp | 19 ++++++++++++++++- .../context/contextapplicationproxy.h | 7 ++++++- src/blackgui/components/registercomponent.cpp | 15 +++++++++---- src/blackgui/components/registercomponent.h | 8 +++---- src/blackmisc/timestampobjectlist.cpp | 6 ++++++ src/blackmisc/timestampobjectlist.h | 3 +++ 9 files changed, 69 insertions(+), 15 deletions(-) diff --git a/src/blackcore/context/contextapplication.h b/src/blackcore/context/contextapplication.h index 81e3be23d..e8b9584c5 100644 --- a/src/blackcore/context/contextapplication.h +++ b/src/blackcore/context/contextapplication.h @@ -212,6 +212,8 @@ namespace BlackCore virtual QString dotCommandsHtmlHelp() const = 0; protected: + static constexpr int PingIdentifiersMs = 20000; //!< how often identifiers are pinged + //! Constructor IContextApplication(CCoreFacadeConfig::ContextMode mode, CCoreFacade *runtime); diff --git a/src/blackcore/context/contextapplicationimpl.cpp b/src/blackcore/context/contextapplicationimpl.cpp index 5a9047b5f..975b99214 100644 --- a/src/blackcore/context/contextapplicationimpl.cpp +++ b/src/blackcore/context/contextapplicationimpl.cpp @@ -153,17 +153,22 @@ namespace BlackCore CIdentifier CContextApplication::registerApplication(const CIdentifier &application) { if (m_debugEnabled) { CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO << application; } - if (!m_registeredApplications.contains(application)) + + CIdentifier identifier(application); + identifier.setCurrentUtcTime(); + + if (!m_registeredApplications.contains(identifier)) { - m_registeredApplications.push_back(application); + m_registeredApplications.push_back(identifier); emit this->registrationChanged(); emit this->hotkeyActionsRegistered(CInputManager::instance()->allAvailableActions(), {}); } else { - m_registeredApplications.replace(application, application); + m_registeredApplications.replace(application, identifier); } + this->cleanupRegisteredApplications(); return application; } @@ -171,13 +176,21 @@ namespace BlackCore { if (m_debugEnabled) { CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO << application; } int r = m_registeredApplications.remove(application); + this->cleanupRegisteredApplications(); if (r > 0) { emit registrationChanged(); } } + void CContextApplication::cleanupRegisteredApplications() + { + static const int outdatedMs = qRound(1.5 * PingIdentifiersMs); + m_registeredApplications.removeOlderThanNowMinusOffset(outdatedMs); + } + CIdentifierList CContextApplication::getRegisteredApplications() const { if (m_debugEnabled) { CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO; } - return m_registeredApplications; + static const int outdatedMs = qRound(1.5 * PingIdentifiersMs); + return m_registeredApplications.findAfterNowMinusOffset(outdatedMs); } QString CContextApplication::readFromFile(const QString &fileName) const diff --git a/src/blackcore/context/contextapplicationimpl.h b/src/blackcore/context/contextapplicationimpl.h index afdd3249e..c45b819f9 100644 --- a/src/blackcore/context/contextapplicationimpl.h +++ b/src/blackcore/context/contextapplicationimpl.h @@ -80,6 +80,9 @@ namespace BlackCore private: BlackMisc::CIdentifierList m_registeredApplications; + + //! Housekeeping + void cleanupRegisteredApplications(); }; } // namespace } // namespace diff --git a/src/blackcore/context/contextapplicationproxy.cpp b/src/blackcore/context/contextapplicationproxy.cpp index c347d9e85..eecd9f646 100644 --- a/src/blackcore/context/contextapplicationproxy.cpp +++ b/src/blackcore/context/contextapplicationproxy.cpp @@ -37,6 +37,10 @@ namespace BlackCore CLogHandler::instance()->logRemoteMessage(message); } }); + + m_pingTimer.setObjectName(serviceName + "::m_pingTimer"); + connect(&m_pingTimer, &QTimer::timeout, this, &CContextApplicationProxy::reRegisterApplications); + m_pingTimer.start(PingIdentifiersMs); } void CContextApplicationProxy::relaySignals(const QString &serviceName, QDBusConnection &connection) @@ -156,13 +160,15 @@ namespace BlackCore m_dBusInterface->callDBus(QLatin1String("callHotkeyAction"), action, argument, origin); } - BlackMisc::CIdentifier CContextApplicationProxy::registerApplication(const CIdentifier &application) + CIdentifier CContextApplicationProxy::registerApplication(const CIdentifier &application) { + m_proxyPingIdentifiers.insert(application); return m_dBusInterface->callDBusRet(QLatin1String("registerApplication"), application); } void CContextApplicationProxy::unregisterApplication(const CIdentifier &application) { + m_proxyPingIdentifiers.remove(application); m_dBusInterface->callDBus(QLatin1String("unregisterApplication"), application); } @@ -200,6 +206,17 @@ namespace BlackCore return m_dBusInterface->callDBusRet(QLatin1String("dotCommandsHtmlHelp")); } + void CContextApplicationProxy::reRegisterApplications() + { + if (!m_dBusInterface) { return; } + if (m_proxyPingIdentifiers.isEmpty()) { return; } + const CIdentifierList identifiers = m_proxyPingIdentifiers; // copy so member can be modified + for (const CIdentifier &identifier : identifiers) + { + this->registerApplication(identifier); + } + } + bool CContextApplicationProxy::isContextResponsive(const QString &dBusAddress, QString &msg, int timeoutMs) { const bool connected = CDBusServer::isDBusAvailable(dBusAddress, msg, timeoutMs); diff --git a/src/blackcore/context/contextapplicationproxy.h b/src/blackcore/context/contextapplicationproxy.h index 9f94113a8..2f478683f 100644 --- a/src/blackcore/context/contextapplicationproxy.h +++ b/src/blackcore/context/contextapplicationproxy.h @@ -89,10 +89,15 @@ namespace BlackCore CContextApplicationProxy(const QString &serviceName, QDBusConnection &connection, CCoreFacadeConfig::ContextMode mode, CCoreFacade *runtime); private: - BlackMisc::CGenericDBusInterface *m_dBusInterface = nullptr; + BlackMisc::CGenericDBusInterface *m_dBusInterface = nullptr; //!< interface + BlackMisc::CIdentifierList m_proxyPingIdentifiers; //!< automatically ping the implementing side + QTimer m_pingTimer; //! Relay connection signals to local signals void relaySignals(const QString &serviceName, QDBusConnection &connection); + + //! Ping/heartbeat identifiers + void reRegisterApplications(); }; } // ns } // ns diff --git a/src/blackgui/components/registercomponent.cpp b/src/blackgui/components/registercomponent.cpp index d05432966..e5d24ffd6 100644 --- a/src/blackgui/components/registercomponent.cpp +++ b/src/blackgui/components/registercomponent.cpp @@ -17,6 +17,7 @@ using namespace BlackCore; using namespace BlackCore::Context; +using namespace BlackGui::Views; namespace BlackGui { @@ -26,11 +27,17 @@ namespace BlackGui QFrame(parent), ui(new Ui::CRegisterComponent) { + Q_ASSERT_X(sGui, Q_FUNC_INFO, "Need sGui"); + Q_ASSERT_X(sGui->getIContextApplication(), Q_FUNC_INFO, "Need application context"); + ui->setupUi(this); - connect(sGui->getIContextApplication(), &IContextApplication::registrationChanged, this, &CRegisterComponent::ps_update); + ui->tvp_RegisteredComponents->menuAddItems(CIdentifierView::MenuRefresh); + + connect(&m_updateTimer, &QTimer::timeout, this, &CRegisterComponent::update); + connect(sGui->getIContextApplication(), &IContextApplication::registrationChanged, this, &CRegisterComponent::update); + connect(ui->tvp_RegisteredComponents, &CIdentifierView::requestUpdate, this, &CRegisterComponent::update); // timer is there just in case something goes wrong - connect(&m_updateTimer, &QTimer::timeout, this, &CRegisterComponent::ps_update); m_updateTimer.setInterval(30 * 1000); m_updateTimer.start(); } @@ -38,10 +45,10 @@ namespace BlackGui CRegisterComponent::~CRegisterComponent() { } - void CRegisterComponent::ps_update() + void CRegisterComponent::update() { // if not supported, do nothing - if (!sGui || !sGui->supportsContexts()) { return; } + if (!sGui || !sGui->supportsContexts() || sGui->isShuttingDown()) { return; } ui->tvp_RegisteredComponents->updateContainer(sGui->getIContextApplication()->getRegisteredApplications()); } } // ns diff --git a/src/blackgui/components/registercomponent.h b/src/blackgui/components/registercomponent.h index bfa0ce1ac..d44d444a4 100644 --- a/src/blackgui/components/registercomponent.h +++ b/src/blackgui/components/registercomponent.h @@ -35,15 +35,13 @@ namespace BlackGui //! Destructor virtual ~CRegisterComponent(); - private slots: - //! Update data - void ps_update(); - private: QScopedPointer ui; QTimer m_updateTimer; - }; + //! Update data + void update(); + }; } // ns } // ns diff --git a/src/blackmisc/timestampobjectlist.cpp b/src/blackmisc/timestampobjectlist.cpp index ff1ae8e79..a7340cb87 100644 --- a/src/blackmisc/timestampobjectlist.cpp +++ b/src/blackmisc/timestampobjectlist.cpp @@ -111,6 +111,12 @@ namespace BlackMisc }); } + template + CONTAINER ITimestampObjectList::findAfterNowMinusOffset(qint64 msOffset) const + { + return this->findAfter(QDateTime::currentMSecsSinceEpoch() - msOffset); + } + template OBJ ITimestampObjectList::findObjectAfterOrDefault(qint64 msSinceEpoch) const { diff --git a/src/blackmisc/timestampobjectlist.h b/src/blackmisc/timestampobjectlist.h index 582650a47..279b24b9e 100644 --- a/src/blackmisc/timestampobjectlist.h +++ b/src/blackmisc/timestampobjectlist.h @@ -72,6 +72,9 @@ namespace BlackMisc //! List of objects after msSinceEpoch (newer) CONTAINER findAfter(qint64 msSinceEpoch) const; + //! List of objects before now - offset + CONTAINER findAfterNowMinusOffset(qint64 msOffset) const; + //! List of objects after msSinceEpoch (newer) OBJ findObjectAfterOrDefault(qint64 msSinceEpoch) const;