Ref T24, preparations to read dbinfo.json for shared files

This will replace http header file timestamps
* read function in info reader has retrieval mode flag, unused parameters removed
* waitForDbInfoObjects/getDbInfoDataReader (added "Db"), there will be a 2nd reader
* CWebReaderFlags::DbInfoDataReader (added "Db")
* removed ps_read, only read (public)
This commit is contained in:
Klaus Basan
2017-04-20 02:26:21 +02:00
parent 65f4d1f9e2
commit 485c95101b
7 changed files with 79 additions and 97 deletions

View File

@@ -269,8 +269,8 @@ namespace BlackCore
{
static const CDbInfoList e;
if (!sApp->hasWebDataServices()) { return e; }
if (!sApp->getWebDataServices()->getInfoDataReader()) { return e; }
return sApp->getWebDataServices()->getInfoDataReader()->getDbInfoObjects();
if (!sApp->getWebDataServices()->getDbInfoDataReader()) { return e; }
return sApp->getWebDataServices()->getDbInfoDataReader()->getDbInfoObjects();
}
bool CDatabaseReader::hasInfoObjects() const

View File

@@ -91,37 +91,17 @@ namespace BlackCore
return sApp->getGlobalSetup().getDbInfoReaderUrl();
}
void CInfoDataReader::read(CEntityFlags::Entity entities, const QDateTime &newerThan)
void CInfoDataReader::read()
{
this->ps_read(entities, CDbFlags::DbReading, newerThan);
}
void CInfoDataReader::ps_read(CEntityFlags::Entity entities, CDbFlags::DataRetrievalModeFlag mode, const QDateTime &newerThan)
{
Q_UNUSED(mode);
CEntityFlags::Entity triggeredRead = CEntityFlags::NoEntity;
CUrl url(getInfoObjectsUrl());
if (entities.testFlag(CEntityFlags::InfoObjectEntity))
const CUrl url(getDbInfoObjectsUrl());
if (!url.isEmpty())
{
if (!url.isEmpty())
{
if (!newerThan.isNull())
{
const QString tss(newerThan.toString(Qt::ISODate));
url.appendQuery(QString(parameterLatestTimestamp() + "=" + tss));
}
sApp->getFromNetwork(url, { this, &CInfoDataReader::ps_parseInfoObjectsData});
triggeredRead |= CEntityFlags::InfoObjectEntity;
}
else
{
CLogMessage(this).error("No URL for %1") << CEntityFlags::flagToString(CEntityFlags::InfoObjectEntity);
}
sApp->getFromNetwork(url, { this, &CInfoDataReader::ps_parseInfoObjectsData});
emit dataRead(CEntityFlags::InfoObjectEntity, CEntityFlags::StartRead, 0);
}
if (triggeredRead != CEntityFlags::NoEntity)
else
{
emit dataRead(triggeredRead, CEntityFlags::StartRead, 0);
CLogMessage(this).error("No URL for %1") << CEntityFlags::flagToString(CEntityFlags::InfoObjectEntity);
}
}
@@ -153,7 +133,7 @@ namespace BlackCore
this->emitAndLogDataRead(CEntityFlags::InfoObjectEntity, n, res);
}
CUrl CInfoDataReader::getInfoObjectsUrl() const
CUrl CInfoDataReader::getDbInfoObjectsUrl() const
{
return getBaseUrl(CDbFlags::DbReading).withAppendedPath("jsondbinfo.php");
}

View File

@@ -46,19 +46,18 @@ namespace BlackCore
bool areAllDataRead() const;
//! URL info objects web service
BlackMisc::Network::CUrl getInfoObjectsUrl() const;
BlackMisc::Network::CUrl getDbInfoObjectsUrl() const;
// cache handling for base class
//! Allow to call directly, special for info objects reader
void read();
// cache handling for base class: no cache handling here in that case
virtual BlackMisc::Network::CEntityFlags::Entity getSupportedEntities() const override;
virtual QDateTime getCacheTimestamp(BlackMisc::Network::CEntityFlags::Entity entity) const override;
virtual int getCacheCount(BlackMisc::Network::CEntityFlags::Entity entity) const override;
virtual void synchronizeCaches(BlackMisc::Network::CEntityFlags::Entity entities) override;
virtual void admitCaches(BlackMisc::Network::CEntityFlags::Entity entities) override;
public slots:
//! Allow to call CInfoDataReader::ps_read directly, special for info objects
void read(BlackMisc::Network::CEntityFlags::Entity entities = BlackMisc::Network::CEntityFlags::InfoObjectEntity, const QDateTime &newerThan = QDateTime());
protected:
// cache handling for base class
virtual void invalidateCaches(BlackMisc::Network::CEntityFlags::Entity entities) override;
@@ -69,10 +68,6 @@ namespace BlackCore
//! Info objects have been read
void ps_parseInfoObjectsData(QNetworkReply *nwReply);
//! Read / re-read data file
void ps_read(BlackMisc::Network::CEntityFlags::Entity entities = BlackMisc::Network::CEntityFlags::InfoObjectEntity,
BlackMisc::Db::CDbFlags::DataRetrievalModeFlag mode = BlackMisc::Db::CDbFlags::DbReading, const QDateTime &newerThan = QDateTime());
private:
BlackMisc::Db::CDbInfoList m_infoObjects;
BlackMisc::Network::CUrl m_urlInfoObjects;

View File

@@ -42,6 +42,7 @@ using namespace BlackCore::Db;
using namespace BlackCore::Data;
using namespace BlackCore::Vatsim;
using namespace BlackMisc;
using namespace BlackMisc::Db;
using namespace BlackMisc::Simulation;
using namespace BlackMisc::Network;
using namespace BlackMisc::Aviation;
@@ -61,10 +62,10 @@ namespace BlackCore
// check if I need info objects
const bool readFromSwiftDb = dbReaderConfig.possiblyReadsFromSwiftDb(); // DB read access
const bool writeToSwiftDb = dbReaderConfig.possiblyWritesToSwiftDb(); // DB write access
if (!readFromSwiftDb && readers.testFlag(CWebReaderFlags::InfoDataReader))
if (!readFromSwiftDb && readers.testFlag(CWebReaderFlags::DbInfoDataReader))
{
// will remove info reader because not needed
readers &= ~CWebReaderFlags::InfoDataReader;
readers &= ~CWebReaderFlags::DbInfoDataReader;
this->m_readers = readers;
CLogMessage(this).info("Remove info object reader because not needed");
}
@@ -73,7 +74,7 @@ namespace BlackCore
CEntityFlags::Entity entities = CWebReaderFlags::allEntitiesForReaders(readers);
if (entities.testFlag(CEntityFlags::InfoObjectEntity))
{
Q_ASSERT_X(readers.testFlag(CWebReaderFlags::InfoDataReader), Q_FUNC_INFO, "info object but no reader");
Q_ASSERT_X(readers.testFlag(CWebReaderFlags::DbInfoDataReader), Q_FUNC_INFO, "info object but no reader");
CLogMessage(this).info("Using info objects for swift DB entities");
}
@@ -154,17 +155,17 @@ namespace BlackCore
void CWebDataServices::triggerReadOfInfoObjects()
{
initInfoObjectReaderAndTriggerRead();
initDbInfoObjectReaderAndTriggerRead();
}
bool CWebDataServices::canConnectSwiftDb() const
{
if (!m_icaoDataReader && !m_modelDataReader && !m_airportDataReader && !m_infoDataReader) { return false; }
if (!m_icaoDataReader && !m_modelDataReader && !m_airportDataReader && !m_dbInfoDataReader) { return false; }
// use the first one to test
if (m_infoDataReader)
if (m_dbInfoDataReader)
{
return m_infoDataReader->hasReceivedOkReply();
return m_dbInfoDataReader->hasReceivedOkReply();
}
else if (m_icaoDataReader)
{
@@ -195,7 +196,7 @@ namespace BlackCore
void CWebDataServices::admitDbCaches(CEntityFlags::Entity entities)
{
// hint: all the readers use own threads
if (this->m_infoDataReader) { this->m_infoDataReader->admitCaches(entities); }
if (this->m_dbInfoDataReader) { this->m_dbInfoDataReader->admitCaches(entities); }
if (this->m_modelDataReader) { this->m_modelDataReader->admitCaches(entities); }
if (this->m_icaoDataReader) { this->m_icaoDataReader->admitCaches(entities); }
if (this->m_airportDataReader) { this->m_airportDataReader->admitCaches(entities); }
@@ -269,7 +270,7 @@ namespace BlackCore
CEntityFlags::Entity CWebDataServices::triggerLoadingDirectlyFromDb(CEntityFlags::Entity whatToRead, const QDateTime &newerThan)
{
CEntityFlags::Entity triggeredRead = CEntityFlags::NoEntity;
if (m_infoDataReader)
if (m_dbInfoDataReader)
{
this->triggerReadOfInfoObjects();
triggeredRead |= CEntityFlags::InfoObjectEntity;
@@ -364,7 +365,7 @@ namespace BlackCore
Q_ASSERT_X(CEntityFlags::isSingleEntity(entity), Q_FUNC_INFO, "Need single entity");
if (CEntityFlags::anySwiftDbEntity(entity))
{
CInfoDataReader *ir = this->getInfoDataReader();
CInfoDataReader *ir = this->getDbInfoDataReader();
if (!ir) { return QDateTime(); }
return ir->getLatestEntityTimestampFromInfoObjects(entity);
}
@@ -730,7 +731,7 @@ namespace BlackCore
if (this->m_modelDataReader) { this->m_modelDataReader->gracefulShutdown(); }
if (this->m_airportDataReader) { this->m_airportDataReader->gracefulShutdown(); }
if (this->m_icaoDataReader) { this->m_icaoDataReader->gracefulShutdown(); }
if (this->m_infoDataReader) { this->m_infoDataReader->gracefulShutdown(); }
if (this->m_dbInfoDataReader) { this->m_dbInfoDataReader->gracefulShutdown(); }
if (this->m_databaseWriter) { this->m_databaseWriter->gracefulShutdown(); }
}
@@ -791,12 +792,12 @@ namespace BlackCore
const bool databaseUp = CInfoDataReader::canPingSwiftServer();
if (!databaseUp) { dbReaderConfig.markAsDbDown(); }
if (anyDbEntities && flags.testFlag(CWebReaderFlags::WebReaderFlag::InfoDataReader))
if (anyDbEntities && flags.testFlag(CWebReaderFlags::WebReaderFlag::DbInfoDataReader))
{
// info data reader has a special role, it will not be triggered in triggerRead()
if (databaseUp)
{
this->initInfoObjectReaderAndTriggerRead();
this->initDbInfoObjectReaderAndTriggerRead();
}
else
{
@@ -805,8 +806,11 @@ namespace BlackCore
}
}
// 1b. Read shared headers if needed
// --> See below after readers have been connected
// 1b. Read info objects if needed
if (needsSharedInfoObjects)
{
this->initSharedInfoObjectReaderAndTriggerRead();
}
// 2. Status file, updating the VATSIM related caches
if (flags.testFlag(CWebReaderFlags::VatsimStatusReader) || flags.testFlag(CWebReaderFlags::VatsimDataReader) || flags.testFlag(CWebReaderFlags::VatsimMetarReader))
@@ -908,24 +912,25 @@ namespace BlackCore
Q_UNUSED(c); // signal connect flag
}
void CWebDataServices::initInfoObjectReaderAndTriggerRead()
void CWebDataServices::initDbInfoObjectReaderAndTriggerRead()
{
if (!this->m_infoDataReader)
if (!this->m_dbInfoDataReader)
{
this->m_infoDataReader = new CInfoDataReader(this, m_dbReaderConfig);
bool c = connect(this->m_infoDataReader, &CInfoDataReader::dataRead, this, &CWebDataServices::ps_readFromSwiftDb);
this->m_dbInfoDataReader = new CInfoDataReader(this, m_dbReaderConfig);
bool c = connect(this->m_dbInfoDataReader, &CInfoDataReader::dataRead, this, &CWebDataServices::ps_readFromSwiftDb);
Q_ASSERT_X(c, Q_FUNC_INFO, "Info reader connect failed");
// relay signal
c = connect(this->m_infoDataReader, &CInfoDataReader::dataRead, this, &CWebDataServices::dataRead);
c = connect(this->m_dbInfoDataReader, &CInfoDataReader::dataRead, this, &CWebDataServices::dataRead);
Q_ASSERT_X(c, Q_FUNC_INFO, "Info reader connect failed");
Q_UNUSED(c);
// start in own thread
this->m_infoDataReader->start(QThread::LowPriority);
this->m_dbInfoDataReader->start(QThread::LowPriority);
}
// and trigger read
QTimer::singleShot(0, [this]() { this->m_infoDataReader->read(CEntityFlags::InfoObjectEntity, QDateTime()); });
QTimer::singleShot(0, [this]() { this->m_dbInfoDataReader->read(); });
}
CDatabaseReader *CWebDataServices::getDbReader(CEntityFlags::Entity entity) const
@@ -1050,10 +1055,10 @@ namespace BlackCore
{
// 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, do not pass as entity here");
const bool waitForInfoReader = this->m_infoDataReader && !this->m_infoDataReader->areAllDataRead() && !this->m_infoDataReader->isMarkedAsFailed();
const bool waitForInfoReader = this->m_dbInfoDataReader && !this->m_dbInfoDataReader->areAllDataRead() && !this->m_dbInfoDataReader->isMarkedAsFailed();
if (waitForInfoReader)
{
if (!this->waitForInfoObjects(entities)) { return; } // will call this function again after some time
if (!this->waitForDbInfoObjects(entities)) { return; } // will call this function again after some time
}
const bool waitForSharedHeaders = m_dbReaderConfig.needsSharedHeadersLoaded(entities);
@@ -1067,38 +1072,39 @@ namespace BlackCore
this->triggerRead(entities);
}
bool CWebDataServices::waitForInfoObjects(CEntityFlags::Entity entities)
bool CWebDataServices::waitForDbInfoObjects(CEntityFlags::Entity entities)
{
const int waitForInfoObjectsMs = 1000; // ms
const int maxWaitCycles = 10;
// try to read
if (this->m_infoObjectTrials > maxWaitCycles)
if (this->m_dbInfoObjectTrials > maxWaitCycles)
{
CLogMessage(this).warning("Cannot read info objects for %1 from %2")
CLogMessage(this).warning("Cannot read info objects for '%1' from '%2'")
<< CEntityFlags::flagToString(entities)
<< this->m_infoDataReader->getInfoObjectsUrl().toQString();
<< this->m_dbInfoDataReader->getInfoObjectsUrl().toQString();
// continue here and read data without info objects
return true; // no need wait any longer
this->m_dbInfoDataReader->setMarkedAsFailed(true);
return true; // carry on, regardless of situation
}
else if (this->m_infoDataReader->hasReceivedFirstReply())
else if (this->m_dbInfoDataReader->hasReceivedFirstReply())
{
if (this->m_infoDataReader->areAllDataRead())
if (this->m_dbInfoDataReader->areAllDataRead())
{
// we have all data and carry on
CLogMessage(this).info("Info objects for %1 loaded (trial %2) from %3")
CLogMessage(this).info("Info objects for '%1' loaded (trial %2) from '%3'")
<< CEntityFlags::flagToString(entities)
<< this->m_infoObjectTrials
<< this->m_infoDataReader->getInfoObjectsUrl().toQString();
return true; // no need wait any longer
<< this->m_dbInfoObjectTrials
<< this->m_dbInfoDataReader->getInfoObjectsUrl().toQString();
return true; // no need to wait any longer
}
else
{
// we have received a response, but not all data yet
if (this->m_infoDataReader->hasReceivedOkReply())
if (this->m_dbInfoDataReader->hasReceivedOkReply())
{
// ok, this means we are parsing
this->m_infoObjectTrials++;
this->m_dbInfoObjectTrials++;
this->readDeferredInBackground(entities, waitForInfoObjectsMs);
return false; // wait
}
@@ -1107,19 +1113,19 @@ namespace BlackCore
// we have a response, but a failure
// means server is alive, but responded with error
// such an error (access, ...) normally will not go away
CLogMessage(this).error("Info objects loading for %1 failed from %2, '%3'")
CLogMessage(this).error("Info objects loading for '%1' failed from '%2', '%3'")
<< CEntityFlags::flagToString(entities)
<< this->m_infoDataReader->getInfoObjectsUrl().toQString()
<< this->m_infoDataReader->getStatusMessage();
this->m_infoDataReader->setMarkedAsFailed(true);
return true; // no need wait any longer
<< this->m_dbInfoDataReader->getInfoObjectsUrl().toQString()
<< this->m_dbInfoDataReader->getStatusMessage();
this->m_dbInfoDataReader->setMarkedAsFailed(true);
return true; // carry on, regardless of situation
}
}
}
else
{
// wait for 1st reply
this->m_infoObjectTrials++;
this->m_dbInfoObjectTrials++;
this->readDeferredInBackground(entities, waitForInfoObjectsMs);
return false; // wait
}

View File

@@ -108,7 +108,7 @@ namespace BlackCore
Vatsim::CVatsimMetarReader *getMetarReader() const { return m_vatsimMetarReader; }
//! Info data reader
Db::CInfoDataReader *getInfoDataReader() const { return m_infoDataReader; }
BlackCore::Db::CInfoDataReader *getDbInfoDataReader() const { return m_dbInfoDataReader; }
//! Currently used URL for shared DB data
BlackMisc::Network::CUrl getDbReaderCurrentSharedDbDataUrl() const;
@@ -389,9 +389,10 @@ namespace BlackCore
void dataRead(BlackMisc::Network::CEntityFlags::Entity entity, BlackMisc::Network::CEntityFlags::ReadState state, int number);
//! Header of shared file read
//! \deprecated shared file headers will be replaced by dbinfo.json
void sharedFileHeaderRead(BlackMisc::Network::CEntityFlags::Entity entity, const QString &fileName, bool success);
// simplified signals
// simplified signals follow
// 1) simple signature
// 2) fired direct after read, no need to wait for other entities
@@ -450,8 +451,8 @@ namespace BlackCore
//! Init the readers
void initReaders(CWebReaderFlags::WebReader flags, BlackMisc::Network::CEntityFlags::Entity entities);
//! Init the info objects readers
void initInfoObjectReaderAndTriggerRead();
//! Init the info objects reader (DB web service)
void initDbInfoObjectReaderAndTriggerRead();
//! DB reader for given entity
Db::CDatabaseReader *getDbReader(BlackMisc::Network::CEntityFlags::Entity entity) const;
@@ -463,18 +464,18 @@ namespace BlackCore
bool signalEntitiesRead(BlackMisc::Network::CEntityFlags::Entity entities);
//! Wait for info objects to be read
bool waitForInfoObjects(BlackMisc::Network::CEntityFlags::Entity entities);
bool waitForDbInfoObjects(BlackMisc::Network::CEntityFlags::Entity entities);
//! Wait for shared headers to be read
bool waitForSharedHeaders(BlackMisc::Network::CEntityFlags::Entity entities);
CWebReaderFlags::WebReader m_readers = CWebReaderFlags::WebReaderFlag::None; //!< which readers are available
BlackCore::Db::CDatabaseReaderConfigList m_dbReaderConfig; //!< how to read DB data
BlackMisc::Network::CEntityFlags::Entity m_entitiesPeriodicallyRead = BlackMisc::Network::CEntityFlags::NoEntity; //!< those entities which are permanently updated by timers
BlackMisc::Network::CEntityFlags::Entity m_entitiesPeriodicallyRead = BlackMisc::Network::CEntityFlags::NoEntity; //!< entities permanently updated by timers
BlackMisc::Network::CEntityFlags::Entity m_swiftDbEntitiesRead = BlackMisc::Network::CEntityFlags::NoEntity; //!< entities read
BlackCore::Db::CDatabaseReaderConfigList m_dbReaderConfig; //!< how to read DB data
bool m_initialRead = false; //!< Initial read started
bool m_signalledHeaders = false; //!< headers loading has been signalled
int m_infoObjectTrials = 0; //!< Tried to read info objects
int m_dbInfoObjectTrials = 0; //!< Tried to read info objects
int m_sharedHeadersTrials = 0; //!< Tried to read shared file headers
QSet<BlackMisc::Network::CEntityFlags::Entity> m_signalledEntities; //!< remember signalled entites
@@ -485,8 +486,8 @@ namespace BlackCore
Vatsim::CVatsimMetarReader *m_vatsimMetarReader = nullptr;
Db::CIcaoDataReader *m_icaoDataReader = nullptr;
Db::CModelDataReader *m_modelDataReader = nullptr;
Db::CInfoDataReader *m_infoDataReader = nullptr;
Db::CAirportDataReader *m_airportDataReader = nullptr;
Db::CInfoDataReader *m_dbInfoDataReader = nullptr;
// writing objects directly into DB
Db::CDatabaseWriter *m_databaseWriter = nullptr;

View File

@@ -31,7 +31,7 @@ namespace BlackCore
f |= AirportReader;
}
if (entity.testFlag(CEntityFlags::InfoObjectEntity)) { f |= InfoDataReader; }
if (entity.testFlag(CEntityFlags::InfoObjectEntity)) { f |= DbInfoDataReader; }
if (entity.testFlag(CEntityFlags::BookingEntity)) { f |= VatsimBookingReader; }
if (entity.testFlag(CEntityFlags::VatsimDataFile)) { f |= VatsimDataReader; }
if (entity.testFlag(CEntityFlags::VatsimStatusFile)) { f |= VatsimStatusReader; }
@@ -51,7 +51,7 @@ namespace BlackCore
if (readers.testFlag(IcaoDataReader)) { entities |= CEntityFlags::AllIcaoAndCountries; }
if (readers.testFlag(ModelReader)) { entities |= CEntityFlags::DistributorLiveryModel; }
if (readers.testFlag(AirportReader)) { entities |= CEntityFlags::AirportEntity; }
if (readers.testFlag(InfoDataReader)) { entities |= CEntityFlags::InfoObjectEntity; }
if (readers.testFlag(DbInfoDataReader)) { entities |= CEntityFlags::InfoObjectEntity; }
if (readers.testFlag(VatsimBookingReader)) { entities |= CEntityFlags::BookingEntity; }
if (readers.testFlag(VatsimMetarReader)) { entities |= CEntityFlags::MetarEntity; }
if (readers.testFlag(VatsimDataReader)) { entities |= CEntityFlags::VatsimDataFile; }
@@ -66,7 +66,7 @@ namespace BlackCore
bool CWebReaderFlags::isFromSwiftDb(WebReader reader)
{
return reader.testFlag(ModelReader) || reader.testFlag(IcaoDataReader) || reader.testFlag(InfoDataReader);
return reader.testFlag(ModelReader) || reader.testFlag(IcaoDataReader) || reader.testFlag(DbInfoDataReader);
}
} // namespace

View File

@@ -37,9 +37,9 @@ namespace BlackCore
IcaoDataReader = 1 << 4, //!< reader for ICAO data
ModelReader = 1 << 5, //!< reader for model data such as liveries, models, etc
AirportReader = 1 << 6, //!< reader for airport list
InfoDataReader = 1 << 7, //!< DB info data (metdata, how many data, when updated)
DbInfoDataReader = 1 << 7, //!< DB info data (metdata, how many data, when updated)
AllVatsimReaders = VatsimBookingReader | VatsimDataReader | VatsimMetarReader | VatsimStatusReader, //!< all VATSIM readers
AllSwiftDbReaders = IcaoDataReader | ModelReader | InfoDataReader | AirportReader, //!< all swift data
AllSwiftDbReaders = IcaoDataReader | ModelReader | DbInfoDataReader | AirportReader, //!< all swift data
AllReaders = AllSwiftDbReaders | AllVatsimReaders //!< everything
};
Q_DECLARE_FLAGS(WebReader, WebReaderFlag)