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
This commit is contained in:
Klaus Basan
2018-08-12 03:12:53 +02:00
parent 7b360e03cc
commit 60b3ed65ab
9 changed files with 69 additions and 15 deletions

View File

@@ -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);

View File

@@ -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

View File

@@ -80,6 +80,9 @@ namespace BlackCore
private:
BlackMisc::CIdentifierList m_registeredApplications;
//! Housekeeping
void cleanupRegisteredApplications();
};
} // namespace
} // namespace

View File

@@ -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<BlackMisc::CIdentifier>(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<QString>(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);

View File

@@ -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

View File

@@ -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

View File

@@ -35,15 +35,13 @@ namespace BlackGui
//! Destructor
virtual ~CRegisterComponent();
private slots:
//! Update data
void ps_update();
private:
QScopedPointer<Ui::CRegisterComponent> ui;
QTimer m_updateTimer;
};
//! Update data
void update();
};
} // ns
} // ns

View File

@@ -111,6 +111,12 @@ namespace BlackMisc
});
}
template<class OBJ, class CONTAINER>
CONTAINER ITimestampObjectList<OBJ, CONTAINER>::findAfterNowMinusOffset(qint64 msOffset) const
{
return this->findAfter(QDateTime::currentMSecsSinceEpoch() - msOffset);
}
template<class OBJ, class CONTAINER>
OBJ ITimestampObjectList<OBJ, CONTAINER>::findObjectAfterOrDefault(qint64 msSinceEpoch) const
{

View File

@@ -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;