diff --git a/src/blackcore/application.cpp b/src/blackcore/application.cpp index 66d7b8694..f9e4fbe73 100644 --- a/src/blackcore/application.cpp +++ b/src/blackcore/application.cpp @@ -104,6 +104,7 @@ namespace BlackCore { } CApplication::CApplication(const QString &applicationName, CApplicationInfo::Application application, bool init) : + CIdentifiable(this), m_accessManager(new QNetworkAccessManager(this)), m_applicationInfo(application), m_applicationName(applicationName), m_coreFacadeConfig(CCoreFacadeConfig::allEmpty()) @@ -156,17 +157,19 @@ namespace BlackCore // Init network sApp = this; Q_ASSERT_X(m_accessManager, Q_FUNC_INFO, "Need QAM"); - m_networkWatchDog.reset(new CNetworkWatchdog(this)); // not yet started + CNetworkWatchdog *nwWatchdog = new CNetworkWatchdog(this->isNetworkAccessible(), this); + m_networkWatchDog.reset(nwWatchdog); // not yet started m_cookieManager = new CCookieManager({}, this); m_cookieManager->setParent(m_accessManager); m_accessManager->setCookieJar(m_cookieManager); - connect(m_accessManager, &QNetworkAccessManager::networkAccessibleChanged, this, &CApplication::changedInternetAccessibility, Qt::QueuedConnection); - connect(m_accessManager, &QNetworkAccessManager::networkAccessibleChanged, this, &CApplication::onChangedNetworkAccessibility, Qt::QueuedConnection); - connect(m_accessManager, &QNetworkAccessManager::networkAccessibleChanged, m_networkWatchDog.data(), &CNetworkWatchdog::onChangedNetworkAccessibility, Qt::QueuedConnection); + + // in to watchdog + connect(m_accessManager, &QNetworkAccessManager::networkAccessibleChanged, m_networkWatchDog.data(), &CNetworkWatchdog::setNetworkAccessibility); + + // out from watchdog to application + connect(m_networkWatchDog.data(), &CNetworkWatchdog::changedNetworkAccessible, this, &CApplication::onChangedNetworkAccessibility, Qt::QueuedConnection); connect(m_networkWatchDog.data(), &CNetworkWatchdog::changedInternetAccessibility, this, &CApplication::onChangedInternetAccessibility, Qt::QueuedConnection); connect(m_networkWatchDog.data(), &CNetworkWatchdog::changedSwiftDbAccessibility, this, &CApplication::onChangedSwiftDbAccessibility, Qt::QueuedConnection); - connect(m_networkWatchDog.data(), &CNetworkWatchdog::changedInternetAccessibility, this, &CApplication::changedInternetAccessibility, Qt::QueuedConnection); - connect(m_networkWatchDog.data(), &CNetworkWatchdog::changedSwiftDbAccessibility, this, &CApplication::changedSwiftDbAccessibility, Qt::QueuedConnection); CLogMessage::preformatted(CNetworkUtils::createNetworkReport(m_accessManager)); m_networkWatchDog->start(QThread::LowestPriority); @@ -359,10 +362,9 @@ namespace BlackCore // crashpad dump if (this->isSet(m_cmdTestCrashpad)) { - QPointer myself(this); QTimer::singleShot(10 * 1000, [ = ] { - if (!myself) { return; } + if (!sApp || sApp->isShuttingDown()) { return; } #ifdef BLACK_USE_CRASHPAD CRASHPAD_SIMULATE_CRASH(); #else @@ -630,7 +632,7 @@ namespace BlackCore return getFromNetwork(request, NoLogRequestId, callback, maxRedirects); } - QNetworkReply *CApplication::getFromNetwork(const QNetworkRequest &request, int logId, const CSlot &callback, int maxRedirects) + QNetworkReply *CApplication::getFromNetwork(const QNetworkRequest &request, int logId, const CallbackSlot &callback, int maxRedirects) { return httpRequestImpl(request, logId, callback, maxRedirects, [](QNetworkAccessManager & qam, const QNetworkRequest & request) { @@ -651,7 +653,7 @@ namespace BlackCore QNetworkReply *CApplication::postToNetwork(const QNetworkRequest &request, int logId, QHttpMultiPart *multiPart, const CSlot &callback) { if (!this->isNetworkAccessible()) { return nullptr; } - if (QThread::currentThread() != m_accessManager->thread()) + if (multiPart->thread() != m_accessManager->thread()) { multiPart->moveToThread(m_accessManager->thread()); } @@ -668,17 +670,17 @@ namespace BlackCore }); } - QNetworkReply *CApplication::headerFromNetwork(const CUrl &url, const CSlot &callback, int maxRedirects) + QNetworkReply *CApplication::headerFromNetwork(const CUrl &url, const CallbackSlot &callback, int maxRedirects) { return headerFromNetwork(url.toNetworkRequest(), callback, maxRedirects); } - QNetworkReply *CApplication::headerFromNetwork(const QNetworkRequest &request, const CSlot &callback, int maxRedirects) + QNetworkReply *CApplication::headerFromNetwork(const QNetworkRequest &request, const CallbackSlot &callback, int maxRedirects) { return httpRequestImpl(request, NoLogRequestId, callback, maxRedirects, [ ](QNetworkAccessManager & qam, const QNetworkRequest & request) { return qam.head(request); }); } - QNetworkReply *CApplication::downloadFromNetwork(const CUrl &url, const QString &saveAsFileName, const BlackMisc::CSlot &callback, int maxRedirects) + QNetworkReply *CApplication::downloadFromNetwork(const CUrl &url, const QString &saveAsFileName, const CSlot &callback, int maxRedirects) { // upfront checks if (url.isEmpty()) { return nullptr; } @@ -686,7 +688,7 @@ namespace BlackCore const QFileInfo fi(saveAsFileName); if (!fi.dir().exists()) { return nullptr; } - CSlot slot([ = ](QNetworkReply * reply) + CallbackSlot slot([ = ](QNetworkReply * reply) { QScopedPointer nwReply(reply); CStatusMessage msg; @@ -702,7 +704,11 @@ namespace BlackCore CStatusMessage(this, CStatusMessage::SeverityError, "Saving file '%1' downloaded from '%2' failed") << saveAsFileName << url.getFullUrl(); } nwReply->close(); - QTimer::singleShot(0, callback.object(), [ = ] { callback(msg); }); + QTimer::singleShot(0, callback.object(), [ = ] + { + if (!sApp || sApp->isShuttingDown()) { return; } + callback(msg); + }); }); slot.setObject(this); // object for thread QNetworkReply *reply = this->getFromNetwork(url, slot, maxRedirects); @@ -725,7 +731,7 @@ namespace BlackCore m_networkWatchDog->setDbAccessibility(accessible); } - int CApplication::triggerNetworkChecks() + int CApplication::triggerNetworkWatchdogChecks() { if (!m_networkWatchDog) { return -1; } return m_networkWatchDog->triggerCheck(); @@ -1073,14 +1079,10 @@ namespace BlackCore void CApplication::onChangedInternetAccessibility(bool accessible) { - if (accessible) - { - CLogMessage(this).info("Internet reported accessible"); - } - else - { - CLogMessage(this).warning("Internet not accessible"); - } + if (accessible) { CLogMessage(this).info("Internet reported accessible"); } + else { CLogMessage(this).warning("Internet not accessible"); } + + emit this->changedInternetAccessibility(accessible); } void CApplication::onChangedSwiftDbAccessibility(bool accessible, const CUrl &url) @@ -1096,7 +1098,10 @@ namespace BlackCore { CLogMessage(this).warning(m_networkWatchDog->getCheckInfo()); } + this->triggerNetworkAccessibilityCheck(10 * 1000); // crosscheck after some time } + + emit this->changedSwiftDbAccessibility(accessible, url); } CStatusMessageList CApplication::asyncWebAndContextStart() @@ -1544,22 +1549,48 @@ namespace BlackCore #endif } + void CApplication::httpRequestImplInQAMThread(const QNetworkRequest &request, int logId, const CallbackSlot &callback, int maxRedirects, NetworkRequestOrPostFunction requestOrPostMethod) + { + // run in QAM thread + if (this->isShuttingDown()) { return; } + QTimer::singleShot(0, m_accessManager, [ = ] + { + // should be now in QAM thread + if (!sApp || sApp->isShuttingDown()) { return; } + Q_ASSERT_X(CThreadUtils::isCurrentThreadObjectThread(sApp->m_accessManager), Q_FUNC_INFO, "Wrong thread, must be QAM thread"); + this->httpRequestImpl(request, logId, callback, maxRedirects, requestOrPostMethod); + }); + } + + void CApplication::triggerNetworkAccessibilityCheck(int deferredMs) + { + if (this->isShuttingDown()) { return; } + if (!m_networkWatchDog) { return; } + QTimer::singleShot(deferredMs, m_accessManager, [ = ] + { + // should be now in QAM thread + if (!sApp || sApp->isShuttingDown()) { return; } + Q_ASSERT_X(CThreadUtils::isCurrentThreadObjectThread(sApp->m_accessManager), Q_FUNC_INFO, "Wrong thread, must be QAM thread"); + const QNetworkAccessManager::NetworkAccessibility accessibility = m_accessManager->networkAccessible(); + m_networkWatchDog->setNetworkAccessibility(accessibility); + }); + } + QNetworkReply *CApplication::httpRequestImpl( const QNetworkRequest &request, int logId, - const BlackMisc::CSlot &callback, int maxRedirects, std::function requestOrPostMethod) + const CallbackSlot &callback, int maxRedirects, NetworkRequestOrPostFunction requestOrPostMethod) { if (this->isShuttingDown()) { return nullptr; } if (!this->isNetworkAccessible()) { return nullptr; } QWriteLocker locker(&m_accessManagerLock); - Q_ASSERT_X(QCoreApplication::instance()->thread() == m_accessManager->thread(), Q_FUNC_INFO, "Network manager supposed to be in main thread"); - if (QThread::currentThread() != m_accessManager->thread()) + Q_ASSERT_X(CThreadUtils::isApplicationThreadObjectThread(m_accessManager), Q_FUNC_INFO, "Network manager supposed to be in main thread"); + if (!CThreadUtils::isCurrentThreadObjectThread(m_accessManager)) { - // run in QAM thread - QTimer::singleShot(0, m_accessManager, std::bind(&CApplication::httpRequestImpl, this, request, logId, callback, maxRedirects, requestOrPostMethod)); - return nullptr; // not yet started + this->httpRequestImplInQAMThread(request, logId, callback, maxRedirects, requestOrPostMethod); + return nullptr; // not yet started, will be called again in QAM thread } - Q_ASSERT_X(QThread::currentThread() == m_accessManager->thread(), Q_FUNC_INFO, "Network manager thread mismatch"); + Q_ASSERT_X(CThreadUtils::isCurrentThreadObjectThread(m_accessManager), Q_FUNC_INFO, "Network manager thread mismatch"); QNetworkRequest copiedRequest = CNetworkUtils::getSwiftNetworkRequest(request, this->getApplicationNameAndVersion()); // If URL is one of the shared URLs, add swift client SSL certificate to request @@ -1584,7 +1615,7 @@ namespace BlackCore { QNetworkRequest redirectRequest(redirectUrl); const int redirectsLeft = maxRedirects - 1; - QTimer::singleShot(0, this, std::bind(&CApplication::httpRequestImpl, this, redirectRequest, logId, callback, redirectsLeft, requestOrPostMethod)); + this->httpRequestImplInQAMThread(redirectRequest, logId, callback, redirectsLeft, requestOrPostMethod); return; } } diff --git a/src/blackcore/application.h b/src/blackcore/application.h index 5ca292b1d..5bf92b769 100644 --- a/src/blackcore/application.h +++ b/src/blackcore/application.h @@ -21,6 +21,7 @@ #include "blackmisc/db/updateinfo.h" #include "blackmisc/network/urllist.h" #include "blackmisc/network/networkutils.h" +#include "blackmisc/identifiable.h" #include "blackmisc/slot.h" #include "blackmisc/applicationinfolist.h" #include "blackmisc/statusmessagelist.h" @@ -91,7 +92,9 @@ namespace BlackCore * * \sa BlackGui::CGuiApplication for the GUI version of application */ - class BLACKCORE_EXPORT CApplication : public QObject + class BLACKCORE_EXPORT CApplication : + public QObject, + public BlackMisc::CIdentifiable { Q_OBJECT @@ -386,11 +389,14 @@ namespace BlackCore static constexpr int NoLogRequestId = -1; //!< network request without logging static constexpr int DefaultMaxRedirects = 2; //!< network request, default for max.redirects + //! The network reply callback when request is completed + using CallbackSlot = BlackMisc::CSlot; + //! Delete all cookies from cookie manager void deleteAllCookies(); //! Get the watchdog - //! \remark mostly for UNIT tests etc, normally not meant to be used directly + //! \private mostly for UNIT tests etc, normally not meant to be used directly Db::CNetworkWatchdog *getNetworkWatchdog() const; //! Allows to mark the DB as "up" or "down" @@ -398,7 +404,7 @@ namespace BlackCore void setSwiftDbAccessibility(bool accessible); //! \copydoc BlackCore::Db::CNetworkWatchdog::triggerCheck - int triggerNetworkChecks(); + int triggerNetworkWatchdogChecks(); //! Is network accessible bool isNetworkAccessible() const; @@ -430,43 +436,39 @@ namespace BlackCore //! Request to get network reply //! \threadsafe QNetworkReply *getFromNetwork(const BlackMisc::Network::CUrl &url, - const BlackMisc::CSlot &callback, int maxRedirects = DefaultMaxRedirects); + const CallbackSlot &callback, int maxRedirects = DefaultMaxRedirects); //! Request to get network reply, supporting BlackMisc::Network::CUrlLog //! \threadsafe QNetworkReply *getFromNetwork(const BlackMisc::Network::CUrl &url, int logId, - const BlackMisc::CSlot &callback, int maxRedirects = DefaultMaxRedirects); + const CallbackSlot &callback, int maxRedirects = DefaultMaxRedirects); //! Request to get network reply //! \threadsafe QNetworkReply *getFromNetwork(const QNetworkRequest &request, - const BlackMisc::CSlot &callback, int maxRedirects = DefaultMaxRedirects); + const CallbackSlot &callback, int maxRedirects = DefaultMaxRedirects); //! Request to get network reply, supporting BlackMisc::Network::CUrlLog //! \threadsafe QNetworkReply *getFromNetwork(const QNetworkRequest &request, int logId, - const BlackMisc::CSlot &callback, int maxRedirects = DefaultMaxRedirects); + const CallbackSlot &callback, int maxRedirects = DefaultMaxRedirects); //! Post to network //! \threadsafe - QNetworkReply *postToNetwork(const QNetworkRequest &request, int logId, const QByteArray &data, - const BlackMisc::CSlot &callback); + QNetworkReply *postToNetwork(const QNetworkRequest &request, int logId, const QByteArray &data, const CallbackSlot &callback); //! Post to network //! \note This method takes ownership over \c multiPart. //! \threadsafe - QNetworkReply *postToNetwork(const QNetworkRequest &request, int logId, QHttpMultiPart *multiPart, - const BlackMisc::CSlot &callback); + QNetworkReply *postToNetwork(const QNetworkRequest &request, int logId, QHttpMultiPart *multiPart, const CallbackSlot &callback); //! Request to get network repy using HTTP's HEADER method //! \threadsafe - QNetworkReply *headerFromNetwork(const BlackMisc::Network::CUrl &url, - const BlackMisc::CSlot &callback, int maxRedirects = NoRedirects); + QNetworkReply *headerFromNetwork(const BlackMisc::Network::CUrl &url, const CallbackSlot &callback, int maxRedirects = NoRedirects); //! Request to get network repy using HTTP's HEADER method //! \threadsafe - QNetworkReply *headerFromNetwork(const QNetworkRequest &request, - const BlackMisc::CSlot &callback, int maxRedirects = NoRedirects); + QNetworkReply *headerFromNetwork(const QNetworkRequest &request, const CallbackSlot &callback, int maxRedirects = NoRedirects); //! Download file from network and store it as passed //! \threadsafe @@ -598,13 +600,22 @@ namespace BlackCore //! Async. start when setup is loaded BlackMisc::CStatusMessageList asyncWebAndContextStart(); + using NetworkRequestOrPostFunction = std::function; + //! Implementation for getFromNetwork(), postToNetwork() and headerFromNetwork() //! \return QNetworkReply reply will only be returned, if the QNetworkAccessManager is in the same thread QNetworkReply *httpRequestImpl(const QNetworkRequest &request, - int logId, - const BlackMisc::CSlot &callback, - int maxRedirects, - std::function requestOrPostMethod); + int logId, const CallbackSlot &callback, + int maxRedirects, NetworkRequestOrPostFunction requestOrPostMethod); + + //! Call httpRequestImpl in correct thread + void httpRequestImplInQAMThread(const QNetworkRequest &request, + int logId, const CallbackSlot &callback, + int maxRedirects, NetworkRequestOrPostFunction requestOrPostMethod); + + //! Triggers a check of the network accessibility + //! \remark this is a check that will double check that the watchdog will receive the correct QNetworkAccessManager::NetworkAccessibility + void triggerNetworkAccessibilityCheck(int deferredMs); //! Write meta information into the application directory so other swift versions can display them void tagApplicationDataDirectory(); diff --git a/src/blackcore/db/networkwatchdog.cpp b/src/blackcore/db/networkwatchdog.cpp index aae5b91da..96207d0b9 100644 --- a/src/blackcore/db/networkwatchdog.cpp +++ b/src/blackcore/db/networkwatchdog.cpp @@ -10,7 +10,6 @@ #include "networkwatchdog.h" #include "application.h" #include "blackmisc/logmessage.h" -#include "blackcore/data/globalsetup.h" #include "blackmisc/network/networkutils.h" #include @@ -33,15 +32,14 @@ namespace BlackCore return cats; } - CNetworkWatchdog::CNetworkWatchdog(QObject *parent) : CContinuousWorker(parent, "swift DB watchdog") + CNetworkWatchdog::CNetworkWatchdog(bool networkAccessible, QObject *parent) : CContinuousWorker(parent, "swift DB watchdog") { Q_ASSERT_X(sApp, Q_FUNC_INFO, "Need sApp"); - const bool network = sApp->isNetworkAccessible(); // default - m_networkAccessible = network; - m_dbAccessible = network && m_checkDbAccessibility; - m_internetAccessible = network; + m_networkAccessible = networkAccessible; + m_internetAccessible = networkAccessible; + m_dbAccessible = networkAccessible && m_checkDbAccessibility; - if (network) + if (networkAccessible) { this->initWorkingSharedUrlFromSetup(); } @@ -55,8 +53,13 @@ namespace BlackCore m_dbAccessible = accessible; m_internetAccessible = m_internetAccessible && m_networkAccessible; - - QTimer::singleShot(0, &m_updateTimer, [this] { m_updateTimer.start(); }); // restart timer + // restart timer + QPointer myself(this); + QTimer::singleShot(0, &m_updateTimer, [ = ] + { + if (!myself) { return; } + m_updateTimer.start(); + }); } bool CNetworkWatchdog::hasWorkingSharedUrl() const @@ -97,7 +100,7 @@ namespace BlackCore { static const QString info("Internet accessible: %1 (good: %2 / bad: %3), swift DB accessible: %4 (good: %5 / bad: %6) DB last ping URL: '%7' canConnect: %8ms"); const QString pUrl(this->getLastPingDbUrl()); - static const QString cct(QString::number(CanConnectTimeMs)); + static const QString cct = QString::number(CanConnectTimeMs); return info. arg(boolToYesNo(this->isInternetAccessible())).arg(m_totalGoodCountInternet).arg(m_totalBadCountInternet). arg(boolToYesNo(this->isSwiftDbAccessible())).arg(m_totalGoodCountDb).arg(m_totalBadCountDb). @@ -126,9 +129,9 @@ namespace BlackCore { const bool wasDbAvailable = m_dbAccessible; const bool wasInternetAvailable = m_internetAccessible; - const bool networkAccess = m_networkAccessible; + const bool networkAccessible = m_networkAccessible; const CUrl testUrl(CNetworkWatchdog::dbTestUrl()); - bool canConnectDb = m_checkDbAccessibility && networkAccess && + bool canConnectDb = m_checkDbAccessibility && networkAccessible && CNetworkUtils::canConnect(testUrl, CanConnectTimeMs); // running here in background worker if (m_checkDbAccessibility && m_doDetailedCheck && canConnectDb) { @@ -137,12 +140,12 @@ namespace BlackCore if (lastHttpSuccess && m_totalCheckCount % 10 == 0) { // seems to be OK, from time to time ping - this->pingDbClientService(PingStarted); + this->pingDbClientService(CGlobalSetup::PingStarted); } else if (!lastHttpSuccess && m_totalCheckCount % 3 == 0) { // not OK, retry more frequently - this->pingDbClientService(PingStarted, true); // force + this->pingDbClientService(CGlobalSetup::PingStarted, true); // force } canConnectDb = lastHttpSuccess; } @@ -159,7 +162,7 @@ namespace BlackCore // check shared URL if (!this->doWorkCheck()) { break; } - if (m_checkSharedUrl && networkAccess) + if (m_checkSharedUrl && networkAccessible) { if (CNetworkUtils::canConnect(this->getWorkingSharedUrl())) { @@ -193,7 +196,7 @@ namespace BlackCore if (canConnectInternet) { m_totalGoodCountInternet++; } else { m_totalBadCountInternet++; } } - m_internetAccessible = networkAccess && canConnectInternet; + m_internetAccessible = networkAccessible && canConnectInternet; // signals this->triggerChangedSignals(wasDbAvailable, wasInternetAvailable); @@ -212,13 +215,31 @@ namespace BlackCore return true; } - void CNetworkWatchdog::onChangedNetworkAccessibility(QNetworkAccessManager::NetworkAccessibility accessible) + void CNetworkWatchdog::setNetworkAccessibility(QNetworkAccessManager::NetworkAccessibility accessibility) { + // avoid unnecessary signals + const int accessiblityInt = static_cast(accessibility); + if (m_networkAccessibility == accessiblityInt) { return; } + + // shift in thread + if (!CThreadUtils::isCurrentThreadObjectThread(this)) + { + QPointer myself(this); + QTimer::singleShot(0, this, [ = ] + { + if (!myself) { return; } + this->setNetworkAccessibility(accessibility); + }); + return; + } + + // set values + m_networkAccessibility = accessiblityInt; const bool db = m_dbAccessible; const bool internet = m_internetAccessible; // Intentionally rating unknown as "accessible" - if (accessible == QNetworkAccessManager::NotAccessible) + if (accessibility == QNetworkAccessManager::NotAccessible) { m_networkAccessible = false; m_dbAccessible = false; @@ -235,41 +256,39 @@ namespace BlackCore this->doWork(); }); } + + emit this->changedNetworkAccessible(accessibility); } void CNetworkWatchdog::gracefulShutdown() { - this->pingDbClientService(PingCompleteShutdown); + this->pingDbClientService(CGlobalSetup::PingCompleteShutdown); this->quit(); } - void CNetworkWatchdog::pingDbClientService(CNetworkWatchdog::PingType type, bool force) + void CNetworkWatchdog::pingDbClientService(CGlobalSetup::PingType type, bool force) { - if (!force && !this->isSwiftDbAccessible()) { return; } if (!sApp || sApp->isShuttingDown()) { return; } + if (!force && !this->isSwiftDbAccessible()) { return; } const CGlobalSetup gs = sApp->getGlobalSetup(); if (!gs.wasLoaded()) { return; } - CUrl pingUrl = gs.getDbClientPingServiceUrl(); - if (pingUrl.isEmpty()) { return; } - - pingUrl.appendQuery("uuid", this->identifier().toUuidString()); - pingUrl.appendQuery("application", sApp->getApplicationNameAndVersion()); - if (type.testFlag(PingLogoff)) { pingUrl.appendQuery("logoff", "true"); } - if (type.testFlag(PingShutdown)) { pingUrl.appendQuery("shutdown", "true"); } - if (type.testFlag(PingStarted)) { pingUrl.appendQuery("started", "true"); } - + const CUrl pingUrl = gs.getDbClientPingServiceUrl(type); sApp->getFromNetwork(pingUrl, { this, &CNetworkWatchdog::replyPingClientService }); } void CNetworkWatchdog::replyPingClientService(QNetworkReply *nwReply) { + // init and clean up QScopedPointer nw(nwReply); // delete reply const bool ok = (nw->error() == QNetworkReply::NoError); const QString errorString = nw->errorString(); + const QString url = nw->url().toString(); nw->close(); + if (!sApp || sApp->isShuttingDown()) { return; } + Q_ASSERT_X(CThreadUtils::isCurrentThreadObjectThread(this), Q_FUNC_INFO, "Wrong thread"); + m_lastClientPingSuccess = ok; - const QString url = nwReply->url().toString(); { QWriteLocker l(&m_lockUrl); m_lastPingUrl = url; @@ -279,6 +298,7 @@ namespace BlackCore { m_totalGoodCountDb++; m_consecutivePingBadCount = 0; + CLogMessage(this).info("Watchdog pinged '%1'") << url; } else { @@ -296,24 +316,14 @@ namespace BlackCore { if (!this->doWorkCheck()) { return; } - // trigger really queued - const QPointer myself(this); if (oldDbAccessible != m_dbAccessible) { const CUrl testUrl(this->dbTestUrl()); - QTimer::singleShot(0, this, [ = ] - { - if (!myself) { return; } - emit this->changedSwiftDbAccessibility(m_dbAccessible, testUrl); - }); + emit this->changedSwiftDbAccessibility(m_dbAccessible, testUrl); } if (oldInternetAccessible != m_internetAccessible) { - QTimer::singleShot(0, this, [ = ] - { - if (!myself) { return; } - emit this->changedInternetAccessibility(m_internetAccessible); - }); + emit this->changedInternetAccessibility(m_internetAccessible); } } diff --git a/src/blackcore/db/networkwatchdog.h b/src/blackcore/db/networkwatchdog.h index c25718a4a..d6370ba4a 100644 --- a/src/blackcore/db/networkwatchdog.h +++ b/src/blackcore/db/networkwatchdog.h @@ -12,6 +12,7 @@ #ifndef BLACKCORE_DB_NETWORKWATCHDOG_H #define BLACKCORE_DB_NETWORKWATCHDOG_H +#include "blackcore/data/globalsetup.h" #include "blackcore/blackcoreexport.h" #include "blackmisc/network/url.h" #include "blackmisc/worker.h" @@ -35,7 +36,11 @@ namespace BlackCore static const BlackMisc::CLogCategoryList &getLogCategories(); //! Ctor - explicit CNetworkWatchdog(QObject *parent = nullptr); + explicit CNetworkWatchdog(bool networkAccessible, QObject *parent); + + //! Network status changed, use this function to inform the watchdog + //! \threadsafe + void setNetworkAccessibility(QNetworkAccessManager::NetworkAccessibility accessibility); //! DB available? //! \threadsafe @@ -100,25 +105,11 @@ namespace BlackCore //! \threadsafe void setWorkingSharedUrl(const BlackMisc::Network::CUrl &workingUrl); - //! Network status changed, use this function to inform the watchdog - void onChangedNetworkAccessibility(QNetworkAccessManager::NetworkAccessibility accessible); - //! Graceful shutdown void gracefulShutdown(); - //! Add info when pinging - enum PingTypeFlag - { - PingUnspecific = 0, - PingLogoff = 1 << 0, - PingStarted = 1 << 1, - PingShutdown = 1 << 2, - PingCompleteShutdown = PingLogoff | PingShutdown - }; - Q_DECLARE_FLAGS(PingType, PingTypeFlag) - //! Ping the DB server, fire and forget (no feedback etc) - void pingDbClientService(PingType type = PingUnspecific, bool force = false); + void pingDbClientService(Data::CGlobalSetup::PingType type = Data::CGlobalSetup::PingUnspecific, bool force = false); //! URL referring to the DB //! \remark depends on BlackCore::Application::getGlobalSetup() @@ -136,6 +127,10 @@ namespace BlackCore //! Internet was available, but not longer is and vice versa void changedInternetAccessibility(bool available); + //! Cleaned version of QNetworkAccessManager::networkAccessibleChanged + //! \remark does only fire if the accessibility changed + void changedNetworkAccessible(QNetworkAccessManager::NetworkAccessibility accessible); + private: static constexpr int CanConnectTimeMs = 5000; @@ -145,7 +140,7 @@ namespace BlackCore //! Do check bool doWorkCheck() const; - //! Trigger the changed signals + //! Trigger the changed signals and avoid unneccessary signals void triggerChangedSignals(bool oldDbAccessible, bool oldInternetAccessible); //! Init a working shared URL @@ -171,12 +166,13 @@ namespace BlackCore std::atomic_bool m_checkDbAccessibility { true }; std::atomic_bool m_checkSharedUrl { true }; std::atomic_bool m_checkInProgress { false }; //!< a check is currently in progress + std::atomic_int m_networkAccessibility { QNetworkAccessManager::Accessible }; //!< last state std::atomic_int m_totalCheckCount { 0 }; //!< counting number of checks - std::atomic_int m_totalBadCountDb { 0 }; //! Total number of DB failing counts (only real responses when tried) - std::atomic_int m_totalBadCountInternet { 0 }; //! Total number of Internet failing count (only when network is accessible) + std::atomic_int m_totalBadCountDb { 0 }; //!< Total number of DB failing counts (only real responses when tried) + std::atomic_int m_totalBadCountInternet { 0 }; //!< Total number of Internet failing count (only when network is accessible) std::atomic_int m_totalGoodCountDb { 0 }; std::atomic_int m_totalGoodCountInternet { 0 }; - std::atomic_int m_consecutivePingBadCount { 0 }; //! Bad count of ping until a godd state is received + std::atomic_int m_consecutivePingBadCount { 0 }; //!< Bad count of ping until a godd state is received QString m_lastPingUrl; BlackMisc::Network::CUrl m_workingSharedUrl; mutable QReadWriteLock m_lockUrl; @@ -184,8 +180,4 @@ namespace BlackCore } // ns } // ns -Q_DECLARE_METATYPE(BlackCore::Db::CNetworkWatchdog::PingTypeFlag) -Q_DECLARE_METATYPE(BlackCore::Db::CNetworkWatchdog::PingType) -Q_DECLARE_OPERATORS_FOR_FLAGS(BlackCore::Db::CNetworkWatchdog::PingType) - #endif // guard diff --git a/src/blackcore/threadedreader.cpp b/src/blackcore/threadedreader.cpp index e4a18c056..ed8aa5c55 100644 --- a/src/blackcore/threadedreader.cpp +++ b/src/blackcore/threadedreader.cpp @@ -136,7 +136,7 @@ namespace BlackCore void CThreadedReader::threadAssertCheck() const { Q_ASSERT_X(QCoreApplication::instance()->thread() != QThread::currentThread(), Q_FUNC_INFO, "Needs to run in own thread"); - Q_ASSERT_X(QObject::thread() == QThread::currentThread(), Q_FUNC_INFO, "Wrong object thread"); + Q_ASSERT_X(this->thread() == QThread::currentThread(), Q_FUNC_INFO, "Wrong object thread"); } void CThreadedReader::setInitialAndPeriodicTime(int initialTime, int periodicTime) diff --git a/tests/blackcore/testconnectivity.cpp b/tests/blackcore/testconnectivity.cpp index 85f7b0c06..8adf2ac92 100644 --- a/tests/blackcore/testconnectivity.cpp +++ b/tests/blackcore/testconnectivity.cpp @@ -38,7 +38,7 @@ namespace BlackCoreTest QVERIFY2(sApp, "sApp not available"); QVERIFY2(sApp->getNetworkWatchdog(), "No network watchdog"); - const int n = sApp->triggerNetworkChecks(); + const int n = sApp->triggerNetworkWatchdogChecks(); QVERIFY2(n >= 0, "Cannot trigger setup reader"); m_networkCheckCount = n; qDebug() << "Initial network check count:" << n;