mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-17 10:55:32 +08:00
refs #712, improved readers
* only trigger read when network interface is available * do not trigger all reads at same time but slightly shifted * renamed to hasReceivedOkReply()
This commit is contained in:
@@ -109,6 +109,12 @@ namespace BlackCore
|
|||||||
{
|
{
|
||||||
// ps_read is implemented in the derived classes
|
// ps_read is implemented in the derived classes
|
||||||
if (entities == CEntityFlags::NoEntity) { return; }
|
if (entities == CEntityFlags::NoEntity) { return; }
|
||||||
|
if (!this->isNetworkAvailable())
|
||||||
|
{
|
||||||
|
CLogMessage(this).warning("No network, will not read %1") << CEntityFlags::flagToString(entities);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const bool s = QMetaObject::invokeMethod(this, "ps_read",
|
const bool s = QMetaObject::invokeMethod(this, "ps_read",
|
||||||
Q_ARG(BlackMisc::Network::CEntityFlags::Entity, entities),
|
Q_ARG(BlackMisc::Network::CEntityFlags::Entity, entities),
|
||||||
Q_ARG(QDateTime, newerThan));
|
Q_ARG(QDateTime, newerThan));
|
||||||
@@ -169,7 +175,7 @@ namespace BlackCore
|
|||||||
|
|
||||||
CDatabaseReader::JsonDatastoreResponse CDatabaseReader::setStatusAndTransformReplyIntoDatastoreResponse(QNetworkReply *nwReply)
|
CDatabaseReader::JsonDatastoreResponse CDatabaseReader::setStatusAndTransformReplyIntoDatastoreResponse(QNetworkReply *nwReply)
|
||||||
{
|
{
|
||||||
this->setConnectionStatus(nwReply);
|
this->setReplyStatus(nwReply);
|
||||||
return this->transformReplyIntoDatastoreResponse(nwReply);
|
return this->transformReplyIntoDatastoreResponse(nwReply);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -233,17 +239,23 @@ namespace BlackCore
|
|||||||
return oldS != currentS;
|
return oldS != currentS;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CDatabaseReader::canConnect() const
|
bool CDatabaseReader::hasReceivedOkReply() const
|
||||||
{
|
{
|
||||||
QReadLocker rl(&this->m_statusLock);
|
QReadLocker rl(&this->m_statusLock);
|
||||||
return m_canConnect;
|
return m_1stReplyReceived && m_1stReplyStatus == QNetworkReply::NoError;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CDatabaseReader::canConnect(QString &message) const
|
bool CDatabaseReader::hasReceivedOkReply(QString &message) const
|
||||||
{
|
{
|
||||||
QReadLocker rl(&this->m_statusLock);
|
QReadLocker rl(&this->m_statusLock);
|
||||||
message = m_statusMessage;
|
message = m_statusMessage;
|
||||||
return m_canConnect;
|
return m_1stReplyReceived && m_1stReplyStatus == QNetworkReply::NoError;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CDatabaseReader::hasReceivedFirstReply() const
|
||||||
|
{
|
||||||
|
QReadLocker rl(&this->m_statusLock);
|
||||||
|
return m_1stReplyReceived;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QString &CDatabaseReader::getStatusMessage() const
|
const QString &CDatabaseReader::getStatusMessage() const
|
||||||
@@ -251,28 +263,20 @@ namespace BlackCore
|
|||||||
return this->m_statusMessage;
|
return this->m_statusMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CDatabaseReader::setConnectionStatus(bool ok, const QString &message)
|
void CDatabaseReader::setReplyStatus(QNetworkReply::NetworkError status, const QString &message)
|
||||||
{
|
|
||||||
{
|
{
|
||||||
QWriteLocker wl(&this->m_statusLock);
|
QWriteLocker wl(&this->m_statusLock);
|
||||||
this->m_statusMessage = message;
|
this->m_statusMessage = message;
|
||||||
this->m_canConnect = ok;
|
this->m_1stReplyStatus = status;
|
||||||
}
|
this->m_1stReplyReceived = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CDatabaseReader::setConnectionStatus(QNetworkReply *nwReply)
|
void CDatabaseReader::setReplyStatus(QNetworkReply *nwReply)
|
||||||
{
|
{
|
||||||
Q_ASSERT_X(nwReply, Q_FUNC_INFO, "Missing network reply");
|
Q_ASSERT_X(nwReply, Q_FUNC_INFO, "Missing network reply");
|
||||||
if (nwReply->isFinished())
|
if (nwReply && nwReply->isFinished())
|
||||||
{
|
{
|
||||||
if (nwReply->error() == QNetworkReply::NoError)
|
this->setReplyStatus(nwReply->error(), nwReply->errorString());
|
||||||
{
|
|
||||||
setConnectionStatus(true);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
setConnectionStatus(false, nwReply->errorString());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,7 @@
|
|||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QtGlobal>
|
#include <QtGlobal>
|
||||||
|
#include <QNetworkReply>
|
||||||
|
|
||||||
class QNetworkReply;
|
class QNetworkReply;
|
||||||
namespace BlackMisc { class CLogCategoryList; }
|
namespace BlackMisc { class CLogCategoryList; }
|
||||||
@@ -98,14 +99,18 @@ namespace BlackCore
|
|||||||
//! Start reading in own thread (without config/caching)
|
//! Start reading in own thread (without config/caching)
|
||||||
void startReadFromDbInBackgroundThread(BlackMisc::Network::CEntityFlags::Entity entities, const QDateTime &newerThan);
|
void startReadFromDbInBackgroundThread(BlackMisc::Network::CEntityFlags::Entity entities, const QDateTime &newerThan);
|
||||||
|
|
||||||
//! Can connect to DB
|
//! Has received Ok response from server at least once?
|
||||||
//! \threadsafe
|
//! \threadsafe
|
||||||
bool canConnect() const;
|
bool hasReceivedOkReply() const;
|
||||||
|
|
||||||
//! Can connect to server?
|
//! Has received Ok response from server at least once?
|
||||||
//! \return message why connect failed
|
//! A message why connect failed can be obtained.
|
||||||
//! \threadsafe
|
//! \threadsafe
|
||||||
bool canConnect(QString &message) const;
|
bool hasReceivedOkReply(QString &message) const;
|
||||||
|
|
||||||
|
//! Has received 1st reply?
|
||||||
|
//! \threadsafe
|
||||||
|
bool hasReceivedFirstReply() const;
|
||||||
|
|
||||||
//! Get cache timestamp
|
//! Get cache timestamp
|
||||||
virtual QDateTime getCacheTimestamp(BlackMisc::Network::CEntityFlags::Entity entities) const = 0;
|
virtual QDateTime getCacheTimestamp(BlackMisc::Network::CEntityFlags::Entity entities) const = 0;
|
||||||
@@ -146,7 +151,8 @@ namespace BlackCore
|
|||||||
protected:
|
protected:
|
||||||
CDatabaseReaderConfigList m_config; //!< DB reder configuration
|
CDatabaseReaderConfigList m_config; //!< DB reder configuration
|
||||||
QString m_statusMessage; //!< Returned status message from watchdog
|
QString m_statusMessage; //!< Returned status message from watchdog
|
||||||
bool m_canConnect = false; //!< Successful connection?
|
bool m_1stReplyReceived = false; //!< Successful connection?
|
||||||
|
QNetworkReply::NetworkError m_1stReplyStatus = QNetworkReply::UnknownServerError; //!< Successful connection?
|
||||||
mutable QReadWriteLock m_statusLock; //!< Lock
|
mutable QReadWriteLock m_statusLock; //!< Lock
|
||||||
|
|
||||||
//! Constructor
|
//! Constructor
|
||||||
@@ -192,11 +198,11 @@ namespace BlackCore
|
|||||||
|
|
||||||
//! Feedback about connection status
|
//! Feedback about connection status
|
||||||
//! \threadsafe
|
//! \threadsafe
|
||||||
void setConnectionStatus(bool ok, const QString &message = "");
|
void setReplyStatus(QNetworkReply::NetworkError status, const QString &message = "");
|
||||||
|
|
||||||
//! Feedback about connection status
|
//! Feedback about connection status
|
||||||
//! \threadsafe
|
//! \threadsafe
|
||||||
void setConnectionStatus(QNetworkReply *nwReply);
|
void setReplyStatus(QNetworkReply *nwReply);
|
||||||
};
|
};
|
||||||
} // ns
|
} // ns
|
||||||
} // ns
|
} // ns
|
||||||
|
|||||||
@@ -197,6 +197,15 @@ namespace BlackCore
|
|||||||
CStatusMessageList CSetupReader::triggerReadSetup()
|
CStatusMessageList CSetupReader::triggerReadSetup()
|
||||||
{
|
{
|
||||||
if (m_shutdown) { return CStatusMessage(this, CStatusMessage::SeverityError, "shutdown"); }
|
if (m_shutdown) { return CStatusMessage(this, CStatusMessage::SeverityError, "shutdown"); }
|
||||||
|
if (!CNetworkUtils::hasConnectedInterface())
|
||||||
|
{
|
||||||
|
const CStatusMessage m(this, CStatusMessage::SeverityError,
|
||||||
|
"No network, cancelled reading of setup");
|
||||||
|
CStatusMessageList msgs(m);
|
||||||
|
msgs.push_back(this->manageSetupAvailability(false, false));
|
||||||
|
return msgs;
|
||||||
|
}
|
||||||
|
|
||||||
const CUrl url(this->m_bootstrapUrls.obtainNextWorkingUrl());
|
const CUrl url(this->m_bootstrapUrls.obtainNextWorkingUrl());
|
||||||
if (url.isEmpty())
|
if (url.isEmpty())
|
||||||
{
|
{
|
||||||
@@ -456,7 +465,7 @@ namespace BlackCore
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bool cacheAvailable = this->m_setup.getThreadLocal().wasLoaded();
|
bool cacheAvailable = this->m_setup.get().wasLoaded();
|
||||||
available = cacheAvailable && this->m_bootstrapMode != Explicit;
|
available = cacheAvailable && this->m_bootstrapMode != Explicit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -73,6 +73,12 @@ namespace BlackCore
|
|||||||
this->initialize();
|
this->initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CThreadedReader::isNetworkAvailable() const
|
||||||
|
{
|
||||||
|
static const bool nw = CNetworkUtils::hasConnectedInterface();
|
||||||
|
return nw;
|
||||||
|
}
|
||||||
|
|
||||||
void CThreadedReader::gracefulShutdown()
|
void CThreadedReader::gracefulShutdown()
|
||||||
{
|
{
|
||||||
// if not in main thread stop, otherwise it makes no sense to abandon
|
// if not in main thread stop, otherwise it makes no sense to abandon
|
||||||
|
|||||||
@@ -55,6 +55,9 @@ namespace BlackCore
|
|||||||
//! \note override as required, default is to call initialize()
|
//! \note override as required, default is to call initialize()
|
||||||
virtual void requestReload();
|
virtual void requestReload();
|
||||||
|
|
||||||
|
//! Network available
|
||||||
|
bool isNetworkAvailable() const;
|
||||||
|
|
||||||
//! Get the timer interval (ms)
|
//! Get the timer interval (ms)
|
||||||
//! \threadsafe
|
//! \threadsafe
|
||||||
int interval() const;
|
int interval() const;
|
||||||
|
|||||||
@@ -67,6 +67,13 @@ namespace BlackCore
|
|||||||
|
|
||||||
void CVatsimBookingReader::ps_read()
|
void CVatsimBookingReader::ps_read()
|
||||||
{
|
{
|
||||||
|
if (!this->isNetworkAvailable())
|
||||||
|
{
|
||||||
|
CLogMessage(this).warning("No network, cancel bookings reader");
|
||||||
|
this->m_updateTimer->stop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this->threadAssertCheck();
|
this->threadAssertCheck();
|
||||||
this->restartTimer(true); // when timer active, restart so we cause no undesired reads
|
this->restartTimer(true); // when timer active, restart so we cause no undesired reads
|
||||||
|
|
||||||
|
|||||||
@@ -186,6 +186,13 @@ namespace BlackCore
|
|||||||
|
|
||||||
void CVatsimDataFileReader::ps_read()
|
void CVatsimDataFileReader::ps_read()
|
||||||
{
|
{
|
||||||
|
if (!this->isNetworkAvailable())
|
||||||
|
{
|
||||||
|
CLogMessage(this).warning("No network, cancel data file reader");
|
||||||
|
this->m_updateTimer->stop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this->threadAssertCheck();
|
this->threadAssertCheck();
|
||||||
this->restartTimer(true); // when timer active, restart so we cause no undesired reads
|
this->restartTimer(true); // when timer active, restart so we cause no undesired reads
|
||||||
|
|
||||||
|
|||||||
@@ -80,6 +80,12 @@ namespace BlackCore
|
|||||||
void CVatsimMetarReader::readMetars()
|
void CVatsimMetarReader::readMetars()
|
||||||
{
|
{
|
||||||
if (this->isAbandoned()) { return; }
|
if (this->isAbandoned()) { return; }
|
||||||
|
if (!this->isNetworkAvailable())
|
||||||
|
{
|
||||||
|
CLogMessage(this).warning("No network, cancel METAR reader");
|
||||||
|
this->m_updateTimer->stop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
this->threadAssertCheck();
|
this->threadAssertCheck();
|
||||||
this->restartTimer(true); // when timer active, restart so we cause no undesired reads
|
this->restartTimer(true); // when timer active, restart so we cause no undesired reads
|
||||||
|
|
||||||
|
|||||||
@@ -83,7 +83,17 @@ namespace BlackCore
|
|||||||
entities &= ~CEntityFlags::InfoObjectEntity; // triggered in init readers
|
entities &= ~CEntityFlags::InfoObjectEntity; // triggered in init readers
|
||||||
entities &= ~CEntityFlags::VatsimStatusFile; // triggered in init readers
|
entities &= ~CEntityFlags::VatsimStatusFile; // triggered in init readers
|
||||||
entities &= ~this->m_entitiesPeriodicallyRead; // will be triggered by timers
|
entities &= ~this->m_entitiesPeriodicallyRead; // will be triggered by timers
|
||||||
this->readDeferredInBackground(entities, 1000);
|
|
||||||
|
// trigger reading
|
||||||
|
// but do not start all at the same time
|
||||||
|
const CEntityFlags::Entity icaoPart = entities & CEntityFlags::AllIcaoAndCountries;
|
||||||
|
const CEntityFlags::Entity modelPart = entities & CEntityFlags::DistributorLiveryModel;
|
||||||
|
this->readDeferredInBackground(icaoPart, 1000);
|
||||||
|
this->readDeferredInBackground(modelPart, 2000);
|
||||||
|
|
||||||
|
CEntityFlags::Entity restEntities = entities & ~icaoPart;
|
||||||
|
restEntities &= ~modelPart;
|
||||||
|
this->readDeferredInBackground(modelPart, 3000);
|
||||||
}
|
}
|
||||||
|
|
||||||
CServerList CWebDataServices::getVatsimFsdServers() const
|
CServerList CWebDataServices::getVatsimFsdServers() const
|
||||||
@@ -146,15 +156,15 @@ namespace BlackCore
|
|||||||
// use the first one to test
|
// use the first one to test
|
||||||
if (m_infoDataReader)
|
if (m_infoDataReader)
|
||||||
{
|
{
|
||||||
return m_infoDataReader->canConnect();
|
return m_infoDataReader->hasReceivedOkReply();
|
||||||
}
|
}
|
||||||
else if (m_icaoDataReader)
|
else if (m_icaoDataReader)
|
||||||
{
|
{
|
||||||
return m_icaoDataReader->canConnect();
|
return m_icaoDataReader->hasReceivedOkReply();
|
||||||
}
|
}
|
||||||
else if (m_modelDataReader)
|
else if (m_modelDataReader)
|
||||||
{
|
{
|
||||||
return m_modelDataReader->canConnect();
|
return m_modelDataReader->hasReceivedOkReply();
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -701,6 +711,7 @@ namespace BlackCore
|
|||||||
|
|
||||||
void CWebDataServices::readDeferredInBackground(CEntityFlags::Entity entities, int delayMs)
|
void CWebDataServices::readDeferredInBackground(CEntityFlags::Entity entities, int delayMs)
|
||||||
{
|
{
|
||||||
|
if (entities == CEntityFlags::NoEntity) { return; }
|
||||||
QTimer::singleShot(delayMs, [ = ]()
|
QTimer::singleShot(delayMs, [ = ]()
|
||||||
{
|
{
|
||||||
this->readInBackground(entities);
|
this->readInBackground(entities);
|
||||||
@@ -712,7 +723,7 @@ namespace BlackCore
|
|||||||
m_initialRead = true; // read started
|
m_initialRead = true; // read started
|
||||||
|
|
||||||
const int waitForInfoObjects = 1000; // ms
|
const int waitForInfoObjects = 1000; // ms
|
||||||
const int maxWaitCycles = 6;
|
const int maxWaitCycles = 10;
|
||||||
|
|
||||||
// with info objects wait until info objects are loaded
|
// with info objects wait until info objects are loaded
|
||||||
Q_ASSERT_X(!entities.testFlag(CEntityFlags::InfoObjectEntity), Q_FUNC_INFO, "Info object must be read upfront");
|
Q_ASSERT_X(!entities.testFlag(CEntityFlags::InfoObjectEntity), Q_FUNC_INFO, "Info object must be read upfront");
|
||||||
@@ -724,14 +735,15 @@ namespace BlackCore
|
|||||||
CLogMessage(this).error("Cannot read info objects for %1 from %2")
|
CLogMessage(this).error("Cannot read info objects for %1 from %2")
|
||||||
<< CEntityFlags::flagToString(entities)
|
<< CEntityFlags::flagToString(entities)
|
||||||
<< this->m_infoDataReader->getInfoObjectsUrl().toQString();
|
<< this->m_infoDataReader->getInfoObjectsUrl().toQString();
|
||||||
// continue here and read data
|
// continue here and read data without info objects
|
||||||
}
|
}
|
||||||
else if (this->m_infoDataReader->canConnect())
|
else if (this->m_infoDataReader->hasReceivedFirstReply())
|
||||||
{
|
{
|
||||||
if (this->m_infoDataReader->areAllDataRead())
|
if (this->m_infoDataReader->areAllDataRead())
|
||||||
{
|
{
|
||||||
CLogMessage(this).info("Info objects for %1 loaded from %2")
|
CLogMessage(this).info("Info objects for %1 loaded (trial %2) from %3")
|
||||||
<< CEntityFlags::flagToString(entities)
|
<< CEntityFlags::flagToString(entities)
|
||||||
|
<< this->m_infoObjectTrials
|
||||||
<< this->m_infoDataReader->getInfoObjectsUrl().toQString();
|
<< this->m_infoDataReader->getInfoObjectsUrl().toQString();
|
||||||
// continue here and read data
|
// continue here and read data
|
||||||
}
|
}
|
||||||
@@ -747,7 +759,7 @@ namespace BlackCore
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// can not connect right now, postpone and try again
|
// wait for 1st reply
|
||||||
this->m_infoObjectTrials++;
|
this->m_infoObjectTrials++;
|
||||||
this->readDeferredInBackground(entities, waitForInfoObjects);
|
this->readDeferredInBackground(entities, waitForInfoObjects);
|
||||||
return;
|
return;
|
||||||
|
|||||||
Reference in New Issue
Block a user