6 #include <QElapsedTimer>
8 #include <QNetworkReply>
10 #include <QStringBuilder>
18 using namespace swift::misc::aviation;
19 using namespace swift::misc::network;
20 using namespace swift::misc::db;
45 bool overrideNewerOnly)
47 if (dir.isEmpty() || whatToRead == CEntityFlags::NoEntity) {
return false; }
49 QPointer<CAirportDataReader> myself(
this);
51 if (!myself) {
return; }
59 bool overrideNewerOnly)
61 const QDir directory(dir);
62 if (!directory.exists()) {
return CStatusMessage(
this).
error(u
"Missing directory '%1'") << dir; }
64 whatToRead &= CEntityFlags::AirportEntity;
65 if (whatToRead == CEntityFlags::NoEntity)
68 << CEntityFlags::entitiesToString(whatToRead);
72 CEntityFlags::Entity reallyRead = CEntityFlags::NoEntity;
76 const QFileInfo fi(fileName);
84 const QUrl url = QUrl::fromLocalFile(fi.absoluteFilePath());
86 if (!airportsJson.isEmpty())
90 const CAirportList airports = CAirportList::fromMultipleJsonFormats(airportsJson);
92 msgs.
push_back(m_airportCache.
set(airports, fi.birthTime().toUTC().toMSecsSinceEpoch()));
94 emit
dataRead(CEntityFlags::AirportEntity, CEntityFlags::ReadFinished, c, url);
95 reallyRead |= CEntityFlags::AirportEntity;
99 emit
dataRead(CEntityFlags::AirportEntity, CEntityFlags::ReadFailed, 0, url);
101 ex,
this, QStringLiteral(
"Reading airports from '%1'").arg(fileName));
112 return entities == CEntityFlags::AirportEntity ? m_airportCache.
getAvailableTimestamp() : QDateTime();
117 return entity == CEntityFlags::AirportEntity ? m_airportCache.
get().size() : 0;
122 CEntityFlags::Entity entities = CEntityFlags::NoEntity;
123 if (this->
getCacheCount(CEntityFlags::AirportEntity) > 0) { entities |= CEntityFlags::AirportEntity; }
129 CEntityFlags::Entity entities = CEntityFlags::NoEntity;
132 entities |= CEntityFlags::AirportEntity;
139 if (entities.testFlag(CEntityFlags::AirportEntity))
141 if (m_syncedAirportCache) {
return; }
142 m_syncedAirportCache =
true;
149 if (entities.testFlag(CEntityFlags::AirportEntity)) { m_airportCache.
admit(); }
154 if (entities.testFlag(CEntityFlags::AirportEntity))
163 oldUrlInfo = m_readerUrlCache.
get();
164 newUrlInfo = this->
getBaseUrl(CDbFlags::DbReading);
175 void CAirportDataReader::parseAirportData(QNetworkReply *nwReplyPtr)
179 QScopedPointer<QNetworkReply, QScopedPointerDeleteLater> nwReply(nwReplyPtr);
182 const CDatabaseReader::JsonDatastoreResponse res =
184 const QUrl url = nwReply->url();
186 if (res.hasErrorMessage())
189 emit this->
dataRead(CEntityFlags::AirportEntity, CEntityFlags::ReadFailed, 0, url);
194 emit this->
dataRead(CEntityFlags::AirportEntity, CEntityFlags::ReadParsing, 0, url);
197 if (res.isRestricted())
199 const CAirportList incrementalAirports(CAirportList::fromDatabaseJson(res, &inconsistent));
200 if (incrementalAirports.isEmpty()) {
return; }
208 airports = CAirportList::fromDatabaseJson(res, &inconsistent);
220 const int size = airports.
size();
222 if (size > 0 && latestTimestamp < 0)
224 CLogMessage(
this).
error(u
"No timestamp in airport list, setting to last modified value");
228 m_airportCache.
set(airports, latestTimestamp);
229 this->updateReaderUrl(
getBaseUrl(CDbFlags::DbReading));
235 const QDateTime &newerThan)
239 entity &= CEntityFlags::AirportEntity;
241 if (entity.testFlag(CEntityFlags::AirportEntity))
243 CUrl url = this->getAirportsUrl(mode);
248 emit
dataRead(CEntityFlags::AirportEntity, CEntityFlags::ReadStarted, 0, url);
254 void CAirportDataReader::airportCacheChanged() { this->
cacheHasChanged(CEntityFlags::AirportEntity); }
256 void CAirportDataReader::baseUrlCacheChanged()
261 void CAirportDataReader::updateReaderUrl(
const CUrl &url)
263 const CUrl current = m_readerUrlCache.
get();
264 if (current == url) {
return; }
SWIFT_CORE_EXPORT swift::core::CApplication * sApp
Single instance of application object.
data::CGlobalSetup getGlobalSetup() const
Global setup.
static void logInconsistentData(const swift::misc::CStatusMessage &msg, const char *funcInfo=nullptr)
Use this to log inconsistent data.
void threadAssertCheck() const
Make sure everthing runs correctly in own thread.
QNetworkReply * getFromNetworkAndLog(const swift::misc::network::CUrl &url, const swift::misc::CSlot< void(QNetworkReply *)> &callback)
Get request from network, and log with m_urlReadLog.
bool doWorkCheck() const
Still enabled etc.?
qint64 lastModifiedMsSinceEpoch(QNetworkReply *nwReply) const
When was reply last modified, -1 if N/A.
swift::misc::network::CUrl getDbAirportReaderUrl() const
Airport reader URL.
virtual bool readFromJsonFilesInBackground(const QString &dir, swift::misc::network::CEntityFlags::Entity whatToRead, bool overrideNewerOnly)
Data read from local data.
virtual swift::misc::network::CEntityFlags::Entity getSupportedEntities() const
Supported entities by this reader.
swift::misc::aviation::CAirport getAirportForIcaoDesignator(const QString &designator) const
Returns airport for designator (or default)
virtual swift::misc::network::CUrl getDbServiceBaseUrl() const
Get the service URL, individual for each reader.
virtual swift::misc::network::CEntityFlags::Entity getEntitiesWithCacheTimestampNewerThan(const QDateTime &threshold) const
Entities already having data in cache (based on timestamp assumption)
virtual void invalidateCaches(swift::misc::network::CEntityFlags::Entity entities)
Invalidate the caches for given entities.
int getAirportsCount() const
Returns a list of all airports in the database.
swift::misc::aviation::CAirport getAirportForNameOrLocation(const QString &location) const
Get airports for location.
virtual void synchronizeCaches(swift::misc::network::CEntityFlags::Entity entities)
Admit caches for given entities.
virtual bool hasChangedUrl(swift::misc::network::CEntityFlags::Entity entity, swift::misc::network::CUrl &oldUrlInfo, swift::misc::network::CUrl &newUrlInfo) const
Changed URL, means the cache values have been read from elsewhere.
swift::misc::aviation::CAirportList getAirports() const
Returns a list of all airports in the database.
virtual int getCacheCount(swift::misc::network::CEntityFlags::Entity entity) const
Cache`s number of entities.
virtual swift::misc::CStatusMessageList readFromJsonFiles(const QString &dir, swift::misc::network::CEntityFlags::Entity whatToRead, bool overrideNewerOnly)
Data read from local data.
virtual void admitCaches(swift::misc::network::CEntityFlags::Entity entities)
Admit caches for given entities.
virtual QDateTime getCacheTimestamp(swift::misc::network::CEntityFlags::Entity entities) const
Get cache timestamp.
virtual swift::misc::network::CEntityFlags::Entity getEntitiesWithCacheCount() const
Entities already having data in cache.
Value object encapsulating a list of reader configs.
Specialized version of threaded reader for DB data.
void emitAndLogDataRead(swift::misc::network::CEntityFlags::Entity entity, int number, const JsonDatastoreResponse &res)
Emit signal and log when data have been read.
static QString queryLatestTimestamp(const QDateTime &ts)
Latest timestamp query for DB.
virtual void cacheHasChanged(swift::misc::network::CEntityFlags::Entity entities)
Cache for given entity has changed.
void logNoWorkingUrl(swift::misc::network::CEntityFlags::Entity entity)
Log if no working URL exists, using m_noWorkingUrlSeverity.
bool overrideCacheFromFile(bool overrideNewerOnly, const QFileInfo &fileInfo, swift::misc::network::CEntityFlags::Entity entity, swift::misc::CStatusMessageList &msgs) const
Override cache from file.
swift::misc::network::CUrl getBaseUrl(swift::misc::db::CDbFlags::DataRetrievalModeFlag mode) const
Base URL for mode (either a shared or DB URL)
void dataRead(swift::misc::network::CEntityFlags::Entity entities, swift::misc::network::CEntityFlags::ReadState state, int number, const QUrl &url)
Combined read signal.
static bool isChangedUrl(const swift::misc::network::CUrl &oldUrl, const swift::misc::network::CUrl ¤tUrl)
Has URL been changed? Means we load from a different server.
static QString fileNameForMode(swift::misc::network::CEntityFlags::Entity entity, swift::misc::db::CDbFlags::DataRetrievalModeFlag mode)
File name for given mode, either php service or shared file name.
CDatabaseReader::JsonDatastoreResponse setStatusAndTransformReplyIntoDatastoreResponse(QNetworkReply *nwReply)
Check if terminated or error, otherwise split into array of objects.
void logParseMessage(const QString &entity, int size, int msElapsed, const JsonDatastoreResponse &response) const
Parsing info message.
bool hasCacheTimestampNewerThan(swift::misc::network::CEntityFlags::Entity entity, const QDateTime &threshold) const
Has entity a valid and newer timestamp.
static QJsonObject readQJsonObjectFromDatabaseFile(const QString &filename)
QJsonObject from database JSON file (normally shared file)
const QString & getKey() const
Get the key string of this value.
T get() const
Get a copy of the current value.
static CDataCache * instance()
Return the singleton instance.
CStatusMessage set(const typename Trait::type &value, qint64 timestamp=0)
Write a new value. Must be called from the thread in which the owner lives.
void admit()
If the value is load-deferred, trigger the deferred load (async).
QDateTime getAvailableTimestamp() const
Get the timestamp of the value, or of the deferred value that is available to be loaded.
void synchronize()
If the value is currently being loaded, wait for it to finish loading, and call the notification slot...
static QString appendFilePaths(const QString &path1, const QString &path2)
Append file paths.
Thrown when a convertFromJson method encounters an unrecoverable error in JSON data.
Class for emitting a log message.
static void preformatted(const CStatusMessage &statusMessage)
Sends a verbatim, preformatted message to the log.
Derived & error(const char16_t(&format)[N])
Set the severity to error, providing a format string.
Derived & info(const char16_t(&format)[N])
Set the severity to info, providing a format string.
size_type size() const
Returns number of elements in the sequence.
void push_back(const T &value)
Appends an element at the end of the sequence.
bool isEmpty() const
Synonym for empty.
Streamable status message, e.g.
static CStatusMessage fromJsonException(const CJsonException &ex, const CLogCategoryList &categories, const QString &prefix)
Object from JSON exception message.
constexpr static auto SeverityInfo
Status severities.
bool isFailure() const
Operation considered unsuccessful.
Status messages, e.g. from Core -> GUI.
bool isFailure() const
Any message is marked as failure.
void clearAllValues(const QString &keyPrefix={})
Clear all values from the cache.
qint64 latestTimestampMsecsSinceEpoch() const
Latest timestamp.
Value object encapsulating information about an airpot.
Value object encapsulating information of airport ICAO data.
Value object for a list of airports.
CAirport findFirstByIcao(const CAirportIcaoCode &icao) const
Find first station by callsign, if not return default.
CAirport findFirstByNameOrLocation(const QString &nameOrLocation) const
Find first by name or location, if not return default.
DataRetrievalModeFlag
Which data to read, requires corresponding readers.
int replaceOrAddObjectsByKey(const CONTAINER &container)
Update or insert data (based on DB key)
QString dbKeysAsString(const QString &separator) const
The DB keys as string.
Value object encapsulating information of a location, kind of simplified CValueObject compliant versi...
bool isEmpty() const
Empty.
CUrl withAppendedPath(const QString &path) const
Append path.
void appendQuery(const QString &queryToAppend)
Append query.
Classes interacting with the swift database (aka "datastore").
Free functions in swift::misc.
auto singleShot(int msec, QObject *target, F &&task)
Starts a single-shot timer which will call a task in the thread of the given object when it times out...