diff --git a/src/blackcore/databasereader.cpp b/src/blackcore/databasereader.cpp index 3274ef4c6..c64512454 100644 --- a/src/blackcore/databasereader.cpp +++ b/src/blackcore/databasereader.cpp @@ -8,6 +8,7 @@ */ #include "databasereader.h" +#include "blackmisc/network/networkutils.h" #include "blackmisc/logmessage.h" #include "blackmisc/datastoreutility.h" #include @@ -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 diff --git a/src/blackcore/databasereader.h b/src/blackcore/databasereader.h index 264afa335..8c3c466e6 100644 --- a/src/blackcore/databasereader.h +++ b/src/blackcore/databasereader.h @@ -18,6 +18,8 @@ #include #include #include +#include + 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 diff --git a/src/blackcore/databasewriter.cpp b/src/blackcore/databasewriter.cpp index 517867dc8..dd035663b 100644 --- a/src/blackcore/databasewriter.cpp +++ b/src/blackcore/databasewriter.cpp @@ -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 #include #include @@ -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 CDatabaseWriter::splitData(const QByteArray &data, int size) diff --git a/src/blackcore/databasewriter.h b/src/blackcore/databasewriter.h index 7b6fc6176..a7e90ae57 100644 --- a/src/blackcore/databasewriter.h +++ b/src/blackcore/databasewriter.h @@ -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 splitData(const QByteArray &data, int size); diff --git a/src/blackcore/icaodatareader.cpp b/src/blackcore/icaodatareader.cpp index d2a36da73..6f3772ecf 100644 --- a/src/blackcore/icaodatareader.cpp +++ b/src/blackcore/icaodatareader.cpp @@ -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 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 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 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 diff --git a/src/blackcore/icaodatareader.h b/src/blackcore/icaodatareader.h index 6ba416cfc..d4e86b8d0 100644 --- a/src/blackcore/icaodatareader.h +++ b/src/blackcore/icaodatareader.h @@ -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 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; }; } diff --git a/src/blackcore/modeldatareader.cpp b/src/blackcore/modeldatareader.cpp index 9ea92d0d8..2d305223c 100644 --- a/src/blackcore/modeldatareader.cpp +++ b/src/blackcore/modeldatareader.cpp @@ -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 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 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 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 diff --git a/src/blackcore/modeldatareader.h b/src/blackcore/modeldatareader.h index 8418e1447..454c1e4a0 100644 --- a/src/blackcore/modeldatareader.h +++ b/src/blackcore/modeldatareader.h @@ -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 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 diff --git a/src/blackcore/vatsimbookingreader.cpp b/src/blackcore/vatsimbookingreader.cpp index 5763cabd7..a23bcd9f0 100644 --- a/src/blackcore/vatsimbookingreader.cpp +++ b/src/blackcore/vatsimbookingreader.cpp @@ -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); } diff --git a/src/blackcore/vatsimbookingreader.h b/src/blackcore/vatsimbookingreader.h index b5beeb4ab..dab529d8a 100644 --- a/src/blackcore/vatsimbookingreader.h +++ b/src/blackcore/vatsimbookingreader.h @@ -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 m_setup {this}; //!< setup cache QNetworkAccessManager *m_networkManager = nullptr; }; } diff --git a/src/blackcore/vatsimdatafilereader.cpp b/src/blackcore/vatsimdatafilereader.cpp index 6acdc5a5f..038c3e27c 100644 --- a/src/blackcore/vatsimdatafilereader.cpp +++ b/src/blackcore/vatsimdatafilereader.cpp @@ -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 @@ -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); } diff --git a/src/blackcore/vatsimdatafilereader.h b/src/blackcore/vatsimdatafilereader.h index 59533e3a3..388965c27 100644 --- a/src/blackcore/vatsimdatafilereader.h +++ b/src/blackcore/vatsimdatafilereader.h @@ -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 m_voiceCapabilities; + BlackCore::CData m_setup {this}; //!< setup cache //! Split line and assign values to their corresponding attribute names static const QMap clientPartsToMap(const QString ¤tLine, const QStringList &clientSectionAttributes); diff --git a/src/blackcore/vatsimmetarreader.cpp b/src/blackcore/vatsimmetarreader.cpp index ab4cf4a63..be43e61f6 100644 --- a/src/blackcore/vatsimmetarreader.cpp +++ b/src/blackcore/vatsimmetarreader.cpp @@ -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; diff --git a/src/blackcore/vatsimmetarreader.h b/src/blackcore/vatsimmetarreader.h index e62cc4851..7ea52db2f 100644 --- a/src/blackcore/vatsimmetarreader.h +++ b/src/blackcore/vatsimmetarreader.h @@ -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 m_setup {this}; //!< setup cache }; } #endif // guard diff --git a/src/blackcore/webdataservices.cpp b/src/blackcore/webdataservices.cpp index e1d718530..c276ff1f8 100644 --- a/src/blackcore/webdataservices.cpp +++ b/src/blackcore/webdataservices.cpp @@ -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 #include 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 diff --git a/src/blackcore/webdataservices.h b/src/blackcore/webdataservices.h index f9576340f..068132459 100644 --- a/src/blackcore/webdataservices.h +++ b/src/blackcore/webdataservices.h @@ -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 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 diff --git a/src/blackmisc/threadedreader.cpp b/src/blackmisc/threadedreader.cpp index b0d28f93f..5fa828247 100644 --- a/src/blackmisc/threadedreader.cpp +++ b/src/blackmisc/threadedreader.cpp @@ -9,6 +9,9 @@ #include "threadedreader.h" +using namespace BlackMisc; +using namespace BlackMisc::Network; + namespace BlackMisc { CThreadedReader::CThreadedReader(QObject *owner, const QString &name) : diff --git a/src/blackmisc/threadedreader.h b/src/blackmisc/threadedreader.h index c35498758..acf2cfeaa 100644 --- a/src/blackmisc/threadedreader.h +++ b/src/blackmisc/threadedreader.h @@ -13,6 +13,7 @@ //! \file #include "blackmiscexport.h" +#include "blackmisc/network/urllist.h" #include "blackmisc/network/entityflags.h" #include "worker.h" #include @@ -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