diff --git a/src/blackcore/data/globalsetup.cpp b/src/blackcore/data/globalsetup.cpp index b91bae16b..4f50dbdf4 100644 --- a/src/blackcore/data/globalsetup.cpp +++ b/src/blackcore/data/globalsetup.cpp @@ -52,6 +52,13 @@ namespace BlackCore return this->m_sharedUrls; } + CUrlList CGlobalSetup::getSwiftAirportUrls() const + { + // currently subdir of shared, this might change + const CUrlList airportUrls(getSwiftSharedUrls().appendPath("/airports/airports.json")); + return airportUrls; + } + CUrl CGlobalSetup::getDbHomePageUrl() const { return getDbRootDirectoryUrl().withAppendedPath("/page/index.php"); @@ -156,7 +163,7 @@ namespace BlackCore s.append(this->getFormattedUtcTimestampYmdhms()); s.append(separator); - s.append("Loaded: "); + s.append("Global setup loaded: "); s.append(boolToYesNo(this->wasLoaded())); s.append(separator); @@ -193,6 +200,10 @@ namespace BlackCore s.append(getSwiftDbDataFileLocationUrls().toQString(i18n)); s.append(separator); + s.append("swift airport files: "); + s.append(getSwiftAirportUrls().toQString(i18n)); + s.append(separator); + s.append("VATSIM bookings: "); s.append(getVatsimBookingsUrl().toQString(i18n)); s.append(separator); diff --git a/src/blackcore/data/globalsetup.h b/src/blackcore/data/globalsetup.h index cdd999ceb..576196ec5 100644 --- a/src/blackcore/data/globalsetup.h +++ b/src/blackcore/data/globalsetup.h @@ -105,6 +105,9 @@ namespace BlackCore //! Shared URLs const BlackMisc::Network::CUrlList &getSwiftSharedUrls() const; + //! Airport URLs + BlackMisc::Network::CUrlList getSwiftAirportUrls() const; + //! URL to read VATSIM bookings const BlackMisc::Network::CUrl &getVatsimBookingsUrl() const { return m_vatsimBookingsUrl; } diff --git a/src/blackcore/db/databasereader.cpp b/src/blackcore/db/databasereader.cpp index 7e88e1c06..a86e75c7e 100644 --- a/src/blackcore/db/databasereader.cpp +++ b/src/blackcore/db/databasereader.cpp @@ -39,7 +39,7 @@ namespace BlackCore CDatabaseReader::CDatabaseReader(QObject *owner, const CDatabaseReaderConfigList &config, const QString &name) : BlackCore::CThreadedReader(owner, name), m_config(config) { - this->m_sharedUrl = sApp->getGlobalSetup().getSwiftSharedUrls().getRandomWorkingUrl(); + getDbUrl(); // init } void CDatabaseReader::readInBackgroundThread(CEntityFlags::Entity entities, const QDateTime &newerThan) @@ -230,11 +230,6 @@ namespace BlackCore return m_canConnect; } - CUrl CDatabaseReader::getWorkingSharedUrl() const - { - return this->m_sharedUrl; - } - const QString &CDatabaseReader::getStatusMessage() const { return this->m_statusMessage; @@ -285,5 +280,21 @@ namespace BlackCore static const QString p("latestId"); return p; } + + const CUrl &CDatabaseReader::getDbUrl() + { + static const CUrl dbUrl(sApp->getGlobalSetup().getDbRootDirectoryUrl()); + return dbUrl; + } + + CUrl CDatabaseReader::getWorkingSharedUrl() + { + return sApp->getGlobalSetup().getSwiftSharedUrls().getRandomWorkingUrl(); + } + + bool CDatabaseReader::canPingSwiftServer() + { + return CNetworkUtils::canConnect(getDbUrl()); + } } // ns } // ns diff --git a/src/blackcore/db/databasereader.h b/src/blackcore/db/databasereader.h index d28cb6098..fa17e085d 100644 --- a/src/blackcore/db/databasereader.h +++ b/src/blackcore/db/databasereader.h @@ -103,9 +103,6 @@ namespace BlackCore //! \threadsafe bool canConnect(QString &message) const; - //! Obtain a working shared URL - BlackMisc::Network::CUrl getWorkingSharedUrl() const; - //! Status message (error message) const QString &getStatusMessage() const; @@ -118,13 +115,15 @@ namespace BlackCore //! Name of parameter for latest id static const QString ¶meterLatestId(); + //! sift DB server reachable? + static bool canPingSwiftServer(); + signals: //! Combined read signal void dataRead(BlackMisc::Network::CEntityFlags::Entity entity, BlackMisc::Network::CEntityFlags::ReadState state, int number); protected: CDatabaseReaderConfigList m_config; //!< DB reder configuration - BlackMisc::Network::CUrl m_sharedUrl; //!< URL for shared files QString m_statusMessage; //!< Returned status message from watchdog bool m_canConnect = false; //!< Successful connection? mutable QReadWriteLock m_statusLock; //!< Lock @@ -152,7 +151,14 @@ namespace BlackCore //! Split into single entity and send dataRead signal void emitReadSignalPerSingleCachedEntity(BlackMisc::Network::CEntityFlags::Entity cachedEntities); - // ---------------- cache access ------------------ + //! DB base URL + static const BlackMisc::Network::CUrl &getDbUrl(); + + //! Obtain a working shared URL + static BlackMisc::Network::CUrl getWorkingSharedUrl(); + + //! \name Cache access + //! @{ //! Syncronize caches for given entities virtual void syncronizeCaches(BlackMisc::Network::CEntityFlags::Entity entities) = 0; @@ -171,6 +177,7 @@ namespace BlackCore //! Has URL been changed? Means we load from a differrent server static bool isChangedUrl(const BlackMisc::Network::CUrl &oldUrl, const BlackMisc::Network::CUrl ¤tUrl); + //! @} private: //! Check if terminated or error, otherwise split into array of objects diff --git a/src/blackcore/db/databasereaderconfig.cpp b/src/blackcore/db/databasereaderconfig.cpp index c8843e332..0ea297b7f 100644 --- a/src/blackcore/db/databasereaderconfig.cpp +++ b/src/blackcore/db/databasereaderconfig.cpp @@ -47,6 +47,13 @@ namespace BlackCore return static_cast(this->m_retrievalFlags); } + void CDatabaseReaderConfig::markAsDbDown() + { + CDbFlags::DataRetrievalMode m = this->getRetrievalMode(); + m = CDbFlags::adjustWhenDbIsDown(m); + this->m_retrievalFlags = static_cast(m); + } + void CDatabaseReaderConfig::setCacheLifetime(const CTime &time) { this->m_cacheLifetime = time; @@ -86,6 +93,14 @@ namespace BlackCore return CDatabaseReaderConfig(); // not found } + void CDatabaseReaderConfigList::markAsDbDown() + { + for (CDatabaseReaderConfig &config : *this) + { + config.markAsDbDown(); + } + } + void CDatabaseReaderConfigList::setCacheLifetimes(const CTime &time) { for (CDatabaseReaderConfig &config : *this) diff --git a/src/blackcore/db/databasereaderconfig.h b/src/blackcore/db/databasereaderconfig.h index 98631f0c3..5bf9b4401 100644 --- a/src/blackcore/db/databasereaderconfig.h +++ b/src/blackcore/db/databasereaderconfig.h @@ -53,6 +53,9 @@ namespace BlackCore //! Supported modes BlackMisc::Db::CDbFlags::DataRetrievalMode getRetrievalMode() const; + //! DB is down + void markAsDbDown(); + //! Timeout void setCacheLifetime(const BlackMisc::PhysicalQuantities::CTime &time); @@ -91,6 +94,9 @@ namespace BlackCore //! FInd first one matching given CDatabaseReaderConfig findFirstOrDefaultForEntity(const BlackMisc::Network::CEntityFlags::Entity entities) const; + //! DB is down + void markAsDbDown(); + //! Update lifetimes void setCacheLifetimes(const BlackMisc::PhysicalQuantities::CTime &time); diff --git a/src/blackcore/setupreader.cpp b/src/blackcore/setupreader.cpp index 62f366e83..b1d7b5849 100644 --- a/src/blackcore/setupreader.cpp +++ b/src/blackcore/setupreader.cpp @@ -35,15 +35,13 @@ using namespace BlackCore::Data; namespace BlackCore { - CSetupReader::CSetupReader(QObject *parent) : - QObject(parent), + CSetupReader::CSetupReader(QObject *parent) : QObject(parent), m_cmdBootstrapUrl { { "url", "bootstrapurl" }, QCoreApplication::translate("application", "bootstrap URL, e.g. datastore.swift-project.org"), "bootstrapurl", (sApp->isUnitTest()) ? unitTestBootstrapUrl() : "" - }, - m_cmdBootstrapMode + }, m_cmdBootstrapMode { { "bmode", "bootstrapmode" }, QCoreApplication::translate("application", "bootstrap mode: explicit, implicit, cache(-only)"), diff --git a/src/blackcore/webdataservices.cpp b/src/blackcore/webdataservices.cpp index 19e273821..c66084ffa 100644 --- a/src/blackcore/webdataservices.cpp +++ b/src/blackcore/webdataservices.cpp @@ -431,21 +431,29 @@ namespace BlackCore // 1. If any DB data, read the info upfront const bool anyDbData = flags.testFlag(CWebReaderFlags::WebReaderFlag::IcaoDataReader) || flags.testFlag(CWebReaderFlags::WebReaderFlag::ModelReader); - const CDatabaseReaderConfigList dbReaderConfig(this->m_dbReaderConfig); - bool c = false; // signal connect - Q_UNUSED(c); + const bool databaseUp = CInfoDataReader::canPingSwiftServer(); + CDatabaseReaderConfigList dbReaderConfig(this->m_dbReaderConfig); + if (!databaseUp) { dbReaderConfig.markAsDbDown(); } + bool c = false; // for signal connect + Q_UNUSED(c); if (anyDbData && flags.testFlag(CWebReaderFlags::WebReaderFlag::InfoDataReader)) { - this->m_infoDataReader = new CInfoDataReader(this, dbReaderConfig); - c = connect(this->m_infoDataReader, &CInfoDataReader::dataRead, this, &CWebDataServices::ps_readFromSwiftDb); - Q_ASSERT_X(c, Q_FUNC_INFO, "ICAO info object signals"); - c = connect(this->m_infoDataReader, &CInfoDataReader::dataRead, this, &CWebDataServices::dataRead); - Q_ASSERT_X(c, Q_FUNC_INFO, "connect failed info data"); - this->m_infoDataReader->start(QThread::LowPriority); - // info data reader has a special role, it will not be triggered in triggerRead() - QTimer::singleShot(0, [this]() { this->m_infoDataReader->read(CEntityFlags::InfoObjectEntity, QDateTime()); }); + if (databaseUp) + { + this->m_infoDataReader = new CInfoDataReader(this, dbReaderConfig); + c = connect(this->m_infoDataReader, &CInfoDataReader::dataRead, this, &CWebDataServices::ps_readFromSwiftDb); + Q_ASSERT_X(c, Q_FUNC_INFO, "ICAO info object signals"); + c = connect(this->m_infoDataReader, &CInfoDataReader::dataRead, this, &CWebDataServices::dataRead); + Q_ASSERT_X(c, Q_FUNC_INFO, "connect failed info data"); + this->m_infoDataReader->start(QThread::LowPriority); + QTimer::singleShot(0, [this]() { this->m_infoDataReader->read(CEntityFlags::InfoObjectEntity, QDateTime()); }); + } + else + { + CLogMessage(this).warning("DB unrechable, skipping read from info data reader"); + } } // 2. Status file, updating the VATSIM related caches diff --git a/src/blackmisc/db/dbflags.cpp b/src/blackmisc/db/dbflags.cpp index 105d44f96..91884232d 100644 --- a/src/blackmisc/db/dbflags.cpp +++ b/src/blackmisc/db/dbflags.cpp @@ -40,12 +40,24 @@ namespace BlackMisc { QStringList list; if (mode.testFlag(Unspecified)) list << "Unspecified"; + if (mode.testFlag(Canceled)) list << "Unspecified"; + if (mode.testFlag(DbDirect)) list << "Direct DB access"; if (mode.testFlag(Shared)) list << "Shared data"; if (mode.testFlag(Cached)) list << "Cached data"; return list.join(','); } + CDbFlags::DataRetrievalMode CDbFlags::adjustWhenDbIsDown(DataRetrievalMode mode) + { + switch (mode) + { + case DbDirect: return Canceled; + case CacheThenDb: return Cached; + default: return mode; + } + } + void CDbFlags::registerMetadata() { // this is no value class and I register enums here, diff --git a/src/blackmisc/db/dbflags.h b/src/blackmisc/db/dbflags.h index 874d82b7c..42c14eccb 100644 --- a/src/blackmisc/db/dbflags.h +++ b/src/blackmisc/db/dbflags.h @@ -35,10 +35,10 @@ namespace BlackMisc DbDirect = 1 << 0, //!< directly from DB Shared = 1 << 1, //!< shared directory Cached = 1 << 2, //!< from cache - DbFailover = 1 << 3, //!< read from DB if cache (and only if) cache is empty - SharedFailover = 1 << 4, //!< read shared if cache (and only if) cache is empty + Canceled = 1 << 3, //!< cancel DB reading CacheThenDb = DbDirect | Cached, //!< Cache when possible, otherwise DB CacheThenShared = Shared | Cached //!< Cache when possible, otherwise shared + }; Q_DECLARE_FLAGS(DataRetrievalMode, DataRetrievalModeFlag) @@ -51,6 +51,9 @@ namespace BlackMisc //! Convert to string static QString flagToString(CDbFlags::DataRetrievalMode mode); + //! Adjust flag as we alread know DB is down + static DataRetrievalMode adjustWhenDbIsDown(DataRetrievalMode mode); + //! Register metadata static void registerMetadata(); };