refs #478, use data cache in readers

* URLs no longer have to be passed
* watchdog for DB readers to check DB status

In same step:
* fixed some log messages and comments
* allow to self signed SSL certificates
* adjusted namespace for CNetworkUtils (now in network)
This commit is contained in:
Klaus Basan
2015-10-14 02:36:14 +02:00
committed by Mathew Sutcliffe
parent 4fce848c59
commit 53ba50dd3a
18 changed files with 281 additions and 178 deletions

View File

@@ -8,6 +8,7 @@
*/
#include "databasereader.h"
#include "blackmisc/network/networkutils.h"
#include "blackmisc/logmessage.h"
#include "blackmisc/datastoreutility.h"
#include <QJsonDocument>
@@ -19,11 +20,14 @@ namespace BlackCore
{
CDatabaseReader::CDatabaseReader(QObject *owner, const QString &name) :
BlackMisc::CThreadedReader(owner, name)
{ }
{
connect(&m_watchdogTimer, &QTimer::timeout, this, &CDatabaseReader::ps_watchdog);
}
void CDatabaseReader::readInBackgroundThread(CEntityFlags::Entity entities)
{
if (m_shutdown) { return; }
this->m_watchdogTimer.stop();
bool s = QMetaObject::invokeMethod(this, "ps_read", Q_ARG(BlackMisc::Network::CEntityFlags::Entity, entities));
Q_ASSERT_X(s, Q_FUNC_INFO, "Invoke failed");
Q_UNUSED(s);
@@ -35,7 +39,6 @@ namespace BlackCore
JsonDatastoreResponse datastoreResponse;
if (m_shutdown || this->isFinished())
{
CLogMessage(this).debug() << Q_FUNC_INFO;
CLogMessage(this).info("Terminated data parsing process"); // for users
nwReply->abort();
return datastoreResponse; // stop, terminate straight away, ending thread
@@ -72,10 +75,85 @@ namespace BlackCore
return datastoreResponse;
}
CDatabaseReader::JsonDatastoreResponse CDatabaseReader::setStatusAndTransformReplyIntoDatastoreResponse(QNetworkReply *nwReply)
{
setConnectionStatus(nwReply);
return transformReplyIntoDatastoreResponse(nwReply);
}
void CDatabaseReader::setWatchdogUrl(const CUrl &url)
{
bool start;
{
QWriteLocker wl(&this->m_watchdogLock);
m_watchdogUrl = url;
start = url.isEmpty();
}
if (start)
{
m_watchdogTimer.start(30 * 1000);
}
else
{
m_watchdogTimer.stop();
}
}
bool CDatabaseReader::canConnect() const
{
QReadLocker rl(&this->m_watchdogLock);
return m_canConnect;
}
bool CDatabaseReader::canConnect(QString &message) const
{
QReadLocker rl(&this->m_watchdogLock);
message = m_watchdogMessage;
return m_canConnect;
}
void CDatabaseReader::setConnectionStatus(bool ok, const QString &message)
{
{
QWriteLocker wl(&this->m_watchdogLock);
this->m_watchdogMessage = message;
this->m_canConnect = ok;
if (this->m_watchdogUrl.isEmpty()) { return; }
}
this->m_updateTimer->start(); // restart
}
void CDatabaseReader::setConnectionStatus(QNetworkReply *nwReply)
{
Q_ASSERT_X(nwReply, Q_FUNC_INFO, "Missing network reply");
if (nwReply->isFinished())
{
if (nwReply->error() == QNetworkReply::NoError)
{
setConnectionStatus(true);
}
else
{
setConnectionStatus(false, nwReply->errorString());
}
}
}
void CDatabaseReader::ps_watchdog()
{
CUrl url;
{
QReadLocker rl(&this->m_watchdogLock);
url = this->m_watchdogUrl;
}
if (url.isEmpty())
{
this->m_watchdogTimer.stop();
return;
}
QString m;
return canConnect(m);
bool ok = CNetworkUtils::canConnect(url, m);
this->setConnectionStatus(ok, m);
}
} // namespace

View File

@@ -18,6 +18,8 @@
#include <QNetworkReply>
#include <QJsonArray>
#include <QDateTime>
#include <QTimer>
namespace BlackCore
{
@@ -57,18 +59,46 @@ namespace BlackCore
void readInBackgroundThread(BlackMisc::Network::CEntityFlags::Entity entities);
//! Can connect to DB
//! \threadsafe
bool canConnect() const;
//! Can connect to server?
//! \return message why connect failed
virtual bool canConnect(QString &message) const = 0;
//! \threadsafe
bool canConnect(QString &message) const;
protected:
BlackMisc::Network::CUrl m_watchdogUrl; //!< URL for checking if alive
QTimer m_watchdogTimer { this }; //!< Timer for watchdog
QString m_watchdogMessage; //!< Returned status message
bool m_canConnect = false; //!< Successful connection?
mutable QReadWriteLock m_watchdogLock; //!< Lock
//! Constructor
CDatabaseReader(QObject *owner, const QString &name);
//! Watchdog URL, empty means no checking
//! \threadsafe
void setWatchdogUrl(const BlackMisc::Network::CUrl &url);
//! Check if terminated or error, otherwise split into array of objects
CDatabaseReader::JsonDatastoreResponse setStatusAndTransformReplyIntoDatastoreResponse(QNetworkReply *nwReply);
private slots:
//! Watchdog
void ps_watchdog();
private:
//! Check if terminated or error, otherwise split into array of objects
JsonDatastoreResponse transformReplyIntoDatastoreResponse(QNetworkReply *nwReply) const;
//! Feedback about connection status
//! \threadsafe
void setConnectionStatus(bool ok, const QString &message = "");
//! Feedback about connection status
//! \threadsafe
void setConnectionStatus(QNetworkReply *nwReply);
};
} // namespace

View File

@@ -10,7 +10,8 @@
#include "databasewriter.h"
#include "blackmisc/logmessage.h"
#include "blackmisc/datastoreutility.h"
#include "blackmisc/networkutils.h"
#include "blackmisc/network/networkutils.h"
#include "blackmisc/project.h"
#include <QUrlQuery>
#include <QJsonDocument>
#include <QHttpPart>
@@ -21,9 +22,9 @@ using namespace BlackMisc::Simulation;
namespace BlackCore
{
CDatabaseWriter::CDatabaseWriter(const QString &protocol, const QString &server, const QString &baseUrl, QObject *parent) :
CDatabaseWriter::CDatabaseWriter(const Network::CUrl &baseUrl, QObject *parent) :
QObject(parent),
m_modelUrl(getModelWriteUrl(protocol, server, baseUrl))
m_modelUrl(getModelWriteUrl(baseUrl))
{
this->m_networkManager = new QNetworkAccessManager(this);
this->connect(this->m_networkManager, &QNetworkAccessManager::finished, this, &CDatabaseWriter::ps_postResponse);
@@ -44,7 +45,7 @@ namespace BlackCore
return msg;
}
QUrl url(m_modelUrl);
QUrl url(m_modelUrl.toQUrl());
QNetworkRequest request(url);
const QByteArray jsonData(QJsonDocument(model.toJson()).toJson(QJsonDocument::Compact));
QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
@@ -54,7 +55,7 @@ namespace BlackCore
textPart.setBody(jsonData);
multiPart->append(textPart);
if (m_phpDebug)
if (m_phpDebug && CProject::isRunningInDeveloperEnvironment())
{
QHttpPart textPartDebug;
textPartDebug.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"XDEBUG_SESSION_START\""));
@@ -113,9 +114,9 @@ namespace BlackCore
}
}
QString CDatabaseWriter::getModelWriteUrl(const QString &protocol, const QString &server, const QString &baseUrl)
Network::CUrl CDatabaseWriter::getModelWriteUrl(const Network::CUrl &baseUrl)
{
return CNetworkUtils::buildUrl(protocol, server, baseUrl, "service/swiftwritemodel.php");
return baseUrl.withAppendedPath("service/swiftwritemodel.php");
}
QList<QByteArray> CDatabaseWriter::splitData(const QByteArray &data, int size)

View File

@@ -29,7 +29,7 @@ namespace BlackCore
public:
//! Constructor
CDatabaseWriter(const QString &protocol, const QString &server, const QString &baseUrl, QObject *parent);
CDatabaseWriter(const BlackMisc::Network::CUrl &baseUrl, QObject *parent);
//! Write model to DB
BlackMisc::CStatusMessageList asyncWriteModel(const BlackMisc::Simulation::CAircraftModel &model);
@@ -42,14 +42,14 @@ namespace BlackCore
void ps_postResponse(QNetworkReply *nwReplyPtr);
private:
QString m_modelUrl;
BlackMisc::Network::CUrl m_modelUrl;
QNetworkAccessManager *m_networkManager = nullptr;
QNetworkReply *m_pendingReply = nullptr;
bool m_shutdown = false;
bool m_phpDebug = true;
//! URL model web service
static QString getModelWriteUrl(const QString &protocol, const QString &server, const QString &baseUrl);
static BlackMisc::Network::CUrl getModelWriteUrl(const BlackMisc::Network::CUrl &baseUrl);
//! Split data array
static QList<QByteArray> splitData(const QByteArray &data, int size);

View File

@@ -7,9 +7,10 @@
* contained in the LICENSE file.
*/
#include "blackcore/setupreader.h"
#include "blackmisc/sequence.h"
#include "blackmisc/logmessage.h"
#include "blackmisc/networkutils.h"
#include "blackmisc/network/networkutils.h"
#include "blackmisc/fileutilities.h"
#include "blackmisc/json.h"
#include "icaodatareader.h"
@@ -21,14 +22,12 @@
using namespace BlackMisc;
using namespace BlackMisc::Aviation;
using namespace BlackMisc::Network;
using namespace BlackCore::Data;
namespace BlackCore
{
CIcaoDataReader::CIcaoDataReader(QObject *owner, const QString &protocol, const QString &server, const QString &baseUrl) :
CDatabaseReader(owner, "CIcaoDataReader"),
m_urlAircraftIcao(getAircraftIcaoUrl(protocol, server, baseUrl)),
m_urlAirlineIcao(getAirlineIcaoUrl(protocol, server, baseUrl)),
m_urlCountry(getCountryUrl(protocol, server, baseUrl))
CIcaoDataReader::CIcaoDataReader(QObject *owner) :
CDatabaseReader(owner, "CIcaoDataReader")
{
this->m_networkManagerAircraft = new QNetworkAccessManager(this);
this->m_networkManagerAirlines = new QNetworkAccessManager(this);
@@ -167,28 +166,31 @@ namespace BlackCore
Q_ASSERT(this->m_networkManagerAircraft);
Q_ASSERT(this->m_networkManagerAirlines);
Q_ASSERT(this->m_networkManagerCountries);
Q_ASSERT(!m_urlAircraftIcao.isEmpty());
Q_ASSERT(!m_urlAirlineIcao.isEmpty());
Q_ASSERT(!m_urlCountry.isEmpty());
CEntityFlags::Entity entitiesTriggered = CEntityFlags::NoEntity;
if (entities.testFlag(CEntityFlags::AircraftIcaoEntity))
{
QNetworkRequest requestAircraft(m_urlAircraftIcao);
QUrl url(getAircraftIcaoUrl());
QNetworkRequest requestAircraft(url);
CNetworkUtils::ignoreSslVerification(requestAircraft);
this->m_networkManagerAircraft->get(requestAircraft);
entitiesTriggered |= CEntityFlags::AircraftIcaoEntity;
}
if (entities.testFlag(CEntityFlags::AirlineIcaoEntity))
{
QNetworkRequest requestAirline(m_urlAirlineIcao);
QUrl url(getAirlineIcaoUrl());
QNetworkRequest requestAirline(url);
CNetworkUtils::ignoreSslVerification(requestAirline);
this->m_networkManagerAirlines->get(requestAirline);
entitiesTriggered |= CEntityFlags::AirlineIcaoEntity;
}
if (entities.testFlag(CEntityFlags::CountryEntity))
{
QNetworkRequest requestCountry(m_urlCountry);
QUrl url(getCountryUrl());
QNetworkRequest requestCountry(url);
CNetworkUtils::ignoreSslVerification(requestCountry);
this->m_networkManagerCountries->get(requestCountry);
entitiesTriggered |= CEntityFlags::CountryEntity;
}
@@ -196,12 +198,19 @@ namespace BlackCore
emit dataRead(entitiesTriggered, CEntityFlags::StartRead, 0);
}
CUrl CIcaoDataReader::getBaseUrl() const
{
CUrl baseUrl(this->m_setup.get().dbIcaoReader());
Q_ASSERT_X(!baseUrl.isEmpty(), Q_FUNC_INFO, "No URL");
return baseUrl;
}
void CIcaoDataReader::ps_parseAircraftIcaoData(QNetworkReply *nwReplyPtr)
{
// wrap pointer, make sure any exit cleans up reply
// required to use delete later as object is created in a different thread
QScopedPointer<QNetworkReply, QScopedPointerDeleteLater> nwReply(nwReplyPtr);
QJsonArray array = this->transformReplyIntoDatastoreResponse(nwReply.data());
QJsonArray array = this->setStatusAndTransformReplyIntoDatastoreResponse(nwReply.data());
if (array.isEmpty())
{
emit dataRead(CEntityFlags::AircraftIcaoEntity, CEntityFlags::ReadFailed, 0);
@@ -221,7 +230,7 @@ namespace BlackCore
void CIcaoDataReader::ps_parseAirlineIcaoData(QNetworkReply *nwReplyPtr)
{
QScopedPointer<QNetworkReply, QScopedPointerDeleteLater> nwReply(nwReplyPtr);
QJsonArray array = this->transformReplyIntoDatastoreResponse(nwReply.data());
QJsonArray array = this->setStatusAndTransformReplyIntoDatastoreResponse(nwReply.data());
if (array.isEmpty())
{
emit dataRead(CEntityFlags::AirlineIcaoEntity, CEntityFlags::ReadFailed, 0);
@@ -241,7 +250,7 @@ namespace BlackCore
void CIcaoDataReader::ps_parseCountryData(QNetworkReply *nwReplyPtr)
{
QScopedPointer<QNetworkReply, QScopedPointerDeleteLater> nwReply(nwReplyPtr);
QJsonArray array = this->transformReplyIntoDatastoreResponse(nwReply.data());
QJsonArray array = this->setStatusAndTransformReplyIntoDatastoreResponse(nwReply.data());
if (array.isEmpty())
{
emit dataRead(CEntityFlags::CountryEntity, CEntityFlags::ReadFailed, 0);
@@ -258,15 +267,6 @@ namespace BlackCore
emit dataRead(CEntityFlags::CountryEntity, CEntityFlags::ReadFinished, n);
}
bool CIcaoDataReader::canConnect(QString &message) const
{
if (m_urlAircraftIcao.isEmpty() || m_urlAirlineIcao.isEmpty()) { return false; }
bool cm = CNetworkUtils::canConnect(m_urlAircraftIcao, message);
// currently only testing one URL, might be changed in the future
return cm;
}
bool CIcaoDataReader::readFromJsonFiles(const QString &dir, CEntityFlags::Entity whatToRead)
{
QDir directory(dir);
@@ -365,19 +365,19 @@ namespace BlackCore
return true;
}
QString CIcaoDataReader::getAircraftIcaoUrl(const QString &protocol, const QString &server, const QString &baseUrl)
CUrl CIcaoDataReader::getAircraftIcaoUrl() const
{
return CNetworkUtils::buildUrl(protocol, server, baseUrl, "service/jsonaircrafticao.php");
return getBaseUrl().withAppendedPath("service/jsonaircrafticao.php");
}
QString CIcaoDataReader::getAirlineIcaoUrl(const QString &protocol, const QString &server, const QString &baseUrl)
CUrl CIcaoDataReader::getAirlineIcaoUrl() const
{
return CNetworkUtils::buildUrl(protocol, server, baseUrl, "service/jsonairlineicao.php");
return getBaseUrl().withAppendedPath("service/jsonairlineicao.php");
}
QString CIcaoDataReader::getCountryUrl(const QString &protocol, const QString &server, const QString &baseUrl)
CUrl CIcaoDataReader::getCountryUrl() const
{
return CNetworkUtils::buildUrl(protocol, server, baseUrl, "service/jsoncountry.php");
return getBaseUrl().withAppendedPath("service/jsoncountry.php");
}
} // namespace

View File

@@ -14,6 +14,7 @@
#include "blackcore/blackcoreexport.h"
#include "blackcore/databasereader.h"
#include "blackcore/data/globalsetup.h"
#include "blackmisc/countrylist.h"
#include "blackmisc/aviation/aircrafticaocodelist.h"
#include "blackmisc/aviation/airlineicaocodelist.h"
@@ -33,7 +34,7 @@ namespace BlackCore
public:
//! Constructor
explicit CIcaoDataReader(QObject *owner, const QString &protocol, const QString &server, const QString &baseUrl);
explicit CIcaoDataReader(QObject *owner);
//! Get aircraft ICAO information
//! \threadsafe
@@ -95,12 +96,6 @@ namespace BlackCore
//! \threadsafe
bool areAllDataRead() const;
//! Can connect to server?
virtual bool canConnect(QString &message) const override;
//! \copydoc CDatabaseReader::canConnect()
using CDatabaseReader::canConnect;
//! Read from static DB data file
bool readFromJsonFiles(const QString &dir, BlackMisc::Network::CEntityFlags::Entity whatToRead = BlackMisc::Network::CEntityFlags::AllIcaoAndCountries);
@@ -128,28 +123,30 @@ namespace BlackCore
void ps_read(BlackMisc::Network::CEntityFlags::Entity entities);
private:
QNetworkAccessManager *m_networkManagerAircraft = nullptr;
QNetworkAccessManager *m_networkManagerAirlines = nullptr;
QNetworkAccessManager *m_networkManagerAircraft = nullptr;
QNetworkAccessManager *m_networkManagerAirlines = nullptr;
QNetworkAccessManager *m_networkManagerCountries = nullptr;
BlackMisc::Aviation::CAircraftIcaoCodeList m_aircraftIcaos;
BlackMisc::Aviation::CAirlineIcaoCodeList m_airlineIcaos;
BlackMisc::CCountryList m_countries;
QString m_urlAircraftIcao;
QString m_urlAirlineIcao;
QString m_urlCountry;
BlackMisc::Aviation::CAirlineIcaoCodeList m_airlineIcaos;
BlackMisc::CCountryList m_countries;
mutable QReadWriteLock m_lockAirline;
mutable QReadWriteLock m_lockAircraft;
mutable QReadWriteLock m_lockCountry;
//! URL
static QString getAircraftIcaoUrl(const QString &protocol, const QString &server, const QString &baseUrl);
BlackCore::CData<BlackCore::Data::GlobalSetup> m_setup {this}; //!< setup cache
//! Base URL
BlackMisc::Network::CUrl getBaseUrl() const;
//! URL
static QString getAirlineIcaoUrl(const QString &protocol, const QString &server, const QString &baseUrl);
BlackMisc::Network::CUrl getAircraftIcaoUrl() const;
//! URL
static QString getCountryUrl(const QString &protocol, const QString &server, const QString &baseUrl);
BlackMisc::Network::CUrl getAirlineIcaoUrl() const;
//! URL
BlackMisc::Network::CUrl getCountryUrl() const;
};
}

View File

@@ -7,9 +7,10 @@
* contained in the LICENSE file.
*/
#include "blackcore/setupreader.h"
#include "blackmisc/sequence.h"
#include "blackmisc/logmessage.h"
#include "blackmisc/networkutils.h"
#include "blackmisc/network/networkutils.h"
#include "blackmisc/fileutilities.h"
#include "modeldatareader.h"
@@ -22,14 +23,12 @@ using namespace BlackMisc;
using namespace BlackMisc::Aviation;
using namespace BlackMisc::Simulation;
using namespace BlackMisc::Network;
using namespace BlackCore::Data;
namespace BlackCore
{
CModelDataReader::CModelDataReader(QObject *owner, const QString &protocol, const QString &server, const QString &baseUrl) :
CDatabaseReader(owner, "CModelDataReader"),
m_urlLiveries(getLiveryUrl(protocol, server, baseUrl)),
m_urlDistributors(getDistributorUrl(protocol, server, baseUrl)),
m_urlModels(getModelUrl(protocol, server, baseUrl))
CModelDataReader::CModelDataReader(QObject *owner) :
CDatabaseReader(owner, "CModelDataReader")
{
this->m_networkManagerLivery = new QNetworkAccessManager(this);
this->m_networkManagerDistributor = new QNetworkAccessManager(this);
@@ -157,42 +156,34 @@ namespace BlackCore
getDistributorsCount() > 0;
}
bool CModelDataReader::canConnect(QString &message) const
{
if (m_urlDistributors.isEmpty() || m_urlLiveries.isEmpty() || m_urlModels.isEmpty()) { return false; }
bool cm = CNetworkUtils::canConnect(m_urlModels, message);
// currently only testing one URL, might be changed in the future
return cm;
}
void CModelDataReader::ps_read(CEntityFlags::Entity entity)
{
this->threadAssertCheck();
Q_ASSERT(this->m_networkManagerLivery);
Q_ASSERT(this->m_networkManagerDistributor);
Q_ASSERT(this->m_networkManagerModel);
Q_ASSERT(!m_urlLiveries.isEmpty());
Q_ASSERT(!m_urlDistributors.isEmpty());
CEntityFlags::Entity triggeredRead = CEntityFlags::NoEntity;
if (entity.testFlag(CEntityFlags::LiveryEntity))
{
QNetworkRequest requestLivery(m_urlLiveries);
QNetworkRequest requestLivery(getLiveryUrl());
CNetworkUtils::ignoreSslVerification(requestLivery);
this->m_networkManagerLivery->get(requestLivery);
triggeredRead |= CEntityFlags::LiveryEntity;
}
if (entity.testFlag(CEntityFlags::DistributorEntity))
{
QNetworkRequest requestDistributor(m_urlDistributors);
QNetworkRequest requestDistributor(getDistributorUrl());
CNetworkUtils::ignoreSslVerification(requestDistributor);
this->m_networkManagerDistributor->get(requestDistributor);
triggeredRead |= CEntityFlags::DistributorEntity;
}
if (entity.testFlag(CEntityFlags::ModelEntity))
{
QNetworkRequest requestModel(m_urlModels);
QNetworkRequest requestModel(getModelUrl());
CNetworkUtils::ignoreSslVerification(requestModel);
this->m_networkManagerModel->get(requestModel);
triggeredRead |= CEntityFlags::ModelEntity;
}
@@ -205,7 +196,7 @@ namespace BlackCore
// wrap pointer, make sure any exit cleans up reply
// required to use delete later as object is created in a different thread
QScopedPointer<QNetworkReply, QScopedPointerDeleteLater> nwReply(nwReplyPtr);
QJsonArray array = this->transformReplyIntoDatastoreResponse(nwReply.data());
QJsonArray array = this->setStatusAndTransformReplyIntoDatastoreResponse(nwReply.data());
if (array.isEmpty())
{
emit dataRead(CEntityFlags::LiveryEntity, CEntityFlags::ReadFailed, 0);
@@ -226,7 +217,7 @@ namespace BlackCore
void CModelDataReader::ps_parseDistributorData(QNetworkReply *nwReplyPtr)
{
QScopedPointer<QNetworkReply, QScopedPointerDeleteLater> nwReply(nwReplyPtr);
QJsonArray array = this->transformReplyIntoDatastoreResponse(nwReply.data());
QJsonArray array = this->setStatusAndTransformReplyIntoDatastoreResponse(nwReply.data());
if (array.isEmpty())
{
emit dataRead(CEntityFlags::DistributorEntity, CEntityFlags::ReadFailed, 0);
@@ -246,7 +237,7 @@ namespace BlackCore
void CModelDataReader::ps_parseModelData(QNetworkReply *nwReplyPtr)
{
QScopedPointer<QNetworkReply, QScopedPointerDeleteLater> nwReply(nwReplyPtr);
QJsonArray array = this->transformReplyIntoDatastoreResponse(nwReply.data());
QJsonArray array = this->setStatusAndTransformReplyIntoDatastoreResponse(nwReply.data());
if (array.isEmpty())
{
emit dataRead(CEntityFlags::ModelEntity, CEntityFlags::ReadFailed, 0);
@@ -362,19 +353,26 @@ namespace BlackCore
return true;
}
QString CModelDataReader::getLiveryUrl(const QString &protocol, const QString &server, const QString &baseUrl)
CUrl CModelDataReader::getBaseUrl() const
{
return CNetworkUtils::buildUrl(protocol, server, baseUrl, "service/jsonlivery.php");
CUrl baseUrl(m_setup.get().dbModelReader());
Q_ASSERT_X(!baseUrl.isEmpty(), Q_FUNC_INFO, "No URL");
return baseUrl;
}
QString CModelDataReader::getDistributorUrl(const QString &protocol, const QString &server, const QString &baseUrl)
CUrl CModelDataReader::getLiveryUrl() const
{
return CNetworkUtils::buildUrl(protocol, server, baseUrl, "service/jsondistributor.php");
return getBaseUrl().withAppendedPath("service/jsonlivery.php");
}
QString CModelDataReader::getModelUrl(const QString &protocol, const QString &server, const QString &baseUrl)
CUrl CModelDataReader::getDistributorUrl() const
{
return CNetworkUtils::buildUrl(protocol, server, baseUrl, "service/jsonaircraftmodel.php");
return getBaseUrl().withAppendedPath("service/jsondistributor.php");
}
CUrl CModelDataReader::getModelUrl() const
{
return getBaseUrl().withAppendedPath("service/jsonaircraftmodel.php");
}
} // namespace

View File

@@ -14,6 +14,7 @@
#include "blackcore/blackcoreexport.h"
#include "blackcore/databasereader.h"
#include "blackcore/data/globalsetup.h"
#include "blackmisc/network/webdataservicesprovider.h"
#include "blackmisc/aviation/liverylist.h"
#include "blackmisc/simulation/distributorlist.h"
@@ -33,7 +34,7 @@ namespace BlackCore
public:
//! Constructor
explicit CModelDataReader(QObject *owner, const QString &protocol, const QString &server, const QString &baseUrl);
explicit CModelDataReader(QObject *owner);
//! Get aircraft liveries
//! \threadsafe
@@ -87,13 +88,7 @@ namespace BlackCore
//! \threadsafe
bool areAllDataRead() const;
//! Can connect?
virtual bool canConnect(QString &message) const override;
//! \copydoc CDatabaseReader::canConnect()
using CDatabaseReader::canConnect;
//! Write to JSON file
//! Read to JSON file
bool readFromJsonFiles(const QString &dir, BlackMisc::Network::CEntityFlags::Entity whatToRead = BlackMisc::Network::CEntityFlags::DistributorLiveryModel);
//! Read from static DB data file
@@ -126,22 +121,27 @@ namespace BlackCore
BlackMisc::Aviation::CLiveryList m_liveries;
BlackMisc::Simulation::CDistributorList m_distributors;
BlackMisc::Simulation::CAircraftModelList m_models;
QString m_urlLiveries;
QString m_urlDistributors;
QString m_urlModels;
BlackMisc::Network::CUrl m_urlLiveries;
BlackMisc::Network::CUrl m_urlDistributors;
BlackMisc::Network::CUrl m_urlModels;
mutable QReadWriteLock m_lockDistributor;
mutable QReadWriteLock m_lockLivery;
mutable QReadWriteLock m_lockModels;
BlackCore::CData<BlackCore::Data::GlobalSetup> m_setup {this}; //!< setup cache
//! Base URL
BlackMisc::Network::CUrl getBaseUrl() const;
//! URL livery web service
static QString getLiveryUrl(const QString &protocol, const QString &server, const QString &baseUrl);
BlackMisc::Network::CUrl getLiveryUrl() const;
//! URL distributor web service
static QString getDistributorUrl(const QString &protocol, const QString &server, const QString &baseUrl);
BlackMisc::Network::CUrl getDistributorUrl() const;
//! URL model web service
static QString getModelUrl(const QString &protocol, const QString &server, const QString &baseUrl);
BlackMisc::Network::CUrl getModelUrl() const;
};
} // ns

View File

@@ -22,9 +22,8 @@ using namespace BlackMisc::Network;
namespace BlackCore
{
CVatsimBookingReader::CVatsimBookingReader(QObject *owner, const QString &url) :
CThreadedReader(owner, "CVatsimBookingReader"),
m_serviceUrl(url)
CVatsimBookingReader::CVatsimBookingReader(QObject *owner) :
CThreadedReader(owner, "CVatsimBookingReader")
{
this->m_networkManager = new QNetworkAccessManager(this);
this->connect(this->m_networkManager, &QNetworkAccessManager::finished, this, &CVatsimBookingReader::ps_parseBookings);
@@ -41,9 +40,10 @@ namespace BlackCore
void CVatsimBookingReader::ps_read()
{
this->threadAssertCheck();
QUrl url(this->m_serviceUrl);
if (url.isEmpty()) return;
Q_ASSERT(this->m_networkManager);
Q_ASSERT_X(this->m_networkManager, Q_FUNC_INFO, "No network manager");
QUrl url(m_setup.get().vatsimBookings());
if (url.isEmpty()) { return; }
QNetworkRequest request(url);
this->m_networkManager->get(request);
}

View File

@@ -13,6 +13,7 @@
#define BLACKCORE_VATSIMBOOKINGREADER_H
#include "blackcoreexport.h"
#include "blackcore/data/globalsetup.h"
#include "blackmisc/threadedreader.h"
#include "blackmisc/aviation/atcstationlist.h"
@@ -30,7 +31,7 @@ namespace BlackCore
public:
//! Constructor
explicit CVatsimBookingReader(QObject *owner, const QString &url);
explicit CVatsimBookingReader(QObject *owner);
//! Read / re-read bookings
void readInBackgroundThread();
@@ -51,7 +52,7 @@ namespace BlackCore
void ps_read();
private:
QString m_serviceUrl; //!< URL of the service
BlackCore::CData<BlackCore::Data::GlobalSetup> m_setup {this}; //!< setup cache
QNetworkAccessManager *m_networkManager = nullptr;
};
}

View File

@@ -11,9 +11,11 @@
#include "blackmisc/aviation/atcstation.h"
#include "blackmisc/network/user.h"
#include "blackmisc/network/server.h"
#include "blackmisc/network/urllist.h"
#include "blackmisc/network/entityflags.h"
#include "blackmisc/logmessage.h"
#include "vatsimdatafilereader.h"
#include "blackcore/vatsimdatafilereader.h"
#include "blackcore/setupreader.h"
#include <QRegularExpression>
@@ -23,12 +25,12 @@ using namespace BlackMisc::Network;
using namespace BlackMisc::Geo;
using namespace BlackMisc::Simulation;
using namespace BlackMisc::PhysicalQuantities;
using namespace BlackCore::Data;
namespace BlackCore
{
CVatsimDataFileReader::CVatsimDataFileReader(QObject *owner, const QStringList &urls) :
CThreadedReader(owner, "CVatsimDataFileReader"),
m_serviceUrls(urls), m_currentUrlIndex(0)
CVatsimDataFileReader::CVatsimDataFileReader(QObject *owner) :
CThreadedReader(owner, "CVatsimDataFileReader")
{
this->m_networkManager = new QNetworkAccessManager(this);
this->connect(this->m_networkManager, &QNetworkAccessManager::finished, this, &CVatsimDataFileReader::ps_parseVatsimFile);
@@ -150,17 +152,14 @@ namespace BlackCore
void CVatsimDataFileReader::ps_read()
{
this->threadAssertCheck();
if (this->m_serviceUrls.isEmpty()) { return; }
// round robin for load distribution
this->m_currentUrlIndex++;
if (this->m_serviceUrls.size() >= this->m_currentUrlIndex) this->m_currentUrlIndex = 0;
if (m_setup.get().vatsimDataFile().size() < 1) { return; }
// round robin for load balancing
// remark: Don't use QThread to run network operations in the background
// see http://qt-project.org/doc/qt-4.7/qnetworkaccessmanager.html
QUrl url(this->m_serviceUrls.at(this->m_currentUrlIndex));
QUrl url(m_setup.get().vatsimDataFile().getNextUrl());
if (url.isEmpty()) { return; }
Q_ASSERT(this->m_networkManager);
Q_ASSERT_X(this->m_networkManager, Q_FUNC_INFO, "Missing network manager");
QNetworkRequest request(url);
this->m_networkManager->get(request);
}

View File

@@ -13,6 +13,7 @@
#define BLACKCORE_VATSIMDATAFILEREADER_H
#include "blackcoreexport.h"
#include "blackcore/data/globalsetup.h"
#include "blackmisc/threadedreader.h"
#include "blackmisc/simulation/simulatedaircraftlist.h"
#include "blackmisc/aviation/atcstationlist.h"
@@ -35,7 +36,7 @@ namespace BlackCore
public:
//! Constructor
explicit CVatsimDataFileReader(QObject *owner, const QStringList &urls);
explicit CVatsimDataFileReader(QObject *owner);
//! Get aircraft
//! \threadsafe
@@ -120,13 +121,12 @@ namespace BlackCore
private:
QNetworkAccessManager *m_networkManager = nullptr;
QStringList m_serviceUrls; //!< URL of the service
int m_currentUrlIndex;
BlackMisc::Network::CServerList m_voiceServers;
BlackMisc::Network::CServerList m_fsdServers;
BlackMisc::Aviation::CAtcStationList m_atcStations;
BlackMisc::Simulation::CSimulatedAircraftList m_aircraft;
QMap<BlackMisc::Aviation::CCallsign, BlackMisc::Network::CVoiceCapabilities> m_voiceCapabilities;
BlackCore::CData<BlackCore::Data::GlobalSetup> m_setup {this}; //!< setup cache
//! Split line and assign values to their corresponding attribute names
static const QMap<QString, QString> clientPartsToMap(const QString &currentLine, const QStringList &clientSectionAttributes);

View File

@@ -7,7 +7,8 @@
* contained in the LICENSE file.
*/
#include "vatsimmetarreader.h"
#include "blackcore/setupreader.h"
#include "blackcore/vatsimmetarreader.h"
#include "blackmisc/network/entityflags.h"
#include "blackmisc/sequence.h"
#include "blackmisc/logmessage.h"
@@ -19,12 +20,12 @@
using namespace BlackMisc;
using namespace BlackMisc::Network;
using namespace BlackMisc::Weather;
using namespace BlackCore::Data;
namespace BlackCore
{
CVatsimMetarReader::CVatsimMetarReader(QObject *owner, const QString &url) :
CThreadedReader(owner, "CVatsimMetarReader"),
m_metarUrl(url)
CVatsimMetarReader::CVatsimMetarReader(QObject *owner) :
CThreadedReader(owner, "CVatsimMetarReader")
{
this->m_networkManager = new QNetworkAccessManager(this);
this->connect(this->m_networkManager, &QNetworkAccessManager::finished, this, &CVatsimMetarReader::ps_decodeMetars);
@@ -59,9 +60,9 @@ namespace BlackCore
void CVatsimMetarReader::ps_readMetars()
{
this->threadAssertCheck();
QUrl url(this->m_metarUrl);
if (url.isEmpty()) return;
Q_ASSERT(this->m_networkManager);
QUrl url(m_setup.get().vatsimMetars());
if (url.isEmpty()) { return; }
Q_ASSERT_X(this->m_networkManager, Q_FUNC_INFO, "No network manager");
QNetworkRequest request(url);
this->m_networkManager->get(request);
}
@@ -74,7 +75,7 @@ namespace BlackCore
this->threadAssertCheck();
// Worker thread, make sure to write no members here!
// Worker thread, make sure to write thread safe!
if (this->isFinished())
{
CLogMessage(this).debug() << Q_FUNC_INFO;

View File

@@ -13,6 +13,7 @@
#define BLACKCORE_VATSIMMETARREADER_H
#include "blackcoreexport.h"
#include "blackcore/data/globalsetup.h"
#include "blackmisc/threadedreader.h"
#include "blackmisc/weather/metardecoder.h"
#include "blackmisc/weather/metarset.h"
@@ -31,7 +32,7 @@ namespace BlackCore
public:
//! Constructor
explicit CVatsimMetarReader(QObject *owner, const QString &url);
explicit CVatsimMetarReader(QObject *owner);
//! Read / re-read bookings
void readInBackgroundThread();
@@ -64,10 +65,10 @@ namespace BlackCore
void ps_readMetars();
private:
QString m_metarUrl; //!< URL of the service
QNetworkAccessManager *m_networkManager = nullptr;
BlackMisc::Weather::CMetarDecoder m_metarDecoder;
BlackMisc::Weather::CMetarSet m_metars;
BlackCore::CData<BlackCore::Data::GlobalSetup> m_setup {this}; //!< setup cache
};
}
#endif // guard

View File

@@ -7,6 +7,7 @@
* contained in the LICENSE file.
*/
#include "blackcore/setupreader.h"
#include "blackcore/webdataservices.h"
#include "blackcore/modeldatareader.h"
#include "blackcore/icaodatareader.h"
@@ -14,16 +15,17 @@
#include "blackcore/vatsimbookingreader.h"
#include "blackcore/vatsimdatafilereader.h"
#include "blackcore/vatsimmetarreader.h"
#include "settings/global_reader_settings.h"
#include "data/globalsetup.h"
#include "blackmisc/logmessage.h"
#include "blackmisc/fileutilities.h"
#include "blackmisc/worker.h"
#include "blackmisc/json.h"
#include "blackmisc/network/networkutils.h"
#include <QJsonObject>
#include <QJsonDocument>
using namespace BlackCore;
using namespace BlackCore::Settings;
using namespace BlackCore::Data;
using namespace BlackMisc;
using namespace BlackMisc::Simulation;
using namespace BlackMisc::Network;
@@ -134,15 +136,17 @@ namespace BlackCore
bool CWebDataServices::canConnectSwiftDb() const
{
if (!m_icaoDataReader && !m_modelDataReader) { return false; }
// use the first one to test
if (m_icaoDataReader)
{
if (!m_icaoDataReader->canConnect()) { return false; }
return m_icaoDataReader->canConnect();
}
if (m_modelDataReader)
else if (m_modelDataReader)
{
if (!m_modelDataReader->canConnect()) { return false; }
return m_modelDataReader->canConnect();
}
return true;
return false;
}
CEntityFlags::Entity CWebDataServices::triggerRead(CEntityFlags::Entity whatToRead)
@@ -386,7 +390,7 @@ namespace BlackCore
// 1. VATSIM bookings
if (flags.testFlag(CWebReaderFlags::WebReaderFlag::VatsimBookingReader))
{
this->m_vatsimBookingReader = new CVatsimBookingReader(this, CGlobalReaderSettings::instance().bookingsUrl());
this->m_vatsimBookingReader = new CVatsimBookingReader(this);
bool c = connect(this->m_vatsimBookingReader, &CVatsimBookingReader::atcBookingsRead, this, &CWebDataServices::ps_receivedBookings);
Q_ASSERT_X(c, Q_FUNC_INFO, "VATSIM booking reader signals");
Q_UNUSED(c);
@@ -397,7 +401,7 @@ namespace BlackCore
// 2. VATSIM data file
if (flags.testFlag(CWebReaderFlags::WebReaderFlag::VatsimDataReader))
{
this->m_vatsimDataFileReader = new CVatsimDataFileReader(this, CGlobalReaderSettings::instance().vatsimDataFileUrls());
this->m_vatsimDataFileReader = new CVatsimDataFileReader(this);
bool c = connect(this->m_vatsimDataFileReader, &CVatsimDataFileReader::dataFileRead, this, &CWebDataServices::ps_dataFileRead);
Q_ASSERT_X(c, Q_FUNC_INFO, "VATSIM data reader signals");
Q_UNUSED(c);
@@ -408,7 +412,7 @@ namespace BlackCore
// 3. VATSIM metar data
if (flags.testFlag(CWebReaderFlags::WebReaderFlag::VatsimMetarReader))
{
this->m_vatsimMetarReader = new CVatsimMetarReader(this, CGlobalReaderSettings::instance().urlVatsimMetars());
this->m_vatsimMetarReader = new CVatsimMetarReader(this);
bool c = connect(this->m_vatsimMetarReader, &CVatsimMetarReader::metarsRead, this, &CWebDataServices::ps_receivedMetars);
Q_ASSERT_X(c, Q_FUNC_INFO, "VATSIM METAR reader signals");
Q_UNUSED(c);
@@ -420,7 +424,7 @@ namespace BlackCore
if (flags.testFlag(CWebReaderFlags::WebReaderFlag::IcaoDataReader))
{
bool c;
this->m_icaoDataReader = new CIcaoDataReader(this, CGlobalReaderSettings::instance().protocolIcaoReader(), CGlobalReaderSettings::instance().serverIcaoReader(), CGlobalReaderSettings::instance().baseUrlIcaoReader());
this->m_icaoDataReader = new CIcaoDataReader(this);
c = connect(this->m_icaoDataReader, &CIcaoDataReader::dataRead, this, &CWebDataServices::ps_readFromSwiftDb);
Q_ASSERT_X(c, Q_FUNC_INFO, "ICAO reader signals");
Q_UNUSED(c);
@@ -430,7 +434,7 @@ namespace BlackCore
// 5. Model reader
if (flags.testFlag(CWebReaderFlags::WebReaderFlag::ModelReader))
{
this->m_modelDataReader = new CModelDataReader(this, CGlobalReaderSettings::instance().protocolModelReader(), CGlobalReaderSettings::instance().serverModelReader(), CGlobalReaderSettings::instance().baseUrlModelReader());
this->m_modelDataReader = new CModelDataReader(this);
bool c = connect(this->m_modelDataReader, &CModelDataReader::dataRead, this, &CWebDataServices::ps_readFromSwiftDb);
Q_ASSERT_X(c, Q_FUNC_INFO, "Model reader signals");
Q_UNUSED(c);
@@ -441,9 +445,7 @@ namespace BlackCore
void CWebDataServices::initWriters()
{
this->m_databaseWriter = new CDatabaseWriter(
CGlobalReaderSettings::instance().protocolModelReader(),
CGlobalReaderSettings::instance().serverModelReader(),
CGlobalReaderSettings::instance().baseUrlModelReader(),
m_setup.get().dbModelReader(),
this);
}
@@ -464,8 +466,7 @@ namespace BlackCore
void CWebDataServices::ps_readFromSwiftDb(CEntityFlags::Entity entity, CEntityFlags::ReadState state, int number)
{
CLogMessage(this).info("Read data %1 %3 %2") << CEntityFlags::flagToString(entity) << number << CEntityFlags::flagToString(state);
// emit readSwiftDbData(entity, state, number);
CLogMessage(this).info("Read data %1 entries: %2 state: %3") << CEntityFlags::flagToString(entity) << number << CEntityFlags::flagToString(state);
}
void CWebDataServices::readAllInBackground(int delayMs)
@@ -532,34 +533,20 @@ namespace BlackCore
QDir directory(dir);
if (!directory.exists()) { return false; }
bool s = false;
if (this->m_icaoDataReader)
{
bool s = false;
if (inBackground)
{
s = (this->m_icaoDataReader->readFromJsonFilesInBackground(dir) != nullptr);
}
else
{
s = this->m_icaoDataReader->readFromJsonFiles(dir);
}
if (!s) { return false; }
s = inBackground ?
this->m_icaoDataReader->readFromJsonFilesInBackground(dir) :
this->m_icaoDataReader->readFromJsonFiles(dir);
}
if (this->m_modelDataReader)
if (s && this->m_modelDataReader)
{
bool s = false;
if (inBackground)
{
s = (this->m_modelDataReader->readFromJsonFilesInBackground(dir) != nullptr);
}
else
{
s = this->m_modelDataReader->readFromJsonFiles(dir);
}
if (!s) { return false; }
s = inBackground ?
this->m_modelDataReader->readFromJsonFilesInBackground(dir) :
this->m_modelDataReader->readFromJsonFiles(dir);
}
return true;
return s;
}
void CWebDataServices::readAtcBookingsInBackground() const

View File

@@ -14,6 +14,8 @@
#include "blackcore/blackcoreexport.h"
#include "blackcore/webreaderflags.h"
#include "blackcore/setupreader.h"
#include "blackcore/data/globalsetup.h"
#include "blackmisc/aviation/atcstationlist.h"
#include "blackmisc/aviation/liverylist.h"
#include "blackmisc/aviation/airlineicaocodelist.h"
@@ -267,6 +269,7 @@ namespace BlackCore
void initWriters();
CWebReaderFlags::WebReader m_readerFlags = CWebReaderFlags::WebReaderFlag::None; //!< which readers are available
BlackCore::CData<BlackCore::Data::GlobalSetup> m_setup {this}; //!< setup cache
// for reading XML and VATSIM data files
CVatsimBookingReader *m_vatsimBookingReader = nullptr;
@@ -277,6 +280,9 @@ namespace BlackCore
// writing objects directly into DB
CDatabaseWriter *m_databaseWriter = nullptr;
// Setup
CSetupReader m_setupReader { this };
};
} // namespace

View File

@@ -9,6 +9,9 @@
#include "threadedreader.h"
using namespace BlackMisc;
using namespace BlackMisc::Network;
namespace BlackMisc
{
CThreadedReader::CThreadedReader(QObject *owner, const QString &name) :

View File

@@ -13,6 +13,7 @@
//! \file
#include "blackmiscexport.h"
#include "blackmisc/network/urllist.h"
#include "blackmisc/network/entityflags.h"
#include "worker.h"
#include <QReadWriteLock>
@@ -63,14 +64,14 @@ namespace BlackMisc
CThreadedReader(QObject *owner, const QString &name);
QTimer *m_updateTimer = nullptr; //!< update timer
bool m_shutdown = false; //!< in shutdown process
bool m_shutdown = false; //!< in shutdown process
mutable QReadWriteLock m_lock {QReadWriteLock::Recursive}; //!< lock which can be used from the derived classes
//! Make sure everthing runs correctly in own thread
void threadAssertCheck() const;
private:
QDateTime m_updateTimestamp; //!< when was file / resource read
QDateTime m_updateTimestamp; //!< when file/resource was read
};
} // namespace