refs #748 Move CAirportDataReader to the db/ subdirectory

* BlackCore::CAirportDataReader -> BlackCore::Db::CAirportDataReader
* fix typo in CDatabaseReader
This commit is contained in:
Michał Garapich
2016-09-04 22:19:46 +02:00
committed by Mathew Sutcliffe
parent 30e3ce2dbf
commit a4b5b28cc1
16 changed files with 258 additions and 211 deletions

View File

@@ -1,117 +0,0 @@
/* Copyright (C) 2015
* swift project Community / Contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
#include "airportdatareader.h"
#include "blackcore/application.h"
#include "blackmisc/logmessage.h"
#include "blackmisc/network/networkutils.h"
#include <QNetworkReply>
using namespace BlackMisc;
using namespace BlackMisc::Aviation;
using namespace BlackMisc::Network;
namespace BlackCore
{
CAirportDataReader::CAirportDataReader(QObject* parent) :
CThreadedReader(parent, QStringLiteral("CAirportDataReader"))
{
// void
}
void CAirportDataReader::readInBackgroundThread()
{
bool s = QMetaObject::invokeMethod(this, "ps_readAirports");
Q_ASSERT_X(s, Q_FUNC_INFO, "Cannot invoke ");
Q_UNUSED(s);
}
BlackMisc::Aviation::CAirportList CAirportDataReader::getAirports() const
{
return m_airportCache.get();
}
CUrl CAirportDataReader::getAirportsUrl() const
{
const CUrl url(sApp->getGlobalSetup().getSwiftAirportUrls().getRandomWorkingUrl());
return url;
}
void CAirportDataReader::ps_parseAirportData(QNetworkReply *nwReply)
{
QJsonParseError error;
QByteArray data = nwReply->readAll();
QJsonDocument document = QJsonDocument::fromJson(data, &error);
if (error.error != QJsonParseError::NoError)
{
CLogMessage(this).error("Error parsing airport list from JSON (%1)") << error.errorString();
return;
}
QJsonArray array = document.array();
if (array.isEmpty())
{
CLogMessage(this).error("Error parsing airport list from JSON (document is not an array)");
return;
}
CAirportList airports;
airports.convertFromDatabaseJson(array);
quint64 timestamp = lastModifiedMsSinceEpoch(nwReply);
{
QWriteLocker wl(&this->m_lock);
m_airportCache.set(airports, timestamp);
}
emit dataRead(CEntityFlags::AirportEntity, CEntityFlags::ReadFinished, airports.size());
}
void CAirportDataReader::ps_parseAirportHeader(QNetworkReply *nwReply)
{
this->threadAssertCheck();
m_lastModified = lastModifiedMsSinceEpoch(nwReply);
ps_readAirports();
}
void CAirportDataReader::ps_readAirports()
{
this->threadAssertCheck();
Q_ASSERT_X(sApp, Q_FUNC_INFO, "No Application");
CFailoverUrlList urls(sApp->getGlobalSetup().getSwiftAirportUrls());
const CUrl url(urls.obtainNextWorkingUrl(true));
if (url.isEmpty()) { return; }
if (0 == m_lastModified) {
sApp->headerFromNetwork(url, { this, &CAirportDataReader::ps_parseAirportHeader });
return;
}
m_airportCache.synchronize();
int size = m_airportCache.get().size();
if (size > 0 &&
m_airportCache.getAvailableTimestamp().toMSecsSinceEpoch() >= static_cast<qint64>(m_lastModified)) // cache is up-to-date
{
CLogMessage(this).info("Loaded %1 airports from cache") << m_airportCache.get().size();
emit dataRead(CEntityFlags::AirportEntity, CEntityFlags::ReadFinished, size);
}
else
{
sApp->getFromNetwork(url, { this, &CAirportDataReader::ps_parseAirportData });
}
}
void CAirportDataReader::ps_airportCacheChanged()
{
// void
}
} // ns

View File

@@ -1,71 +0,0 @@
/* Copyright (C) 2015
* swift project Community / Contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
//! \file
#ifndef BLACKCORE_AIRPORTDATAREADER_H
#define BLACKCORE_AIRPORTDATAREADER_H
#include "blackcore/blackcoreexport.h"
#include "blackcore/threadedreader.h"
#include "blackcore/data/dbcaches.h"
#include "blackmisc/aviation/airportlist.h"
#include "blackmisc/network/entityflags.h"
#include <QNetworkAccessManager>
namespace BlackCore
{
/**
* Reader for airport database.
*/
class BLACKCORE_EXPORT CAirportDataReader : public CThreadedReader
{
Q_OBJECT
signals:
//! Emitted when data is parsed
void dataRead(BlackMisc::Network::CEntityFlags::Entity entity, BlackMisc::Network::CEntityFlags::ReadState state, int number);
public:
//! Constructor
CAirportDataReader(QObject* parent);
//! Read airports
void readInBackgroundThread();
//! Returns a list of all airports in the database.
//! \threadsafe
BlackMisc::Aviation::CAirportList getAirports() const;
private:
//! URL for airport list
BlackMisc::Network::CUrl getAirportsUrl() const;
private slots:
//! Parse downloaded JSON file
void ps_parseAirportData(QNetworkReply *nwReply);
//! Read Last-Modified header
void ps_parseAirportHeader(QNetworkReply *nwReply);
//! Read airports
void ps_readAirports();
//! Airport cache changed
void ps_airportCacheChanged();
private:
BlackMisc::CData<BlackCore::Data::TDbAirportCache> m_airportCache {this, &CAirportDataReader::ps_airportCacheChanged};
mutable QReadWriteLock m_lock;
quint64 m_lastModified = 0; //!< When was data file updated, obtained from HTTP Last-Modified header, in ms from epoch
};
} // ns
#endif // guard

View File

@@ -0,0 +1,145 @@
/* Copyright (C) 2015
* swift project Community / Contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
#include "airportdatareader.h"
#include "blackcore/application.h"
#include "blackmisc/logmessage.h"
#include "blackmisc/network/networkutils.h"
#include <QNetworkReply>
using namespace BlackMisc;
using namespace BlackMisc::Aviation;
using namespace BlackMisc::Network;
namespace BlackCore
{
namespace Db
{
CAirportDataReader::CAirportDataReader(QObject* parent, const CDatabaseReaderConfigList &config) :
CDatabaseReader(parent, config, QStringLiteral("CAirportDataReader"))
{
// void
}
void CAirportDataReader::readInBackgroundThread()
{
bool s = QMetaObject::invokeMethod(this, "ps_readAirports");
Q_ASSERT_X(s, Q_FUNC_INFO, "Cannot invoke ");
Q_UNUSED(s);
}
BlackMisc::Aviation::CAirportList CAirportDataReader::getAirports() const
{
return m_airportCache.get();
}
QDateTime CAirportDataReader::getCacheTimestamp(CEntityFlags::Entity entities) const
{
return entities == CEntityFlags::AirportEntity ? m_airportCache.getAvailableTimestamp() : QDateTime();
}
int CAirportDataReader::getCacheCount(CEntityFlags::Entity entity) const
{
return entity == CEntityFlags::AirportEntity ? m_airportCache.get().size() : 0;
}
void CAirportDataReader::synchronizeCaches(CEntityFlags::Entity entities)
{
if (entities.testFlag(CEntityFlags::AirportEntity)) { this->m_airportCache.synchronize(); }
}
void CAirportDataReader::invalidateCaches(CEntityFlags::Entity entities)
{
if (entities.testFlag(CEntityFlags::AirportEntity)) { CDataCache::instance()->clearAllValues(this->m_airportCache.getKey()); }
}
bool CAirportDataReader::hasChangedUrl(CEntityFlags::Entity entity) const
{
// TODO
return false;
}
CUrl CAirportDataReader::getAirportsUrl() const
{
const CUrl url(sApp->getGlobalSetup().getSwiftAirportUrls().getRandomWorkingUrl());
return url;
}
void CAirportDataReader::ps_parseAirportData(QNetworkReply *nwReply)
{
QJsonParseError error;
QByteArray data = nwReply->readAll();
QJsonDocument document = QJsonDocument::fromJson(data, &error);
if (error.error != QJsonParseError::NoError)
{
CLogMessage(this).error("Error parsing airport list from JSON (%1)") << error.errorString();
return;
}
QJsonArray array = document.array();
if (array.isEmpty())
{
CLogMessage(this).error("Error parsing airport list from JSON (document is not an array)");
return;
}
CAirportList airports;
airports.convertFromDatabaseJson(array);
quint64 timestamp = lastModifiedMsSinceEpoch(nwReply);
{
QWriteLocker wl(&this->m_lock);
m_airportCache.set(airports, timestamp);
}
emit dataRead(CEntityFlags::AirportEntity, CEntityFlags::ReadFinished, airports.size());
}
void CAirportDataReader::ps_parseAirportHeader(QNetworkReply *nwReply)
{
this->threadAssertCheck();
m_lastModified = lastModifiedMsSinceEpoch(nwReply);
ps_readAirports();
}
void CAirportDataReader::ps_readAirports()
{
this->threadAssertCheck();
Q_ASSERT_X(sApp, Q_FUNC_INFO, "No Application");
CFailoverUrlList urls(sApp->getGlobalSetup().getSwiftAirportUrls());
const CUrl url(urls.obtainNextWorkingUrl(true));
if (url.isEmpty()) { return; }
if (0 == m_lastModified) {
sApp->headerFromNetwork(url, { this, &CAirportDataReader::ps_parseAirportHeader });
return;
}
m_airportCache.synchronize();
int size = m_airportCache.get().size();
if (size > 0 &&
m_airportCache.getAvailableTimestamp().toMSecsSinceEpoch() >= static_cast<qint64>(m_lastModified)) // cache is up-to-date
{
CLogMessage(this).info("Loaded %1 airports from cache") << m_airportCache.get().size();
emit dataRead(CEntityFlags::AirportEntity, CEntityFlags::ReadFinished, size);
}
else
{
sApp->getFromNetwork(url, { this, &CAirportDataReader::ps_parseAirportData });
}
}
void CAirportDataReader::ps_airportCacheChanged()
{
// void
}
} // ns
} // ns

View File

@@ -0,0 +1,90 @@
/* Copyright (C) 2015
* swift project Community / Contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
//! \file
#ifndef BLACKCORE_AIRPORTDATAREADER_H
#define BLACKCORE_AIRPORTDATAREADER_H
#include "blackcore/blackcoreexport.h"
#include "blackcore/data/dbcaches.h"
#include "blackcore/db/databasereader.h"
#include "blackmisc/aviation/airportlist.h"
#include "blackmisc/network/entityflags.h"
#include <QNetworkAccessManager>
namespace BlackCore
{
namespace Db
{
/**
* Reader for airport database.
*/
class BLACKCORE_EXPORT CAirportDataReader : public CDatabaseReader
{
Q_OBJECT
signals:
//! Emitted when data is parsed
void dataRead(BlackMisc::Network::CEntityFlags::Entity entity, BlackMisc::Network::CEntityFlags::ReadState state, int number);
public:
//! Constructor
CAirportDataReader(QObject* parent, const CDatabaseReaderConfigList &config);
//! Read airports
void readInBackgroundThread();
//! Returns a list of all airports in the database.
//! \threadsafe
BlackMisc::Aviation::CAirportList getAirports() const;
//! \copydoc BlackCore::Db::CDatabaseReader::getCacheTimestamp()
QDateTime getCacheTimestamp(BlackMisc::Network::CEntityFlags::Entity entities) const override;
//! \copydoc BlackCore::Db::CDatabaseReader:;getCacheCount()
int getCacheCount(BlackMisc::Network::CEntityFlags::Entity entity) const override;
protected:
//! \copydoc BlackCore::Db::CDatabaseReader::syncronizeCaches()
void synchronizeCaches(BlackMisc::Network::CEntityFlags::Entity entities) override;
//! \copydoc BlackCore::Db::CDatabaseReader::invalidateCaches()
void invalidateCaches(BlackMisc::Network::CEntityFlags::Entity entities) override;
//! \copydoc BlackCore::Db::CDatabaseReader::hasChangedUrl()
bool hasChangedUrl(BlackMisc::Network::CEntityFlags::Entity entity) const override;
private:
//! URL for airport list
BlackMisc::Network::CUrl getAirportsUrl() const;
private slots:
//! Parse downloaded JSON file
void ps_parseAirportData(QNetworkReply *nwReply);
//! Read Last-Modified header
void ps_parseAirportHeader(QNetworkReply *nwReply);
//! Read airports
void ps_readAirports();
//! Airport cache changed
void ps_airportCacheChanged();
private:
BlackMisc::CData<BlackCore::Data::TDbAirportCache> m_airportCache {this, &CAirportDataReader::ps_airportCacheChanged};
mutable QReadWriteLock m_lock;
quint64 m_lastModified = 0; //!< When was data file updated, obtained from HTTP Last-Modified header, in ms from epoch
};
}
} // ns
#endif // guard

View File

@@ -68,7 +68,7 @@ namespace BlackCore
Q_ASSERT_X(latestEntityTimestamp >= 0, Q_FUNC_INFO, "Missing timestamp");
if (!changedUrl && cacheTimestamp >= latestEntityTimestamp && cacheTimestamp >= 0 && latestEntityTimestamp >= 0)
{
this->syncronizeCaches(currentEntity);
this->synchronizeCaches(currentEntity);
entities &= ~currentEntity; // do not load from web
cachedEntities |= currentEntity; // read from cache
CLogMessage(this).info("Using cache for %1 (%2, %3)") << currentEntityName << cacheTs.toString() << cacheTimestamp;
@@ -88,7 +88,7 @@ namespace BlackCore
else
{
// no info objects, server down
this->syncronizeCaches(currentEntity);
this->synchronizeCaches(currentEntity);
const int c = this->getCacheCount(currentEntity);
CLogMessage(this).info("No info object for %1, using cache with %2 objects") << currentEntityName << c;
entities &= ~currentEntity; // do not load from web

View File

@@ -179,8 +179,8 @@ namespace BlackCore
//! \name Cache access
//! @{
//! Syncronize caches for given entities
virtual void syncronizeCaches(BlackMisc::Network::CEntityFlags::Entity entities) = 0;
//! Synchronize caches for given entities
virtual void synchronizeCaches(BlackMisc::Network::CEntityFlags::Entity entities) = 0;
//! Invalidate the caches for given entities
virtual void invalidateCaches(BlackMisc::Network::CEntityFlags::Entity entities) = 0;

View File

@@ -393,7 +393,7 @@ namespace BlackCore
return true;
}
void CIcaoDataReader::syncronizeCaches(CEntityFlags::Entity entities)
void CIcaoDataReader::synchronizeCaches(CEntityFlags::Entity entities)
{
if (entities.testFlag(CEntityFlags::AircraftIcaoEntity)) { this->m_aircraftIcaoCache.synchronize(); }
if (entities.testFlag(CEntityFlags::AirlineIcaoEntity)) { this->m_airlineIcaoCache.synchronize(); }

View File

@@ -117,7 +117,7 @@ namespace BlackCore
// cache handling for base class
virtual QDateTime getCacheTimestamp(BlackMisc::Network::CEntityFlags::Entity entity) const override;
virtual int getCacheCount(BlackMisc::Network::CEntityFlags::Entity entity) const override;
virtual void syncronizeCaches(BlackMisc::Network::CEntityFlags::Entity entities) override;
virtual void synchronizeCaches(BlackMisc::Network::CEntityFlags::Entity entities) override;
protected:
// cache handling for base class

View File

@@ -50,7 +50,7 @@ namespace BlackCore
return getDbInfoObjectCount() > 4;
}
void CInfoDataReader::syncronizeCaches(CEntityFlags::Entity entities)
void CInfoDataReader::synchronizeCaches(CEntityFlags::Entity entities)
{
// no caching used here
Q_UNUSED(entities);

View File

@@ -58,7 +58,7 @@ namespace BlackCore
protected:
// cache handling for base class
virtual void syncronizeCaches(BlackMisc::Network::CEntityFlags::Entity entities) override;
virtual void synchronizeCaches(BlackMisc::Network::CEntityFlags::Entity entities) override;
virtual void invalidateCaches(BlackMisc::Network::CEntityFlags::Entity entities) override;
virtual bool hasChangedUrl(BlackMisc::Network::CEntityFlags::Entity entity) const override;

View File

@@ -466,7 +466,7 @@ namespace BlackCore
return true;
}
void CModelDataReader::syncronizeCaches(CEntityFlags::Entity entities)
void CModelDataReader::synchronizeCaches(CEntityFlags::Entity entities)
{
if (entities.testFlag(CEntityFlags::LiveryEntity)) { this->m_liveryCache.synchronize(); }
if (entities.testFlag(CEntityFlags::ModelEntity)) { this->m_modelCache.synchronize(); }

View File

@@ -127,7 +127,7 @@ namespace BlackCore
// cache handling for base class
virtual QDateTime getCacheTimestamp(BlackMisc::Network::CEntityFlags::Entity entity) const override;
virtual int getCacheCount(BlackMisc::Network::CEntityFlags::Entity entity) const override;
virtual void syncronizeCaches(BlackMisc::Network::CEntityFlags::Entity entities) override;
virtual void synchronizeCaches(BlackMisc::Network::CEntityFlags::Entity entities) override;
protected:
// cache handling for base class

View File

@@ -7,9 +7,9 @@
* contained in the LICENSE file.
*/
#include "blackcore/airportdatareader.h"
#include "blackcore/application.h"
#include "blackcore/data/globalsetup.h"
#include "blackcore/db/airportdatareader.h"
#include "blackcore/db/infodatareader.h"
#include "blackcore/db/icaodatareader.h"
#include "blackcore/db/databasewriter.h"
@@ -172,8 +172,8 @@ namespace BlackCore
void CWebDataServices::syncronizeDbCaches(CEntityFlags::Entity entities)
{
if (this->m_modelDataReader) { this->m_modelDataReader->syncronizeCaches(entities); }
if (this->m_icaoDataReader) { this->m_icaoDataReader->syncronizeCaches(entities); }
if (this->m_modelDataReader) { this->m_modelDataReader->synchronizeCaches(entities); }
if (this->m_icaoDataReader) { this->m_icaoDataReader->synchronizeCaches(entities); }
}
CEntityFlags::Entity CWebDataServices::triggerRead(CEntityFlags::Entity whatToRead, const QDateTime &newerThan)
@@ -688,7 +688,7 @@ namespace BlackCore
// 6. Airport list reader
if (flags.testFlag(CWebReaderFlags::WebReaderFlag::AirportReader))
{
this->m_airportDataReader = new CAirportDataReader(this);
this->m_airportDataReader = new CAirportDataReader(this, dbReaderConfig);
c = connect(this->m_airportDataReader, &CAirportDataReader::dataRead, this, &CWebDataServices::ps_readFromSwiftDb);
Q_ASSERT_X(c, Q_FUNC_INFO, "Airport reader signals");
c = connect(this->m_airportDataReader, &CAirportDataReader::dataRead, this, &CWebDataServices::dataRead);

View File

@@ -57,7 +57,7 @@ namespace BlackMisc
namespace BlackCore
{
class CApplication;
class CAirportDataReader;
namespace Vatsim
{
class CVatsimBookingReader;
@@ -68,6 +68,7 @@ namespace BlackCore
namespace Db
{
class CAirportDataReader;
class CDatabaseWriter;
class CDatabaseReader;
class CIcaoDataReader;
@@ -390,7 +391,7 @@ namespace BlackCore
Db::CIcaoDataReader *m_icaoDataReader = nullptr;
Db::CModelDataReader *m_modelDataReader = nullptr;
Db::CInfoDataReader *m_infoDataReader = nullptr;
CAirportDataReader *m_airportDataReader = nullptr;
Db::CAirportDataReader *m_airportDataReader = nullptr;
// writing objects directly into DB
Db::CDatabaseWriter *m_databaseWriter = nullptr;

View File

@@ -13,8 +13,8 @@
#include "testreaders.h"
#include "blackcore/application.h"
#include "blackcore/airportdatareader.h"
#include "blackcore/data/globalsetup.h"
#include "blackcore/db/airportdatareader.h"
#include "blackcore/db/icaodatareader.h"
#include "blackcore/db/modeldatareader.h"
#include "blackmisc/aviation/aircrafticaocode.h"
@@ -45,7 +45,7 @@ namespace BlackCoreTest
{
CTestReaders::CTestReaders(QObject *parent) :
QObject(parent),
m_airportReader(new CAirportDataReader(this)),
m_airportReader(new CAirportDataReader(this, CDatabaseReaderConfigList::allDirectDbAccess())),
m_icaoReader(new CIcaoDataReader(this, CDatabaseReaderConfigList::allDirectDbAccess())),
m_modelReader(new CModelDataReader(this, CDatabaseReaderConfigList::allDirectDbAccess()))
{ }

View File

@@ -22,11 +22,10 @@ namespace BlackCore
{
namespace Db
{
class CAirportDataReader;
class CIcaoDataReader;
class CModelDataReader;
}
class CAirportDataReader;
}
namespace BlackCoreTest
@@ -56,9 +55,9 @@ namespace BlackCoreTest
void readAirportData();
private:
BlackCore::CAirportDataReader *m_airportReader = nullptr;
BlackCore::Db::CIcaoDataReader *m_icaoReader = nullptr;
BlackCore::Db::CModelDataReader *m_modelReader = nullptr;
BlackCore::Db::CAirportDataReader *m_airportReader = nullptr;
BlackCore::Db::CIcaoDataReader *m_icaoReader = nullptr;
BlackCore::Db::CModelDataReader *m_modelReader = nullptr;
//! Test if server is available
static bool pingServer(const BlackMisc::Network::CUrl &url);