swift
webdataservices.cpp
1 // SPDX-FileCopyrightText: Copyright (C) 2015 swift Project Community / Contributors
2 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
3 
4 #include "core/webdataservices.h"
5 
6 #include <QDir>
7 #include <QJsonDocument>
8 #include <QPointer>
9 #include <QSslSocket>
10 #include <QThread>
11 #include <QTimer>
12 #include <QtGlobal>
13 
14 #include "config/buildconfig.h"
15 #include "core/application.h"
17 #include "core/data/globalsetup.h"
19 #include "core/db/databasewriter.h"
20 #include "core/db/icaodatareader.h"
21 #include "core/db/infodatareader.h"
23 #include "core/setupreader.h"
28 #include "misc/fileutils.h"
29 #include "misc/logcategories.h"
30 #include "misc/logmessage.h"
31 #include "misc/statusmessage.h"
32 #include "misc/threadutils.h"
33 #include "misc/worker.h"
34 
35 using namespace swift::core;
36 using namespace swift::core::db;
37 using namespace swift::core::data;
38 using namespace swift::core::vatsim;
39 using namespace swift::core::context;
40 using namespace swift::config;
41 using namespace swift::misc;
42 using namespace swift::misc::db;
43 using namespace swift::misc::simulation;
44 using namespace swift::misc::network;
45 using namespace swift::misc::aviation;
46 using namespace swift::misc::weather;
47 
48 namespace swift::core
49 {
50  CWebDataServices::CWebDataServices(CWebReaderFlags::WebReader readerFlags,
51  const CDatabaseReaderConfigList &dbReaderConfig, QObject *parent)
52  : QObject(parent), m_dbReaderConfig(dbReaderConfig)
53  {
54  if (!sApp) { return; } // shutting down
55 
56  Q_ASSERT_X(QSslSocket::supportsSsl(), Q_FUNC_INFO, "Missing SSL support");
57  Q_ASSERT_X(sApp->isSetupAvailable(), Q_FUNC_INFO, "Setup not synchronized");
58  this->setObjectName("CWebDataServices");
59 
60  // SSL INFOs
61  CLogMessage(this).info(u"SSL supported: %1 Version: %2 (build version) %3 (library version)")
62  << boolToYesNo(QSslSocket::supportsSsl()) << QSslSocket::sslLibraryBuildVersionString()
63  << QSslSocket::sslLibraryVersionString();
64 
65  // check if I need info objects
66  const bool readFromSwiftDb = dbReaderConfig.possiblyReadsFromSwiftDb(); // DB read access
67  const bool writeToSwiftDb = dbReaderConfig.possiblyWritesToSwiftDb(); // DB write access
68  if (!readFromSwiftDb && readerFlags.testFlag(CWebReaderFlags::DbInfoDataReader))
69  {
70  // will remove info reader because not needed
71  readerFlags &= ~CWebReaderFlags::DbInfoDataReader;
72  CLogMessage(this).info(u"Remove info object reader because not needed");
73  }
74 
75  // get entities to be read
76  CEntityFlags::Entity entities = CWebReaderFlags::allEntitiesForReaders(readerFlags);
77  if (entities.testFlag(CEntityFlags::DbInfoObjectEntity))
78  {
79  Q_ASSERT_X(readerFlags.testFlag(CWebReaderFlags::DbInfoDataReader), Q_FUNC_INFO,
80  "info object but no reader");
81  CLogMessage(this).info(u"Using info objects for swift DB entities");
82  }
83 
84  this->initReaders(readerFlags, entities); // reads info objects if required
85  if (writeToSwiftDb) { this->initWriters(); }
86 
87  // make sure this is called in event queue, so pending tasks cam be performed
88  entities &= ~CEntityFlags::DbInfoObjectEntity; // triggered in init readers
89  entities &= ~CEntityFlags::VatsimStatusFile; // triggered in init readers
90  entities &= ~m_entitiesPeriodicallyRead; // will be triggered by timers
91 
92  // trigger reading
93  // but do not start all at the same time
94  this->readDeferredInBackground(entities);
95  }
96 
98 
100  {
101  if (m_vatsimServerFileReader) { return m_vatsimServerFileReader->getFsdServers(); }
102  return {};
103  }
104 
106  {
107  if (m_vatsimStatusReader) { return m_vatsimStatusReader->getMetarFileUrl(); }
108  return {};
109  }
110 
112  {
113  if (m_vatsimStatusReader) { return m_vatsimStatusReader->getDataFileUrl(); }
114  return {};
115  }
116 
118  {
119  if (m_vatsimDataFileReader) { return m_vatsimDataFileReader->getUsersForCallsign(callsign); }
120  return {};
121  }
122 
124  {
125  if (m_vatsimDataFileReader) { return m_vatsimDataFileReader->getAtcStationsForCallsign(callsign); }
126  return {};
127  }
128 
130  {
131  if (m_vatsimDataFileReader) { return m_vatsimDataFileReader->getVoiceCapabilityForCallsign(callsign); }
132  return {};
133  }
134 
136  {
137  if (m_vatsimDataFileReader) { m_vatsimDataFileReader->updateWithVatsimDataFileData(aircraftToBeUdpated); }
138  }
139 
141  {
142  if (m_databaseWriter) { return m_databaseWriter->asyncPublishModels(modelsToBePublished, ""); }
143  return {};
144  }
145 
147  {
148  if (m_databaseWriter) { return m_databaseWriter->asyncAutoPublish(data); }
149  return {};
150  }
151 
152  void CWebDataServices::triggerReadOfDbInfoObjects() { initDbInfoObjectReaderAndTriggerRead(); }
153 
154  void CWebDataServices::triggerReadOfSharedInfoObjects() { initSharedInfoObjectReaderAndTriggerRead(); }
155 
157  {
158  if (!m_icaoDataReader && !m_modelDataReader && !m_airportDataReader && !m_dbInfoDataReader) { return false; }
159 
160  // use the first one to test
161  if (m_dbInfoDataReader) { return m_dbInfoDataReader->hasReceivedOkReply(); }
162  if (m_icaoDataReader) { return m_icaoDataReader->hasReceivedOkReply(); }
163  if (m_modelDataReader) { return m_modelDataReader->hasReceivedOkReply(); }
164  if (m_airportDataReader) { return m_airportDataReader->hasReceivedOkReply(); }
165  return false;
166  }
167 
168  bool CWebDataServices::hasDbAircraftData() const { return this->hasDbIcaoData() && this->hasDbModelData(); }
169 
171  {
172  return (this->getModelsCount() > 0) && (this->getLiveriesCount() > 0) && (this->getDistributorsCount() > 0);
173  }
174 
176  {
177  return (this->getAircraftIcaoCodesCount() > 0) && (this->getAirlineIcaoCodesCount() > 0) &&
178  (this->getCountriesCount() > 0);
179  }
180 
181  void CWebDataServices::admitDbCaches(CEntityFlags::Entity entities)
182  {
183  if (m_shuttingDown) { return; }
184 
185  // hint: those 2 are currently doing nothing, but this might change in the future
186  // if (m_dbInfoDataReader) { m_dbInfoDataReader->admitCaches(entities); }
187  // if (m_sharedInfoDataReader) { m_sharedInfoDataReader->admitCaches(entities); }
188 
189  // hint: all the readers use own threads
190  if (m_modelDataReader) { m_modelDataReader->admitCaches(entities); }
191  if (m_icaoDataReader) { m_icaoDataReader->admitCaches(entities); }
192  if (m_airportDataReader) { m_airportDataReader->admitCaches(entities); }
193  }
194 
195  void CWebDataServices::synchronizeDbCaches(CEntityFlags::Entity entities)
196  {
197  if (m_shuttingDown) { return; }
198 
199  // hint: those 2 are currently doing nothing, but this might change in the future
200  // if (m_dbInfoDataReader) { m_dbInfoDataReader->synchronizeCaches(entities); }
201  // if (m_sharedInfoDataReader) { m_sharedInfoDataReader->synchronizeCaches(entities); }
202 
203  // hint: all the readers use own threads
204  if (m_modelDataReader) { m_modelDataReader->synchronizeCaches(entities); }
205  if (m_icaoDataReader) { m_icaoDataReader->synchronizeCaches(entities); }
206  if (m_airportDataReader) { m_airportDataReader->synchronizeCaches(entities); }
207  }
208 
209  CEntityFlags::Entity CWebDataServices::triggerRead(CEntityFlags::Entity whatToRead, const QDateTime &newerThan)
210  {
211  if (m_shuttingDown) { return CEntityFlags::NoEntity; }
212 
213  Q_ASSERT_X(!whatToRead.testFlag(CEntityFlags::DbInfoObjectEntity), Q_FUNC_INFO,
214  "Info object must be read upfront");
215  Q_ASSERT_X(!whatToRead.testFlag(CEntityFlags::VatsimDataFile), Q_FUNC_INFO,
216  "Datafile is read periodically and should not be triggered manually!");
217  Q_ASSERT_X(!whatToRead.testFlag(CEntityFlags::MetarEntity), Q_FUNC_INFO,
218  "METAR file is read periodically and should not be triggered manually!");
219 
220  CEntityFlags::Entity triggeredRead = CEntityFlags::NoEntity;
221 
222  if (m_airportDataReader && whatToRead.testFlag(CEntityFlags::AirportEntity))
223  {
224  CEntityFlags::Entity airportEntities = whatToRead & CEntityFlags::AirportEntity;
225  m_airportDataReader->readInBackgroundThread(airportEntities, newerThan);
226  triggeredRead |= CEntityFlags::AirportEntity;
227  }
228 
229  const bool shouldReadIcaoData = whatToRead.testFlag(CEntityFlags::AircraftIcaoEntity) ||
230  whatToRead.testFlag(CEntityFlags::AircraftCategoryEntity) ||
231  whatToRead.testFlag(CEntityFlags::AirlineIcaoEntity) ||
232  whatToRead.testFlag(CEntityFlags::CountryEntity);
233  if (m_icaoDataReader && shouldReadIcaoData)
234  {
235  CEntityFlags::Entity icaoEntities = whatToRead & CEntityFlags::AllIcaoCountriesCategory;
236  m_icaoDataReader->readInBackgroundThread(icaoEntities, newerThan);
237  triggeredRead |= icaoEntities;
238  }
239 
240  const bool shouldReadModelData = whatToRead.testFlag(CEntityFlags::LiveryEntity) ||
241  whatToRead.testFlag(CEntityFlags::DistributorEntity) ||
242  whatToRead.testFlag(CEntityFlags::ModelEntity);
243  if (m_modelDataReader && shouldReadModelData)
244  {
245  CEntityFlags::Entity modelEntities = whatToRead & CEntityFlags::DistributorLiveryModel;
246  m_modelDataReader->readInBackgroundThread(modelEntities, newerThan);
247  triggeredRead |= modelEntities;
248  }
249 
250  return triggeredRead;
251  }
252 
253  CEntityFlags::Entity CWebDataServices::triggerLoadingDirectlyFromDb(CEntityFlags::Entity whatToRead,
254  const QDateTime &newerThan)
255  {
256  if (m_shuttingDown) { return CEntityFlags::NoEntity; }
257  if (!sApp || sApp->isShuttingDown()) { return CEntityFlags::NoEntity; }
258 
259  CEntityFlags::Entity triggeredRead = CEntityFlags::NoEntity;
260  if (m_dbInfoDataReader)
261  {
263  triggeredRead |= CEntityFlags::DbInfoObjectEntity;
264  }
265 
266  if (m_icaoDataReader)
267  {
268  if (m_icaoDataReader->supportsAnyOfEntities(whatToRead))
269  {
270  const CEntityFlags::Entity icaoEntities = m_icaoDataReader->maskBySupportedEntities(whatToRead);
271  m_icaoDataReader->triggerLoadingDirectlyFromDb(icaoEntities, newerThan);
272  triggeredRead |= icaoEntities;
273  }
274  }
275 
276  if (m_modelDataReader)
277  {
278  if (m_modelDataReader->supportsAnyOfEntities(whatToRead))
279  {
280  const CEntityFlags::Entity modelEntities = m_modelDataReader->maskBySupportedEntities(whatToRead);
281  m_modelDataReader->triggerLoadingDirectlyFromDb(modelEntities, newerThan);
282  triggeredRead |= modelEntities;
283  }
284  }
285 
286  if (m_airportDataReader)
287  {
288  if (m_airportDataReader->supportsAnyOfEntities(whatToRead))
289  {
290  const CEntityFlags::Entity airportEntities = m_airportDataReader->maskBySupportedEntities(whatToRead);
291  m_airportDataReader->triggerLoadingDirectlyFromDb(airportEntities, newerThan);
292  triggeredRead |= airportEntities;
293  }
294  }
295 
296  return triggeredRead;
297  }
298 
299  CEntityFlags::Entity CWebDataServices::triggerLoadingDirectlyFromSharedFiles(CEntityFlags::Entity whatToRead,
300  bool checkCacheTsUpfront)
301  {
302  if (m_shuttingDown) { return CEntityFlags::NoEntity; }
303  if (!sApp || sApp->isShuttingDown()) { return CEntityFlags::NoEntity; }
304 
305  CEntityFlags::Entity triggeredRead = CEntityFlags::NoEntity;
306  this->triggerReadOfSharedInfoObjects(); // trigger reload of info objects (for shared)
307 
308  if (m_icaoDataReader)
309  {
310  if (m_icaoDataReader->supportsAnyOfEntities(whatToRead))
311  {
312  CEntityFlags::Entity icaoEntities = m_icaoDataReader->maskBySupportedEntities(whatToRead);
313  triggeredRead |=
314  m_icaoDataReader->triggerLoadingDirectlyFromSharedFiles(icaoEntities, checkCacheTsUpfront);
315  }
316  }
317 
318  if (m_modelDataReader)
319  {
320  if (m_modelDataReader->supportsAnyOfEntities(whatToRead))
321  {
322  CEntityFlags::Entity modelEntities = m_modelDataReader->maskBySupportedEntities(whatToRead);
323  triggeredRead |=
324  m_modelDataReader->triggerLoadingDirectlyFromSharedFiles(modelEntities, checkCacheTsUpfront);
325  }
326  }
327 
328  if (m_airportDataReader)
329  {
330  if (m_airportDataReader->supportsAnyOfEntities(whatToRead))
331  {
332  CEntityFlags::Entity airportEntities = m_airportDataReader->maskBySupportedEntities(whatToRead);
333  triggeredRead |=
334  m_airportDataReader->triggerLoadingDirectlyFromSharedFiles(airportEntities, checkCacheTsUpfront);
335  }
336  }
337 
338  return triggeredRead;
339  }
340 
341  QDateTime CWebDataServices::getCacheTimestamp(CEntityFlags::Entity entity) const
342  {
343  Q_ASSERT_X(CEntityFlags::isSingleEntity(entity), Q_FUNC_INFO, "Need single entity");
344  if (!CEntityFlags::anySwiftDbEntity(entity)) { return {}; }
345  const CDatabaseReader *dr = this->getDbReader(entity);
346  if (!dr) { return {}; }
347  return dr->getCacheTimestamp(entity);
348  }
349 
350  QDateTime CWebDataServices::getLatestDbEntityTimestamp(CEntityFlags::Entity entity) const
351  {
352  Q_ASSERT_X(CEntityFlags::isSingleEntity(entity), Q_FUNC_INFO, "Need single entity");
353  if (!CEntityFlags::anySwiftDbEntity(entity)) { return {}; }
354  const CInfoDataReader *ir = this->getDbInfoDataReader();
355  if (!ir) { return {}; }
357  }
358 
359  QDateTime CWebDataServices::getLatestSharedInfoObjectTimestamp(CEntityFlags::Entity entity) const
360  {
361  const CDatabaseReader *reader = this->getDbReader(entity);
362  if (!reader) { return {}; }
363  Q_ASSERT_X(CEntityFlags::isSingleEntity(entity), Q_FUNC_INFO, "need single entity");
364  return reader->getLatestEntityTimestampFromSharedInfoObjects(entity);
365  }
366 
368  {
369  QDateTime latest;
370  const CEntityFlags::EntitySet set = CEntityFlags::asSingleEntities(CEntityFlags::AllDbEntitiesNoInfoObjects);
371  for (CEntityFlags::Entity e : set)
372  {
373  const QDateTime ts = this->getCacheTimestamp(e);
374  if (!ts.isValid()) { continue; }
375  if (!latest.isValid() || latest < ts) { latest = ts; }
376  }
377  return latest;
378  }
379 
380  CEntityFlags::Entity CWebDataServices::getEntitiesWithNewerSharedFile(CEntityFlags::Entity entities) const
381  {
382  Q_ASSERT_X(m_sharedInfoDataReader, Q_FUNC_INFO, "Shared info reader was not initialized");
383  if (m_sharedInfoDataReader->getInfoObjectCount() < 1) { return CEntityFlags::NoEntity; }
384  return m_sharedInfoDataReader->getEntitesWithNewerSharedInfoObject(entities);
385  }
386 
387  CEntityFlags::Entity CWebDataServices::getEmptyEntities(CEntityFlags::Entity entities) const
388  {
389  entities &= CEntityFlags::AllDbEntities; // handled by this reader
390  CEntityFlags::Entity currentEntity = CEntityFlags::iterateDbEntities(entities);
391  CEntityFlags::Entity emptyEntities = CEntityFlags::NoEntity;
392  while (currentEntity != CEntityFlags::NoEntity)
393  {
394  const int c = this->getCacheCount(currentEntity);
395  if (c < 1) { emptyEntities |= currentEntity; }
396  currentEntity = CEntityFlags::iterateDbEntities(entities);
397  }
398  return emptyEntities;
399  }
400 
401  CEntityFlags::Entity
402  CWebDataServices::getSynchronizedEntitiesWithNewerSharedFileOrEmpty(bool syncData, CEntityFlags::Entity entities)
403  {
404  CEntityFlags::Entity loadEntities = this->getEntitiesWithNewerSharedFile(entities);
405  const CEntityFlags::Entity checkForEmptyEntities =
406  CEntityFlags::entityFlagToEntity(CEntityFlags::AllDbEntitiesNoInfoObjects) & ~loadEntities;
407 
408  // it can happen the timestamps are not newer, but the data are empty
409  // - can happen if caches are copied and the TS does not represent the DB timestamp
410  // - cache files have been deleted
411  // - sync all DB entities
412  // - fast if there are no data
413  // - no impact if already synced
414  // - slow if newer synced before and all has to be done now
415  if (syncData) { this->synchronizeDbCaches(checkForEmptyEntities); }
416 
417  // we have no newer timestamps, but incomplete data
418  loadEntities |= this->getEmptyEntities();
419  return loadEntities;
420  }
421 
422  int CWebDataServices::getCacheCount(CEntityFlags::Entity entity) const
423  {
424  Q_ASSERT_X(CEntityFlags::isSingleEntity(entity), Q_FUNC_INFO, "Need single entity");
425  if (CEntityFlags::anySwiftDbEntity(entity))
426  {
427  const CDatabaseReader *dr = this->getDbReader(entity);
428  if (!dr) { return -1; }
429  return dr->getCacheCount(entity);
430  }
431  // non DB/shared entities would go here
432  return -1;
433  }
434 
435  int CWebDataServices::getDbInfoObjectCount(CEntityFlags::Entity entity) const
436  {
437  if (!m_dbInfoDataReader) { return -1; }
438  return this->getInfoObjectCount(entity, m_dbInfoDataReader);
439  }
440 
441  int CWebDataServices::getDbInfoObjectsCount(CEntityFlags::Entity entities, bool stopIfNotFound) const
442  {
443  if (!m_dbInfoDataReader) { return -1; }
444  int total = 0;
445  CEntityFlags::EntitySet set = CEntityFlags::asSingleEntities(entities);
446  for (CEntityFlags::Entity single : set)
447  {
448  const int c = this->getDbInfoObjectCount(single);
449  if (c < 0 && stopIfNotFound) { return -1; }
450  if (c > 0) { total += c; }
451  }
452  return total;
453  }
454 
455  int CWebDataServices::getSharedInfoObjectCount(CEntityFlags::Entity entity) const
456  {
457  if (!m_sharedInfoDataReader) return -1;
458  return this->getInfoObjectCount(entity, m_sharedInfoDataReader);
459  }
460 
461  QString CWebDataServices::getDbReadersLog(const QString &separator) const
462  {
463  QStringList report;
464  if (m_dbInfoDataReader)
465  {
466  report << m_dbInfoDataReader->getName() + ": " + m_dbInfoDataReader->getReadLog().getSummary();
467  }
468  if (m_sharedInfoDataReader)
469  {
470  report << m_sharedInfoDataReader->getName() + ": " + m_sharedInfoDataReader->getReadLog().getSummary();
471  }
472 
473  if (m_airportDataReader)
474  {
475  report << m_airportDataReader->getName() + ": " + m_airportDataReader->getReadLog().getSummary();
476  }
477  if (m_icaoDataReader)
478  {
479  report << m_icaoDataReader->getName() + ": " + m_icaoDataReader->getReadLog().getSummary();
480  }
481  if (m_modelDataReader)
482  {
483  report << m_modelDataReader->getName() + ": " + m_modelDataReader->getReadLog().getSummary();
484  }
485  if (m_databaseWriter)
486  {
487  report << m_databaseWriter->getName() + ": " + m_databaseWriter->getWriteLog().getSummary();
488  }
489  return report.join(separator);
490  }
491 
492  QString CWebDataServices::getReadersLog(const QString &separator) const
493  {
494  const QString db = this->getDbReadersLog(separator);
495  QStringList report;
496  if (m_vatsimMetarReader)
497  {
498  report << m_vatsimMetarReader->getName() + ": " + m_vatsimMetarReader->getReadLog().getSummary();
499  }
500  if (m_vatsimStatusReader)
501  {
502  report << m_vatsimStatusReader->getName() + ": " + m_vatsimStatusReader->getReadLog().getSummary();
503  }
504  if (report.isEmpty()) { return db; }
505  return report.join(separator) + separator + db;
506  }
507 
509  {
510  if (m_modelDataReader) { return m_modelDataReader->getDistributors(); }
511  return {};
512  }
513 
515  {
516  if (m_modelDataReader) { return m_modelDataReader->getDistributorsCount(); }
517  return 0;
518  }
519 
521  {
522  if (m_modelDataReader) { return m_modelDataReader->getDistributorForDbKey(key); }
523  return {};
524  }
525 
527  {
528  if (m_modelDataReader) { return m_modelDataReader->smartDistributorSelector(distributor); }
529  return {};
530  }
531 
533  const CAircraftModel &model) const
534  {
535  if (m_modelDataReader) { return m_modelDataReader->smartDistributorSelector(distributor, model); }
536  return {};
537  }
538 
540  {
541  if (m_modelDataReader) { return m_modelDataReader->getLiveries(); }
542  return {};
543  }
544 
546  {
547  if (m_modelDataReader) { return m_modelDataReader->getLiveriesCount(); }
548  return 0;
549  }
550 
551  CLivery CWebDataServices::getLiveryForCombinedCode(const QString &combinedCode) const
552  {
553  if (m_modelDataReader) { return m_modelDataReader->getLiveryForCombinedCode(combinedCode); }
554  return {};
555  }
556 
558  {
559  if (m_modelDataReader) { return m_modelDataReader->getLiveryForCombinedCode(CLivery::tempLiveryCode()); }
560  return {};
561  }
562 
564  {
565  if (m_modelDataReader) { return m_modelDataReader->getStdLiveryForAirlineVDesignator(icao); }
566  return {};
567  }
568 
570  {
571  if (m_modelDataReader) { return m_modelDataReader->getLiveryForDbKey(id); }
572  return {};
573  }
574 
576  {
577  if (m_modelDataReader) { return m_modelDataReader->smartLiverySelector(livery); }
578  return livery;
579  }
580 
582  {
583  if (m_modelDataReader) { return m_modelDataReader->getModels(); }
584  return {};
585  }
586 
588  {
589  if (m_modelDataReader) { return m_modelDataReader->getModelsCount(); }
590  return 0;
591  }
592 
594  {
595  if (m_modelDataReader) { return m_modelDataReader->getModelDbKeys(); }
596  return {};
597  }
598 
599  QStringList CWebDataServices::getModelStrings(bool sort) const
600  {
601  if (m_modelDataReader) { return m_modelDataReader->getModelStringList(sort); }
602  return {};
603  }
604 
605  QStringList CWebDataServices::getModelCompleterStrings(bool sorted, const CSimulatorInfo &simulator) const
606  {
607  if (m_modelDataReader) { return m_modelDataReader->getModels().toCompleterStrings(sorted, simulator); }
608  return {};
609  }
610 
613  const QString &combinedCode) const
614  {
615  if (m_modelDataReader)
616  {
617  return m_modelDataReader->getModelsForAircraftDesignatorAndLiveryCombinedCode(aircraftDesignator,
618  combinedCode);
619  }
620  return {};
621  }
622 
624  {
625  if (m_modelDataReader) { return m_modelDataReader->getModelForModelString(modelString); }
626  return {};
627  }
628 
629  bool CWebDataServices::containsModelString(const QString &modelString) const
630  {
631  if (m_modelDataReader) { return m_modelDataReader->containsModelString(modelString); }
632  return false;
633  }
634 
636  {
637  if (m_modelDataReader) { return m_modelDataReader->getModelForDbKey(dbKey); }
638  return {};
639  }
640 
642  {
643  if (m_icaoDataReader) { return m_icaoDataReader->getAircraftIcaoCodes(); }
644  return {};
645  }
646 
648  {
649  if (m_icaoDataReader) { return m_icaoDataReader->getAircraftIcaoCodesCount(); }
650  return 0;
651  }
652 
654  {
655  if (m_icaoDataReader) { return m_icaoDataReader->getAircraftIcaoCodeForDesignator(designator); }
656  return {};
657  }
658 
659  int CWebDataServices::getAircraftIcaoCodesForDesignatorCount(const QString &designator) const
660  {
661  return this->getAircraftIcaoCodesForDesignator(designator).size();
662  }
663 
665  {
666  if (!airline.hasValidDesignator()) { return {}; }
667  if (m_modelDataReader) { return m_modelDataReader->getAircraftDesignatorsForAirline(airline); }
668  return {};
669  }
670 
672  {
673  if (!airline.hasValidDesignator()) { return {}; }
674  if (m_modelDataReader) { return m_modelDataReader->getAicraftIcaoCodesForAirline(airline); }
675  return {};
676  }
677 
679  {
680  if (m_icaoDataReader) { return m_icaoDataReader->getAircraftCategories(); }
681  return {};
682  }
683 
685  {
686  if (m_icaoDataReader) { return m_icaoDataReader->getAircraftCategoryCount(); }
687  return 0;
688  }
689 
690  bool CWebDataServices::containsAircraftIcaoDesignator(const QString &designator) const
691  {
692  if (designator.isEmpty()) { return false; }
693  if (m_icaoDataReader) { return m_icaoDataReader->containsAircraftIcaoDesignator(designator); }
694  return false;
695  }
696 
698  {
699  if (m_icaoDataReader) { return m_icaoDataReader->getAircraftIcaoCodesForDesignator(designator); }
700  return {};
701  }
702 
704  {
705  if (m_icaoDataReader) { return m_icaoDataReader->getAircraftIcaoCodeForDbKey(key); }
706  return {};
707  }
708 
710  {
711  if (m_icaoDataReader) { return m_icaoDataReader->smartAircraftIcaoSelector(icao); }
712  return icao;
713  }
714 
716  {
717  if (m_icaoDataReader) { return m_icaoDataReader->getAirlineIcaoCodes(); }
718  return {};
719  }
720 
721  bool CWebDataServices::containsAirlineIcaoDesignator(const QString &designator) const
722  {
723  if (designator.isEmpty()) { return false; }
724  if (m_icaoDataReader) { return m_icaoDataReader->containsAirlineIcaoDesignator(designator); }
725  return false;
726  }
727 
730  bool preferOperatingAirlines) const
731  {
732  if (designator.isEmpty()) { return {}; }
733  if (m_icaoDataReader)
734  {
735  return m_icaoDataReader->getAirlineIcaoCodeForUniqueDesignatorOrDefault(designator,
736  preferOperatingAirlines);
737  }
738  return {};
739  }
740 
742  {
743  if (iataCode.isEmpty()) { return {}; }
744  if (m_icaoDataReader) { return m_icaoDataReader->getAirlineIcaoCodeForUniqueIataCodeOrDefault(iataCode); }
745  return {};
746  }
747 
749  {
750  if (m_icaoDataReader) { return m_icaoDataReader->getAirlineIcaoCodesCount(); }
751  return 0;
752  }
753 
755  {
756  QStringList names;
757  if (!m_icaoDataReader) { return names; }
758  for (const CAirlineIcaoCode &code : this->getAirlineIcaoCodes())
759  {
760  if (code.hasName()) { names.push_back(code.getName()); }
761  }
762  return names;
763  }
764 
766  {
767  QStringList designators;
768  if (!m_icaoDataReader) { return designators; }
769  for (const CAirlineIcaoCode &code : this->getAirlineIcaoCodes())
770  {
771  if (code.hasTelephonyDesignator()) { designators.push_back(code.getTelephonyDesignator()); }
772  }
773  return designators;
774  }
775 
777  const CCallsign &callsign) const
778  {
779  if (m_icaoDataReader) { return m_icaoDataReader->smartAirlineIcaoSelector(icaoPattern, callsign); }
780  return {};
781  }
782 
784  {
785  if (callsign.isEmpty()) { return {}; }
786  const CAirlineIcaoCodeList icaos(this->getAirlineIcaoCodes());
787  return icaos.findBestMatchByCallsign(callsign);
788  }
789 
791  {
792  if (m_icaoDataReader) { return m_icaoDataReader->getAirlineIcaoCodeForDbKey(key); }
793  return {};
794  }
795 
797  {
798  if (m_icaoDataReader) { return m_icaoDataReader->getCountries(); }
799  return {};
800  }
801 
803  {
804  if (m_icaoDataReader) { return m_icaoDataReader->getCountriesCount(); }
805  return 0;
806  }
807 
809  {
810  if (m_icaoDataReader) { return m_icaoDataReader->getCountryForName(name); }
811  return {};
812  }
813 
815  {
816  if (m_airportDataReader) { return m_airportDataReader->getAirports(); }
817  return {};
818  }
819 
821  {
822  if (m_airportDataReader) { return m_airportDataReader->getAirportsCount(); }
823  return 0;
824  }
825 
827  {
828  if (m_airportDataReader) { return m_airportDataReader->getAirportForIcaoDesignator(icao); }
829  return {};
830  }
831 
832  CAirport CWebDataServices::getAirportForNameOrLocation(const QString &nameOrLocation) const
833  {
834  if (m_airportDataReader) { return m_airportDataReader->getAirportForNameOrLocation(nameOrLocation); }
835  return {};
836  }
837 
839  {
840  if (m_icaoDataReader) { return m_icaoDataReader->getCountryForIsoCode(iso); }
841  return {};
842  }
843 
845  {
846  if (m_vatsimMetarReader) { return m_vatsimMetarReader->getMetars(); }
847  return {};
848  }
849 
851  {
852  if (m_vatsimMetarReader) { return m_vatsimMetarReader->getMetarForAirport(icao); }
853  return {};
854  }
855 
857  bool ignoreEqual, CAircraftModelList &validModels,
858  CAircraftModelList &invalidModels) const
859  {
860  CStatusMessageList msgs(
861  modelsToBePublished.validateForPublishing(validModels, invalidModels)); // technical validation
862 
863  // check against existing distributors
864  const CDistributorList distributors(this->getDistributors());
865  if (!distributors.isEmpty())
866  {
867  // only further check the valid ones
868  CAircraftModelList newValidModels;
869  const CStatusMessageList msgsDistributors(
870  validModels.validateDistributors(distributors, newValidModels, invalidModels));
871  validModels = newValidModels;
872  msgs.push_back(msgsDistributors);
873  }
874 
875  // check if model is changed
876  // in case of not ignoreEqual we just check create the messages
877  {
878  CAircraftModelList newValidModels;
879  for (const CAircraftModel &publishModel : validModels)
880  {
881  CStatusMessageList equalMessages;
882  const bool changed = !this->isDbModelEqualForPublishing(publishModel, &equalMessages);
883  if (changed)
884  {
885  // all good
886  newValidModels.push_back(publishModel);
887  continue;
888  }
889  if (ignoreEqual) { equalMessages.warningToError(); }
890  msgs.push_back(
892  u"Model: '%1', there is no change")
893  << publishModel.getModelString());
894  if (ignoreEqual) { invalidModels.push_back(publishModel); }
895  else { newValidModels.push_back(publishModel); }
896  }
897  validModels = newValidModels;
898  }
899  return msgs;
900  }
901 
903  CStatusMessageList *details) const
904  {
905  const CAircraftModel compareDbModel = modelToBeChecked.isLoadedFromDb() ?
906  this->getModelForDbKey(modelToBeChecked.getDbKey()) :
907  this->getModelForModelString(modelToBeChecked.getModelString());
908  return modelToBeChecked.isEqualForPublishing(compareDbModel, details);
909  }
910 
912  {
913  if (m_icaoDataReader) { return m_icaoDataReader->getAirlineIcaoCodesForDesignator(designator); }
914  return {};
915  }
916 
917  int CWebDataServices::getAirlineIcaoCodesForDesignatorCount(const QString &designator) const
918  {
919  return this->getAirlineIcaoCodesForDesignator(designator).size();
920  }
921 
923  {
924  if (m_shuttingDown) { return; }
925  m_shuttingDown = true;
926  this->disconnect(); // all signals
927  if (m_vatsimMetarReader)
928  {
929  m_vatsimMetarReader->quitAndWait();
930  m_vatsimMetarReader = nullptr;
931  }
932  if (m_vatsimDataFileReader)
933  {
934  m_vatsimDataFileReader->quitAndWait();
935  m_vatsimDataFileReader = nullptr;
936  }
937  if (m_vatsimStatusReader)
938  {
939  m_vatsimStatusReader->quitAndWait();
940  m_vatsimStatusReader = nullptr;
941  }
942  if (m_vatsimServerFileReader)
943  {
944  m_vatsimServerFileReader->quitAndWait();
945  m_vatsimServerFileReader = nullptr;
946  }
947  if (m_modelDataReader)
948  {
949  m_modelDataReader->quitAndWait();
950  m_modelDataReader = nullptr;
951  }
952  if (m_airportDataReader)
953  {
954  m_airportDataReader->quitAndWait();
955  m_airportDataReader = nullptr;
956  }
957  if (m_icaoDataReader)
958  {
959  m_icaoDataReader->quitAndWait();
960  m_icaoDataReader = nullptr;
961  }
962  if (m_dbInfoDataReader)
963  {
964  m_dbInfoDataReader->quitAndWait();
965  m_dbInfoDataReader = nullptr;
966  }
967 
968  // DB writer is no threaded reader, it has a special role
969  if (m_databaseWriter)
970  {
971  m_databaseWriter->gracefulShutdown();
972  m_databaseWriter = nullptr;
973  }
974  }
975 
977  {
978  // obtain entities from real readers (means when reader is really used)
979  CEntityFlags::Entity entities = CEntityFlags::NoEntity;
980  if (m_icaoDataReader) { entities |= CWebReaderFlags::allEntitiesForReaders(CWebReaderFlags::IcaoDataReader); }
981  if (m_modelDataReader) { entities |= CWebReaderFlags::allEntitiesForReaders(CWebReaderFlags::ModelReader); }
982  if (m_airportDataReader) { entities |= CWebReaderFlags::allEntitiesForReaders(CWebReaderFlags::AirportReader); }
983 
984  // when we have a config, we ignore the ones not from cache or DB
985  if (!m_dbReaderConfig.isEmpty())
986  {
987  CEntityFlags::Entity configuredEntities = m_dbReaderConfig.getEntitesCachedOrReadFromDB();
988  entities &= configuredEntities;
989  }
990 
991  entities &= CEntityFlags::AllDbEntities; // make sure to only use DB data
992  return entities;
993  }
994 
996  {
997  static const QStringList cats { "swift.datareader", CLogCategories::webservice() };
998  return cats;
999  }
1000 
1001  void CWebDataServices::initReaders(CWebReaderFlags::WebReader readersNeeded, CEntityFlags::Entity entities)
1002  {
1003  Q_ASSERT_X(CThreadUtils::thisIsMainThread(), Q_FUNC_INFO, "shall run in main application thread");
1004 
1005  //
1006  // ---- "metadata" reader, 1 will trigger read directly during init
1007  //
1008  const CEntityFlags::Entity dbEntities = entities & CEntityFlags::AllDbEntitiesNoInfoObjects;
1009  const bool anyDbEntities = CEntityFlags::anySwiftDbEntity(dbEntities); // contains any DB entities
1010  const bool needsSharedInfoObjects = m_dbReaderConfig.needsSharedInfoObjects(dbEntities);
1011  const bool needsDbInfoObjects = m_dbReaderConfig.possiblyReadsFromSwiftDb();
1012 
1013  // 1a. If any DB data, read the info objects upfront
1014  if (needsDbInfoObjects)
1015  {
1016  if (anyDbEntities && readersNeeded.testFlag(CWebReaderFlags::WebReaderFlag::DbInfoDataReader))
1017  {
1018  // info data reader has a special role, it will not be triggered in triggerRead()
1019  this->initDbInfoObjectReaderAndTriggerRead();
1020  }
1021  }
1022 
1023  // 1b. Read info objects if needed
1024  if (needsSharedInfoObjects) { this->initSharedInfoObjectReaderAndTriggerRead(); }
1025 
1026  // ---- data that is read once (triggered via readInBackgroundThread after initReaders finished)
1027 
1028  // 2. Status and server file, updating the VATSIM related caches
1029  if (readersNeeded.testFlag(CWebReaderFlags::VatsimStatusReader) ||
1030  readersNeeded.testFlag(CWebReaderFlags::VatsimServerFileReader))
1031  {
1032  startVatsimStatusFileReader();
1033  startVatsimServerFileReader();
1034  }
1035 
1036  // ---- periodically read data (via CThreadedReader/CContinousWorker)
1037 
1038  // 3. VATSIM data file
1039  if (readersNeeded.testFlag(CWebReaderFlags::WebReaderFlag::VatsimDataReader)) { startVatsimDataFileReader(); }
1040 
1041  // 4. VATSIM METAR data
1042  if (readersNeeded.testFlag(CWebReaderFlags::WebReaderFlag::VatsimMetarReader)) { startVatsimMetarFileReader(); }
1043 
1044  // ---- "normal data", triggerRead will start read, not starting directly
1045 
1046  // 5. ICAO data reader
1047  if (readersNeeded.testFlag(CWebReaderFlags::WebReaderFlag::IcaoDataReader)) { startIcaoDataReader(); }
1048 
1049  // 6. Model reader
1050  if (readersNeeded.testFlag(CWebReaderFlags::WebReaderFlag::ModelReader)) { startModelDataReader(); }
1051 
1052  // 7. Airport reader
1053  if (readersNeeded.testFlag(CWebReaderFlags::WebReaderFlag::AirportReader)) { startAirportDataReader(); }
1054 
1055  const QDateTime threshold =
1056  QDateTime::currentDateTimeUtc().addDays(-365); // country and airports are "semi static"
1057  const CEntityFlags::Entity cachedDbEntities =
1058  this->getDbEntitiesWithCachedData(); // those caches are already read
1059  const CEntityFlags::Entity validTsDbEntities =
1060  this->getDbEntitiesWithTimestampNewerThan(threshold); // those caches are not read, but have a timestamp
1061  const bool needsSharedInfoObjectsWithoutCache =
1062  m_dbReaderConfig.needsSharedInfoObjectsIfCachesEmpty(dbEntities, cachedDbEntities | validTsDbEntities);
1063  if (m_sharedInfoDataReader && !needsSharedInfoObjectsWithoutCache)
1064  {
1065  // demote error message
1066  // Rational: we cannot read shared info objects, but we have and use cached objects
1068  }
1069  }
1070 
1071  void CWebDataServices::startVatsimStatusFileReader()
1072  {
1073  Q_ASSERT_X(!m_vatsimStatusReader, Q_FUNC_INFO, "VATSIM status file reader already initialized");
1074  m_vatsimStatusReader = new CVatsimStatusFileReader(this);
1075  connect(m_vatsimStatusReader, &CVatsimStatusFileReader::statusFileRead, this,
1076  &CWebDataServices::vatsimStatusFileRead, Qt::QueuedConnection);
1077  CLogMessage(this).info(u"Trigger read of VATSIM status file");
1078  m_vatsimStatusReader->start(QThread::LowPriority);
1079 
1080  // run single shot in main loop, so readInBackgroundThread is not called before initReaders completes
1081  const QPointer<CWebDataServices> myself(this);
1082  QTimer::singleShot(0, this, [=]() {
1083  if (!myself || m_shuttingDown) { return; }
1084  if (!sApp || sApp->isShuttingDown()) { return; }
1085  m_vatsimStatusReader->readInBackgroundThread();
1086  });
1087  }
1088 
1089  void CWebDataServices::startVatsimServerFileReader()
1090  {
1091  Q_ASSERT_X(!m_vatsimServerFileReader, Q_FUNC_INFO, "VATSIM server file reader already initialized");
1092  m_vatsimServerFileReader = new CVatsimServerFileReader(this);
1093  bool c = connect(m_vatsimServerFileReader, &CVatsimServerFileReader::dataFileRead, this,
1094  &CWebDataServices::vatsimServerFileRead, Qt::QueuedConnection);
1095  Q_ASSERT_X(c, Q_FUNC_INFO, "VATSIM server reader signals");
1096  CLogMessage(this).info(u"Trigger read of VATSIM server file");
1097  m_vatsimServerFileReader->start(QThread::LowPriority);
1098 
1099  // run single shot in main loop, so readInBackgroundThread is not called before initReaders completes
1100  const QPointer<CWebDataServices> myself(this);
1101  QTimer::singleShot(0, this, [=]() {
1102  if (!myself || m_shuttingDown) { return; }
1103  if (!sApp || sApp->isShuttingDown()) { return; }
1104  m_vatsimServerFileReader->readInBackgroundThread();
1105  });
1106  }
1107 
1108  void CWebDataServices::startVatsimDataFileReader()
1109  {
1110  Q_ASSERT_X(!m_vatsimDataFileReader, Q_FUNC_INFO, "VATSIM data file reader already initialized");
1111  m_vatsimDataFileReader = new CVatsimDataFileReader(this);
1112  bool c = connect(m_vatsimDataFileReader, &CVatsimDataFileReader::dataFileRead, this,
1113  &CWebDataServices::vatsimDataFileRead, Qt::QueuedConnection);
1114  Q_ASSERT_X(c, Q_FUNC_INFO, "VATSIM data reader signals");
1115  c = connect(m_vatsimDataFileReader, &CVatsimDataFileReader::dataRead, this, &CWebDataServices::dataRead,
1116  Qt::QueuedConnection);
1117  Q_ASSERT_X(c, Q_FUNC_INFO, "connect failed VATSIM data file");
1118  m_entitiesPeriodicallyRead |= CEntityFlags::VatsimDataFile;
1119  m_vatsimDataFileReader->start(QThread::LowPriority);
1120  m_vatsimDataFileReader->startReader();
1121  }
1122 
1123  void CWebDataServices::startVatsimMetarFileReader()
1124  {
1125  Q_ASSERT_X(!m_vatsimMetarReader, Q_FUNC_INFO, "VATSIM METAR file reader already initialized");
1126  m_vatsimMetarReader = new CVatsimMetarReader(this);
1127  bool c = connect(m_vatsimMetarReader, &CVatsimMetarReader::metarsRead, this, &CWebDataServices::receivedMetars,
1128  Qt::QueuedConnection);
1129  Q_ASSERT_X(c, Q_FUNC_INFO, "VATSIM METAR reader signals");
1130  c = connect(m_vatsimMetarReader, &CVatsimMetarReader::dataRead, this, &CWebDataServices::dataRead,
1131  Qt::QueuedConnection);
1132  Q_ASSERT_X(c, Q_FUNC_INFO, "connect failed VATSIM METAR");
1133  m_entitiesPeriodicallyRead |= CEntityFlags::MetarEntity;
1134  m_vatsimMetarReader->start(QThread::LowPriority);
1135  m_vatsimMetarReader->startReader();
1136  }
1137 
1138  void CWebDataServices::startIcaoDataReader()
1139  {
1140  Q_ASSERT_X(!m_icaoDataReader, Q_FUNC_INFO, "ICAO data reader already initialized");
1141  m_icaoDataReader = new CIcaoDataReader(this, m_dbReaderConfig);
1142  bool c = connect(m_icaoDataReader, &CIcaoDataReader::dataRead, this, &CWebDataServices::readFromSwiftReader,
1143  Qt::QueuedConnection);
1144  Q_ASSERT_X(c, Q_FUNC_INFO, "Cannot connect ICAO reader signals");
1145  c = connect(m_icaoDataReader, &CIcaoDataReader::dataRead, this, &CWebDataServices::dataRead,
1146  Qt::QueuedConnection);
1147  Q_ASSERT_X(c, Q_FUNC_INFO, "Cannot connect ICAO reader signals");
1148  c = connect(m_icaoDataReader, &CIcaoDataReader::swiftDbDataRead, this, &CWebDataServices::swiftDbDataRead,
1149  Qt::QueuedConnection);
1150  Q_ASSERT_X(c, Q_FUNC_INFO, "Cannot connect Model reader signals");
1151  c = connect(m_icaoDataReader, &CIcaoDataReader::entityDownloadProgress, this,
1152  &CWebDataServices::entityDownloadProgress, Qt::QueuedConnection);
1153  Q_ASSERT_X(c, Q_FUNC_INFO, "Cannot connect Model reader signals");
1154  m_icaoDataReader->start(QThread::LowPriority);
1155  }
1156 
1157  void CWebDataServices::startModelDataReader()
1158  {
1159  Q_ASSERT_X(!m_modelDataReader, Q_FUNC_INFO, "Model data reader already initialized");
1160  m_modelDataReader = new CModelDataReader(this, m_dbReaderConfig);
1161  bool c = connect(m_modelDataReader, &CModelDataReader::dataRead, this, &CWebDataServices::readFromSwiftReader,
1162  Qt::QueuedConnection);
1163  Q_ASSERT_X(c, Q_FUNC_INFO, "Cannot connect Model reader signals");
1164  c = connect(m_modelDataReader, &CModelDataReader::dataRead, this, &CWebDataServices::dataRead,
1165  Qt::QueuedConnection);
1166  Q_ASSERT_X(c, Q_FUNC_INFO, "Cannot connect Model reader signals");
1167  c = connect(m_modelDataReader, &CModelDataReader::swiftDbDataRead, this, &CWebDataServices::swiftDbDataRead,
1168  Qt::QueuedConnection);
1169  Q_ASSERT_X(c, Q_FUNC_INFO, "Cannot connect Model reader signals");
1170  c = connect(m_modelDataReader, &CModelDataReader::entityDownloadProgress, this,
1171  &CWebDataServices::entityDownloadProgress, Qt::QueuedConnection);
1172  Q_ASSERT_X(c, Q_FUNC_INFO, "Cannot connect Model reader signals");
1173  m_modelDataReader->start(QThread::LowPriority);
1174  }
1175 
1176  void CWebDataServices::startAirportDataReader()
1177  {
1178  m_airportDataReader = new CAirportDataReader(this, m_dbReaderConfig);
1179  bool c = connect(m_airportDataReader, &CAirportDataReader::dataRead, this,
1180  &CWebDataServices::readFromSwiftReader, Qt::QueuedConnection);
1181  Q_ASSERT_X(c, Q_FUNC_INFO, "Cannot connect Model reader signals");
1182  c = connect(m_airportDataReader, &CAirportDataReader::dataRead, this, &CWebDataServices::dataRead,
1183  Qt::QueuedConnection);
1184  Q_ASSERT_X(c, Q_FUNC_INFO, "Cannot connect Model reader signals");
1185  c = connect(m_airportDataReader, &CAirportDataReader::swiftDbDataRead, this, &CWebDataServices::swiftDbDataRead,
1186  Qt::QueuedConnection);
1187  Q_ASSERT_X(c, Q_FUNC_INFO, "Cannot connect Model reader signals");
1188  c = connect(m_airportDataReader, &CAirportDataReader::entityDownloadProgress, this,
1189  &CWebDataServices::entityDownloadProgress, Qt::QueuedConnection);
1190  Q_ASSERT_X(c, Q_FUNC_INFO, "Cannot connect Model reader signals");
1191  m_airportDataReader->start(QThread::LowPriority);
1192  }
1193 
1194  void CWebDataServices::initDbInfoObjectReaderAndTriggerRead()
1195  {
1196  // run in correct thread
1197  if (m_shuttingDown) { return; }
1198  if (!CThreadUtils::isInThisThread(this))
1199  {
1200  const QPointer<CWebDataServices> myself(this);
1201  QTimer::singleShot(0, this, [=] {
1202  if (!myself || m_shuttingDown) { return; }
1203  if (!sApp || sApp->isShuttingDown()) { return; }
1204  this->initDbInfoObjectReaderAndTriggerRead();
1205  });
1206  return;
1207  }
1208 
1209  if (!m_dbInfoDataReader)
1210  {
1211  m_dbInfoDataReader = new CInfoDataReader(this, m_dbReaderConfig, CDbFlags::DbReading);
1212  m_dbInfoDataReader->setObjectName(m_dbInfoDataReader->objectName() + " (DB)");
1213  bool c =
1214  connect(m_dbInfoDataReader, &CInfoDataReader::dataRead, this, &CWebDataServices::readFromSwiftReader);
1215  Q_ASSERT_X(c, Q_FUNC_INFO, "Info reader connect failed");
1216 
1217  // relay signal
1218  c = connect(m_dbInfoDataReader, &CInfoDataReader::dataRead, this, &CWebDataServices::dataRead);
1219  Q_ASSERT_X(c, Q_FUNC_INFO, "Info reader connect failed");
1220  c = connect(m_dbInfoDataReader, &CInfoDataReader::databaseReaderMessages, this,
1222  Q_UNUSED(c)
1223 
1224  // start in own thread
1225  m_dbInfoDataReader->start(QThread::LowPriority);
1226 
1227  const QPointer<CWebDataServices> myself(this);
1228  QTimer::singleShot(25, m_dbInfoDataReader, [=]() {
1229  if (!myself || m_shuttingDown) { return; }
1230  if (!sApp || sApp->isShuttingDown()) { return; }
1231  m_dbInfoDataReader->readInfoData(); // trigger read of info objects
1232  });
1233  }
1234  }
1235 
1236  void CWebDataServices::initSharedInfoObjectReaderAndTriggerRead()
1237  {
1238  // run in correct thread
1239  if (m_shuttingDown) { return; }
1240  if (!CThreadUtils::isInThisThread(this))
1241  {
1242  const QPointer<CWebDataServices> myself(this);
1243  QTimer::singleShot(0, this, [=] {
1244  if (!myself || m_shuttingDown) { return; }
1245  this->initSharedInfoObjectReaderAndTriggerRead();
1246  });
1247  return;
1248  }
1249 
1250  if (!m_sharedInfoDataReader)
1251  {
1252  m_sharedInfoDataReader = new CInfoDataReader(this, m_dbReaderConfig, CDbFlags::Shared);
1253  m_sharedInfoDataReader->setObjectName(m_sharedInfoDataReader->objectName() + " (shared)");
1254  bool c = connect(m_sharedInfoDataReader, &CInfoDataReader::dataRead, this,
1255  &CWebDataServices::readFromSwiftReader);
1256  Q_ASSERT_X(c, Q_FUNC_INFO, "Info reader connect failed");
1257 
1258  // relay signal
1259  c = connect(m_sharedInfoDataReader, &CInfoDataReader::dataRead, this, &CWebDataServices::dataRead);
1260  Q_ASSERT_X(c, Q_FUNC_INFO, "Info reader connect failed");
1261  Q_UNUSED(c)
1262 
1263  // start in own thread
1264  m_sharedInfoDataReader->start(QThread::LowPriority);
1265  }
1266 
1267  // and trigger read
1268  const QPointer<CWebDataServices> myself(this);
1269  QTimer::singleShot(0, m_sharedInfoDataReader, [=]() {
1270  if (!myself || m_shuttingDown) { return; }
1271  m_sharedInfoDataReader->readInfoData();
1272  });
1273  }
1274 
1275  CDatabaseReader *CWebDataServices::getDbReader(CEntityFlags::Entity entity) const
1276  {
1277  Q_ASSERT_X(CEntityFlags::isSingleEntity(entity), Q_FUNC_INFO, "Need single entity");
1278  Q_ASSERT_X(CEntityFlags::anySwiftDbEntity(entity), Q_FUNC_INFO, "No swift DB entity");
1279 
1280  const CWebReaderFlags::WebReader wr = CWebReaderFlags::entitiesToReaders(entity);
1281  switch (wr)
1282  {
1283  case CWebReaderFlags::IcaoDataReader: return m_icaoDataReader;
1284  case CWebReaderFlags::ModelReader: return m_modelDataReader;
1285  case CWebReaderFlags::AirportReader: return m_airportDataReader;
1286  default: break;
1287  }
1288  return nullptr;
1289  }
1290 
1291  void CWebDataServices::initWriters()
1292  {
1293  m_databaseWriter = new CDatabaseWriter(sApp->getGlobalSetup().getDbRootDirectoryUrl(), this);
1294  }
1295 
1296  bool CWebDataServices::signalEntitiesAlreadyRead(CEntityFlags::Entity entities)
1297  {
1298  if (m_signalledEntities.contains(entities)) { return false; }
1299  m_signalledEntities.insert(entities);
1300  return true;
1301  }
1302 
1303  int CWebDataServices::getInfoObjectCount(CEntityFlags::Entity entity, CInfoDataReader *reader) const
1304  {
1305  Q_ASSERT_X(CEntityFlags::isSingleEntity(entity), Q_FUNC_INFO, "Need single entity");
1306  Q_ASSERT_X(reader, Q_FUNC_INFO, "Need reader");
1307  if (CEntityFlags::anySwiftDbEntity(entity))
1308  {
1309  const CDbInfo info = reader->getInfoObjects().findFirstByEntityOrDefault(entity);
1310  return info.getEntries();
1311  }
1312  // non DB entities would go here
1313  return -1;
1314  }
1315 
1316  CEntityFlags::Entity CWebDataServices::getDbEntitiesWithCachedData() const
1317  {
1318  CEntityFlags::Entity entities = CEntityFlags::NoEntity;
1319  if (m_airportDataReader) { entities |= m_airportDataReader->getEntitiesWithCacheCount(); }
1320  if (m_icaoDataReader) { entities |= m_icaoDataReader->getEntitiesWithCacheCount(); }
1321  if (m_modelDataReader) { entities |= m_modelDataReader->getEntitiesWithCacheCount(); }
1322  return entities;
1323  }
1324 
1325  CEntityFlags::Entity CWebDataServices::getDbEntitiesWithTimestampNewerThan(const QDateTime &threshold) const
1326  {
1327  CEntityFlags::Entity entities = CEntityFlags::NoEntity;
1328  if (m_airportDataReader) { entities |= m_airportDataReader->getEntitiesWithCacheTimestampNewerThan(threshold); }
1329  if (m_icaoDataReader) { entities |= m_icaoDataReader->getEntitiesWithCacheTimestampNewerThan(threshold); }
1330  if (m_modelDataReader) { entities |= m_modelDataReader->getEntitiesWithCacheTimestampNewerThan(threshold); }
1331  return entities;
1332  }
1333 
1334  void CWebDataServices::receivedMetars(const CMetarList &metars)
1335  {
1336  CLogMessage(this).info(u"Read %1 METARs") << metars.size();
1337  }
1338 
1339  void CWebDataServices::vatsimDataFileRead(int kB) { CLogMessage(this).info(u"Read VATSIM data file, %1 kB") << kB; }
1340 
1341  void CWebDataServices::vatsimStatusFileRead(int bytes)
1342  {
1343  CLogMessage(this).info(u"Read VATSIM status file, %1 bytes") << bytes;
1344  }
1345 
1346  void CWebDataServices::vatsimServerFileRead(int bytes)
1347  {
1348  CLogMessage(this).info(u"Read VATSIM server file, %1 bytes") << bytes;
1349  }
1350 
1351  void CWebDataServices::readFromSwiftReader(CEntityFlags::Entity entities, CEntityFlags::ReadState state, int number,
1352  const QUrl &url)
1353  {
1354  if (state == CEntityFlags::ReadStarted) { return; } // just started
1355 
1356  const QString from = url.isEmpty() ? QStringLiteral("") : QStringLiteral(" from '%1'").arg(url.toString());
1357  const QString entStr = CEntityFlags::entitiesToString(entities);
1358 
1359  if (CEntityFlags::isWarningOrAbove(state))
1360  {
1361  const CStatusMessage::StatusSeverity severity = CEntityFlags::flagToSeverity(state);
1362  if (severity == CStatusMessage::SeverityWarning)
1363  {
1364  CLogMessage(this).warning(u"Read data '%1' entries: %2 state: %3%4")
1365  << entStr << number << CEntityFlags::stateToString(state) << from;
1366  }
1367  else
1368  {
1369  CLogMessage(this).error(u"Read data '%1' entries: %2 state: %3%4")
1370  << entStr << number << CEntityFlags::stateToString(state) << from;
1371  }
1372  }
1373  else
1374  {
1375  CLogMessage(this).info(u"Read data '%1' entries: %2 state: %3%4")
1376  << entStr << number << CEntityFlags::stateToString(state) << from;
1377  }
1378 
1379  m_swiftDbEntitiesRead |= entities;
1380  const int allUsedEntities = static_cast<int>(this->allDbEntitiesForUsedReaders());
1381  if (((static_cast<int>(m_swiftDbEntitiesRead)) & allUsedEntities) == allUsedEntities)
1382  {
1383  emit this->swiftDbAllDataRead();
1384  }
1385 
1386  // individual signals
1387  if (CEntityFlags::isFinishedReadState(state))
1388  {
1389  // emit one time only
1390  if (entities.testFlag(CEntityFlags::AirportEntity) &&
1391  signalEntitiesAlreadyRead(CEntityFlags::AirportEntity))
1392  {
1393  emit swiftDbAirportsRead();
1394  }
1395  if (entities.testFlag(CEntityFlags::AirlineIcaoEntity) &&
1396  signalEntitiesAlreadyRead(CEntityFlags::AirlineIcaoEntity))
1397  {
1398  emit swiftDbAirlineIcaoRead();
1399  }
1400  if (entities.testFlag(CEntityFlags::AircraftIcaoEntity) &&
1401  signalEntitiesAlreadyRead(CEntityFlags::AircraftIcaoEntity))
1402  {
1403  emit swiftDbAircraftIcaoRead();
1404  }
1405  if (entities.testFlag(CEntityFlags::ModelEntity) && signalEntitiesAlreadyRead(CEntityFlags::ModelEntity))
1406  {
1407  emit swiftDbModelsRead();
1408  }
1409  if (entities.testFlag(CEntityFlags::SharedInfoObjectEntity)) { emit sharedInfoObjectsRead(); }
1410 
1411  if (m_swiftDbEntitiesRead.testFlag(CEntityFlags::AllIcaoEntities) &&
1412  signalEntitiesAlreadyRead(CEntityFlags::AllIcaoEntities))
1413  {
1414  emit this->swiftDbAllIcaoEntitiesRead();
1415  }
1416  if (m_swiftDbEntitiesRead.testFlag(CEntityFlags::ModelMatchingEntities) &&
1417  signalEntitiesAlreadyRead(CEntityFlags::ModelMatchingEntities))
1418  {
1419  emit this->swiftDbModelMatchingEntitiesRead();
1420  }
1421  }
1422  }
1423 
1424  void CWebDataServices::readDeferredInBackground(CEntityFlags::Entity entities)
1425  {
1426  if (m_shuttingDown) { return; }
1427  if (entities == CEntityFlags::NoEntity) { return; }
1428  const QPointer<CWebDataServices> myself(this);
1429  QTimer::singleShot(0, [=]() // clazy:exclude=connect-3arg-lambda
1430  {
1431  if (!myself || m_shuttingDown) { return; }
1432  this->readInBackground(entities); // deferred
1433  });
1434  }
1435 
1436  void CWebDataServices::readInBackground(CEntityFlags::Entity entities)
1437  {
1438  if (m_shuttingDown) { return; }
1439 
1440  if (CEntityFlags::anySwiftDbEntity(entities))
1441  {
1442  // with info objects wait until info objects are loaded
1443  Q_ASSERT_X(!entities.testFlag(CEntityFlags::DbInfoObjectEntity), Q_FUNC_INFO,
1444  "Info object must be read upfront, do not pass as entity here");
1445  const bool waitForDbInfoReader = m_dbInfoDataReader && !m_dbInfoDataReader->areAllInfoObjectsRead() &&
1446  !m_dbInfoDataReader->isMarkedAsFailed();
1447  if (waitForDbInfoReader)
1448  {
1449  // do not read yet, will call this function again after some time
1450  if (!this->waitForDbInfoObjectsThenRead(entities)) { return; }
1451  }
1452 
1453  const bool waitForSharedInfoFile =
1454  m_dbReaderConfig.needsSharedInfoFile(entities) && !m_sharedInfoDataReader->areAllInfoObjectsRead();
1455  if (waitForSharedInfoFile)
1456  {
1457  // do not read yet, will call this function again after some time
1458  if (!this->waitForSharedInfoObjectsThenRead(entities)) { return; }
1459  }
1460  }
1461 
1462  // read entities
1463  this->triggerRead(entities);
1464  }
1465 
1466  bool CWebDataServices::waitForDbInfoObjectsThenRead(CEntityFlags::Entity entities)
1467  {
1468  if (m_shuttingDown) { return false; }
1469 
1470  Q_ASSERT_X(m_dbInfoDataReader, Q_FUNC_INFO, "need reader");
1471 
1472  // in a dev build all symbols are loaded which sometimes causes unnecessary timeout
1473  if (m_dbInfoDataReader->areAllInfoObjectsRead()) { return true; }
1474  const int timeOutMs = 30 * 1000;
1475  if (!m_dbInfoObjectTimeout.isValid())
1476  {
1477  m_dbInfoObjectTimeout = QDateTime::currentDateTimeUtc().addMSecs(timeOutMs);
1478  CLogMessage(this).info(u"Set DbInfoObjects timeout %1ms to %2")
1479  << timeOutMs << m_dbInfoObjectTimeout.toString("dd.MM.yyyy hh:mm:ss");
1480  }
1481  const bool read = this->waitForInfoObjectsThenRead(entities, "DB", m_dbInfoDataReader, m_dbInfoObjectTimeout);
1482  return read;
1483  }
1484 
1485  bool CWebDataServices::waitForSharedInfoObjectsThenRead(CEntityFlags::Entity entities)
1486  {
1487  if (m_shuttingDown) { return false; }
1488 
1489  Q_ASSERT_X(m_sharedInfoDataReader, Q_FUNC_INFO, "need reader");
1490  if (m_sharedInfoDataReader->areAllInfoObjectsRead()) { return true; }
1491  const int timeOutMs = 30 * 1000;
1492  if (!m_sharedInfoObjectsTimeout.isValid())
1493  {
1494  m_sharedInfoObjectsTimeout = QDateTime::currentDateTimeUtc().addMSecs(timeOutMs);
1495  CLogMessage(this).info(u"Set SharedInfoObjects timeout %1ms to %2")
1496  << timeOutMs << m_sharedInfoObjectsTimeout.toString("dd.MM.yyyy hh:mm:ss");
1497  }
1498  const bool read =
1499  this->waitForInfoObjectsThenRead(entities, "shared", m_sharedInfoDataReader, m_sharedInfoObjectsTimeout);
1500  return read;
1501  }
1502 
1503  bool CWebDataServices::waitForInfoObjectsThenRead(CEntityFlags::Entity entities, const QString &info,
1504  CInfoDataReader *infoReader, QDateTime &timeOut)
1505  {
1506  if (m_shuttingDown) { return false; }
1507 
1508  // this will called for each entity readers, i.e. model reader, ICAO reader ...
1509  Q_ASSERT_X(infoReader, Q_FUNC_INFO, "Need info data reader");
1510 
1511  if (infoReader->areAllInfoObjectsRead())
1512  {
1513  // we have all data and carry on
1514  CLogMessage(this).info(u"Info objects (%1) triggered for '%2' loaded from '%3'")
1515  << info << CEntityFlags::entitiesToString(entities) << infoReader->getInfoObjectsUrl().toQString();
1516  timeOut = QDateTime(); // reset to null
1517  return true; // no need to wait any longer
1518  }
1519 
1520  // try to read if not timed out
1521  if (timeOut.isValid() && QDateTime::currentDateTimeUtc() > timeOut)
1522  {
1523  const QString timeOutString = timeOut.toString();
1524  const CStatusMessage m =
1525  CLogMessage(this).warning(u"Could not read '%1' info objects for '%2' from '%3', time out '%4'. "
1526  u"Marking reader '%5' as failed and continue.")
1527  << info << CEntityFlags::entitiesToString(entities) << infoReader->getInfoObjectsUrl().toQString()
1528  << timeOutString << infoReader->getName();
1529  emit this->databaseReaderMessages(m);
1530 
1531  // continue here and read data without info objects
1532  infoReader->setMarkedAsFailed(true);
1533  // no timeout reset here
1534  return true; // carry on, regardless of situation
1535  }
1536 
1537  if (infoReader->hasReceivedFirstReply())
1538  {
1539  // we have received a response, but not all data yet
1540  if (infoReader->hasReceivedOkReply())
1541  {
1542  // ok, this means we are parsing
1543  this->readDeferredInBackground(entities);
1544  const CStatusMessage m = CLogMessage(this).info(u"Parsing objects (%1) for '%2' from '%3'")
1545  << info << CEntityFlags::entitiesToString(entities)
1546  << infoReader->getInfoObjectsUrl().toQString();
1547  emit this->databaseReaderMessages(m);
1548  return false; // wait
1549  }
1550 
1551  // we have a response, but a failure, means server is alive, but responded with error
1552  // such an error (access, ...) normally will not go away
1553  const CStatusMessage m =
1554  CLogMessage(this).error(u"Info objects (%1) loading for '%2' failed from '%3', '%4'")
1555  << info << CEntityFlags::entitiesToString(entities) << infoReader->getInfoObjectsUrl().toQString()
1556  << infoReader->getStatusMessage();
1557  infoReader->setMarkedAsFailed(true);
1558  emit this->databaseReaderMessages(m);
1559  return true; // carry on, regardless of situation
1560  }
1561 
1562  // wait for 1st reply
1563  // we call read again in some time
1564  this->readDeferredInBackground(entities);
1565  return false; // wait
1566  }
1567 
1568  bool CWebDataServices::writeDbDataToDisk(const QString &dir)
1569  {
1570  if (dir.isEmpty()) { return false; }
1571  const QDir directory(dir);
1572  if (!directory.exists())
1573  {
1574  const bool s = directory.mkpath(dir);
1575  if (!s) { return false; }
1576  }
1577  QList<QPair<QString, QString>> fileContents;
1578 
1579  if (this->getModelsCount() > 0)
1580  {
1581  const QString json(QJsonDocument(this->getModels().toJson()).toJson());
1582  fileContents.push_back({ "models.json", json });
1583  }
1584 
1585  if (this->getLiveriesCount() > 0)
1586  {
1587  const QString json(QJsonDocument(this->getLiveries().toJson()).toJson());
1588  fileContents.push_back({ "liveries.json", json });
1589  }
1590 
1591  if (this->getAirportsCount() > 0)
1592  {
1593  const QString json(QJsonDocument(this->getAirports().toJson()).toJson());
1594  fileContents.push_back({ "airports.json", json });
1595  }
1596 
1597  for (const auto &pair : fileContents)
1598  {
1599  CWorker::fromTask(this, Q_FUNC_INFO, [pair, directory] {
1600  CFileUtils::writeStringToFile(CFileUtils::appendFilePaths(directory.absolutePath(), pair.first),
1601  pair.second);
1602  });
1603  }
1604  return true;
1605  }
1606 
1607  bool CWebDataServices::readDbDataFromDisk(const QString &dir, bool inBackground, bool overrideNewerOnly)
1608  {
1609  if (dir.isEmpty()) { return false; }
1610  const QDir directory(dir);
1611  if (!directory.exists()) { return false; }
1612 
1613  bool s1 = !m_icaoDataReader;
1614  if (m_icaoDataReader)
1615  {
1616  // force update to background reading if reader is already in another thread
1617  bool ib = inBackground || !CThreadUtils::isInThisThread(m_icaoDataReader);
1618  if (ib)
1619  {
1620  CLogMessage(this).info(u"Reading from disk in background: %1")
1621  << m_icaoDataReader->getSupportedEntitiesAsString();
1622  s1 = m_icaoDataReader->readFromJsonFilesInBackground(dir, m_icaoDataReader->getSupportedEntities(),
1623  overrideNewerOnly);
1624  }
1625  else
1626  {
1627  const CStatusMessageList msgs = m_icaoDataReader->readFromJsonFiles(
1628  dir, m_icaoDataReader->getSupportedEntities(), overrideNewerOnly);
1630  s1 = msgs.isSuccess();
1631  }
1632  }
1633 
1634  bool s2 = !m_modelDataReader;
1635  if (m_modelDataReader)
1636  {
1637  // force update to background reading if reader is already in another thread
1638  bool ib = inBackground || !CThreadUtils::isInThisThread(m_modelDataReader);
1639  if (ib)
1640  {
1641  CLogMessage(this).info(u"Reading from disk in background: %1")
1642  << m_modelDataReader->getSupportedEntitiesAsString();
1643  s2 = m_modelDataReader->readFromJsonFilesInBackground(dir, m_modelDataReader->getSupportedEntities(),
1644  overrideNewerOnly);
1645  }
1646  else
1647  {
1648  const CStatusMessageList msgs = m_modelDataReader->readFromJsonFiles(
1649  dir, m_modelDataReader->getSupportedEntities(), overrideNewerOnly);
1651  s2 = msgs.isSuccess();
1652  }
1653  }
1654 
1655  bool s3 = !m_airportDataReader;
1656  if (m_airportDataReader)
1657  {
1658  // force update to background reading if reader is already in another thread
1659  bool ib = inBackground || !CThreadUtils::isInThisThread(m_airportDataReader);
1660  if (ib)
1661  {
1662  CLogMessage(this).info(u"Reading from disk in background: %1")
1663  << m_airportDataReader->getSupportedEntitiesAsString();
1664  s3 = m_airportDataReader->readFromJsonFilesInBackground(
1665  dir, m_airportDataReader->getSupportedEntities(), overrideNewerOnly);
1666  }
1667  else
1668  {
1669  const CStatusMessageList msgs = m_airportDataReader->readFromJsonFiles(
1670  dir, m_airportDataReader->getSupportedEntities(), overrideNewerOnly);
1672  s3 = msgs.isSuccess();
1673  }
1674  }
1675 
1676  return s1 && s2 && s3;
1677  }
1678 
1680  {
1681  CStatusMessageList msgs;
1682  msgs.push_back(m_icaoDataReader ? m_icaoDataReader->initFromLocalResourceFiles(inBackground) :
1683  CStatusMessage(this).info(u"No ICAO reader"));
1684  msgs.push_back(m_modelDataReader ? m_modelDataReader->initFromLocalResourceFiles(inBackground) :
1685  CStatusMessage(this).info(u"No model reader"));
1686  msgs.push_back(m_airportDataReader ? m_airportDataReader->initFromLocalResourceFiles(inBackground) :
1687  CStatusMessage(this).info(u"No airport reader"));
1688  return msgs;
1689  }
1690 
1693  bool inBackground)
1694  {
1695  CStatusMessageList msgs;
1696  msgs.push_back(m_icaoDataReader && m_icaoDataReader->supportsAnyOfEntities(entities) ?
1697  m_icaoDataReader->initFromLocalResourceFiles(entities, inBackground) :
1698  CStatusMessage(this).info(u"No ICAO reader or not supporting entities"));
1699  msgs.push_back(m_modelDataReader && m_modelDataReader->supportsAnyOfEntities(entities) ?
1700  m_modelDataReader->initFromLocalResourceFiles(entities, inBackground) :
1701  CStatusMessage(this).info(u"No model reader or not supporting entities"));
1702  msgs.push_back(m_airportDataReader && m_airportDataReader->supportsAnyOfEntities(entities) ?
1703  m_airportDataReader->initFromLocalResourceFiles(entities, inBackground) :
1704  CStatusMessage(this).info(u"No airport reader or not supporting entities"));
1705  return msgs;
1706  }
1708 } // namespace swift::core
SWIFT_CORE_EXPORT swift::core::CApplication * sApp
Single instance of application object.
Definition: application.cpp:71
data::CGlobalSetup getGlobalSetup() const
Global setup.
bool isShuttingDown() const
Is application shutting down?
bool isSetupAvailable() const
Setup already synchronized.
swift::misc::network::CUrlLogList getReadLog() const
Get the read log.
void setMarkedAsFailed(bool failed)
Set marker for read failed.
bool isMarkedAsFailed() const
Is marked as read failed.
void databaseReaderMessages(const swift::misc::CStatusMessageList &messages)
Database reader messages.
swift::misc::network::CEntityFlags::Entity allDbEntitiesForUsedReaders() const
All DB entities for those readers used and not ignored.
swift::misc::network::CServerList getVatsimFsdServers() const
FSD servers.
int getSharedInfoObjectCount(swift::misc::network::CEntityFlags::Entity entity) const
Count for entity from shared entity objects.
swift::misc::CStatusMessageList asyncPublishModels(const swift::misc::simulation::CAircraftModelList &modelsToBePublished) const
Publish models to database.
bool hasDbModelData() const
Are DB model data available?
void swiftDbAirportsRead()
Airports read.
swift::misc::aviation::CAircraftIcaoCode smartAircraftIcaoSelector(const swift::misc::aviation::CAircraftIcaoCode &icao) const
Use an ICAO object to select the best complete ICAO object from DB for it.
void sharedInfoObjectsRead()
Shared info objects read.
swift::misc::network::CUserList getUsersForCallsign(const swift::misc::aviation::CCallsign &callsign) const
Users by callsign.
bool containsModelString(const QString &modelString) const
Existing modelstring?
swift::misc::aviation::CAirlineIcaoCode findBestMatchByCallsign(const swift::misc::aviation::CCallsign &callsign) const
ICAO code for callsign (e.g. DLH123 -> DLH)
int getDistributorsCount() const
Distributors count.
QSet< int > getModelDbKeys() const
Model keys.
swift::misc::weather::CMetar getMetarForAirport(const swift::misc::aviation::CAirportIcaoCode &icao) const
Get METAR for airport.
swift::misc::aviation::CAirlineIcaoCodeList getAirlineIcaoCodesForDesignator(const QString &designator) const
Airline ICAO codes for designator.
int getModelsCount() const
Models count.
bool hasSuccesfullyConnectedSwiftDb() const
Has already successfully connect swift DB?
void swiftDbModelsRead()
All models read.
swift::misc::CCountryList getCountries() const
Countries.
swift::core::db::CInfoDataReader * getDbInfoDataReader() const
DB info data reader.
void readInBackground(swift::misc::network::CEntityFlags::Entity entities=swift::misc::network::CEntityFlags::AllEntities)
First read (allows to immediately read in background)
swift::misc::aviation::CAircraftIcaoCode getAircraftIcaoCodeForDesignator(const QString &designator) const
ICAO code for designator.
QDateTime getLatestDbEntityTimestamp(swift::misc::network::CEntityFlags::Entity entity) const
Corresponding DB timestamp if applicable.
void updateWithVatsimDataFileData(swift::misc::simulation::CSimulatedAircraft &aircraftToBeUdpated) const
Update with web data.
QString getDbReadersLog(const QString &separator="\n") const
For all available DB readers the log info is generated.
swift::misc::aviation::CLivery getStdLiveryForAirlineCode(const swift::misc::aviation::CAirlineIcaoCode &icao) const
Standard livery for airline code.
swift::misc::aviation::CAircraftIcaoCodeList getAircraftIcaoCodesForAirline(const swift::misc::aviation::CAirlineIcaoCode &airline) const
Aircraft ICAO codes for airline.
swift::misc::network::CVoiceCapabilities getVoiceCapabilityForCallsign(const swift::misc::aviation::CCallsign &callsign) const
Voice capabilities for given callsign.
int getAircraftCategoriesCount() const
Aircraft categories count.
swift::misc::CStatusMessageList asyncAutoPublish(const swift::misc::simulation::CAutoPublishData &data) const
Auto publish to database.
QStringList getModelCompleterStrings(bool sorted=true, const swift::misc::simulation::CSimulatorInfo &simulator={ swift::misc::simulation::CSimulatorInfo::All }) const
Model completer string.
swift::misc::weather::CMetarList getMetars() const
Get METARs.
swift::misc::network::CEntityFlags::Entity triggerLoadingDirectlyFromSharedFiles(swift::misc::network::CEntityFlags::Entity whatToRead, bool checkCacheTsUpfront)
Trigger reload from shared files, loads the data and bypasses caches.
int getDbInfoObjectsCount(swift::misc::network::CEntityFlags::Entity entities, bool stopIfNotFound=true) const
Count for 1-n entities from DB entity objects.
static const QStringList & getLogCategories()
Log categories.
swift::misc::simulation::CAircraftModelList getModels() const
Models.
swift::misc::network::CUrl getVatsimMetarUrl() const
METAR URL (from status file)
QDateTime getCacheTimestamp(swift::misc::network::CEntityFlags::Entity entity) const
Corresponding cache timestamp if applicable.
void entityDownloadProgress(swift::misc::network::CEntityFlags::Entity entity, int logId, int progress, qint64 current, qint64 max, const QUrl &url)
Download progress for an entity.
swift::misc::aviation::CAirlineIcaoCode getAirlineIcaoCodeForDbKey(int key) const
ICAO code for id.
swift::misc::simulation::CDistributorList getDistributors() const
Distributors.
QDateTime getLatestDbEntityCacheTimestamp() const
Latest DB object timestamp, or null if there is no such timestamp.
int getCountriesCount() const
Country count.
int getAircraftIcaoCodesForDesignatorCount(const QString &designator) const
ICAO code for designator count.
QDateTime getLatestSharedInfoObjectTimestamp(swift::misc::network::CEntityFlags::Entity entity) const
Shared info object timestamp.
bool isDbModelEqualForPublishing(const swift::misc::simulation::CAircraftModel &modelToBeChecked, swift::misc::CStatusMessageList *details=nullptr) const
Considered equal for publishing, compares if livery etc. are the same DB values.
QString getReadersLog(const QString &separator="\n") const
For all available readers the log info is generated.
swift::misc::CStatusMessageList validateForPublishing(const swift::misc::simulation::CAircraftModelList &modelsToBePublished, bool ignoreEqual, swift::misc::simulation::CAircraftModelList &validModels, swift::misc::simulation::CAircraftModelList &invalidModels) const
Validate for publishing.
swift::misc::CStatusMessageList initDbCachesFromLocalResourceFiles(bool inBackground)
Init caches from local DB files.
swift::misc::aviation::CAircraftIcaoCodeList getAircraftIcaoCodesForDesignator(const QString &designator) const
ICAO codes for designator.
swift::misc::network::CEntityFlags::Entity getEmptyEntities(swift::misc::network::CEntityFlags::Entity entities=swift::misc::network::CEntityFlags::AllDbEntities) const
Empty entities in cache.
swift::misc::aviation::CAirport getAirportForIcaoDesignator(const QString &icao) const
Get airport for ICAO designator.
swift::misc::network::CEntityFlags::Entity getSynchronizedEntitiesWithNewerSharedFileOrEmpty(bool syncData=true, swift::misc::network::CEntityFlags::Entity entities=swift::misc::network::CEntityFlags::AllDbEntities)
Synchronized entities either empty or with newer shared file.
swift::misc::network::CEntityFlags::Entity triggerLoadingDirectlyFromDb(swift::misc::network::CEntityFlags::Entity whatToRead, const QDateTime &newerThan=QDateTime())
Trigger reload from DB, loads the DB data and bypasses the caches checks and info objects.
swift::misc::simulation::CAircraftModel getModelForDbKey(int dbKey) const
Model for key if any.
void readDeferredInBackground(swift::misc::network::CEntityFlags::Entity entities)
Call CWebDataServices::readInBackground by single shot.
int getAirportsCount() const
Get airports count.
swift::misc::network::CEntityFlags::Entity triggerRead(swift::misc::network::CEntityFlags::Entity whatToRead, const QDateTime &newerThan=QDateTime())
Trigger read of new data.
void synchronizeDbCaches(swift::misc::network::CEntityFlags::Entity entities)
Synchronize all DB caches specified.
swift::misc::aviation::CAirlineIcaoCode getAirlineIcaoCodeForUniqueIataCodeOrDefault(const QString &iataCode) const
ICAO code if unique, otherwise default.
void triggerReadOfSharedInfoObjects()
Trigger read of shared info objects.
QStringList getTelephonyDesignators() const
Airline telephony designators.
CWebDataServices(CWebReaderFlags::WebReader readerFlags, const swift::core::db::CDatabaseReaderConfigList &dbReaderConfig, QObject *parent=nullptr)
Constructor, only allowed from swift::core::CApplication.
swift::misc::simulation::CAircraftModel getModelForModelString(const QString &modelString) const
Model for model string if any.
swift::misc::network::CEntityFlags::Entity getEntitiesWithNewerSharedFile(swift::misc::network::CEntityFlags::Entity entities) const
Entities with newer shared file (from DB Info object)
swift::misc::aviation::CLivery getTempLiveryOrDefault() const
The temp. livery if available.
void dataRead(swift::misc::network::CEntityFlags::Entity entity, swift::misc::network::CEntityFlags::ReadState state, int number, const QUrl &url)
Combined read signal.
void swiftDbModelMatchingEntitiesRead()
All entities needed for model matching.
swift::misc::simulation::CDistributor smartDistributorSelector() const
Use distributor object to select the best complete distributor from DB.
swift::misc::aviation::CAircraftIcaoCode getAircraftIcaoCodeForDbKey(int key) const
ICAO code for id.
swift::misc::aviation::CAircraftCategoryList getAircraftCategories() const
Aircraft categories.
void swiftDbAirlineIcaoRead()
Airline ICAO data read.
swift::misc::aviation::CAirportList getAirports() const
Get airports.
int getCacheCount(swift::misc::network::CEntityFlags::Entity entity) const
Cache count for entity.
swift::misc::aviation::CLiveryList getLiveries() const
Liveries.
swift::misc::CCountry getCountryForIsoCode(const QString &iso) const
Country by ISO code (GB, US...)
swift::misc::aviation::CAirlineIcaoCode smartAirlineIcaoSelector(const swift::misc::aviation::CAirlineIcaoCode &icaoPattern, const swift::misc::aviation::CCallsign &callsign=swift::misc::aviation::CCallsign()) const
Smart airline selector.
QSet< QString > getAircraftDesignatorsForAirline(const swift::misc::aviation::CAirlineIcaoCode &airline) const
Aircraft ICAO designators for airline.
int getAirlineIcaoCodesForDesignatorCount(const QString &designator) const
Airline ICAO codes for designator count.
void swiftDbDataRead(bool success)
DB data read.
bool containsAircraftIcaoDesignator(const QString &designator) const
Contains the given designator?
swift::misc::aviation::CLivery getLiveryForDbKey(int id) const
Livery for id.
swift::misc::aviation::CLivery getLiveryForCombinedCode(const QString &combinedCode) const
Livery for its combined code.
swift::misc::network::CUrl getVatsimDataFileUrl() const
Data file location (from status file)
bool hasDbAircraftData() const
Are all DB data for an aircraft entity available?
int getDbInfoObjectCount(swift::misc::network::CEntityFlags::Entity entity) const
Count for entity from DB entity objects.
swift::misc::simulation::CDistributor getDistributorForDbKey(const QString &key) const
Distributor for key.
swift::misc::aviation::CAirport getAirportForNameOrLocation(const QString &nameOrLocation) const
Get airport for name of location.
bool writeDbDataToDisk(const QString &dir)
Write data to disk (mainly for testing scenarios)
bool containsAirlineIcaoDesignator(const QString &designator) const
Contains the given designator?
int getAircraftIcaoCodesCount() const
Aircraft ICAO codes count.
virtual ~CWebDataServices()
Destructor.
swift::misc::aviation::CAtcStationList getAtcStationsForCallsign(const swift::misc::aviation::CCallsign &callsign) const
ATC stations by callsign.
void swiftDbAllIcaoEntitiesRead()
All ICAO entities.
bool readDbDataFromDisk(const QString &dir, bool inBackground, bool overrideNewerOnly)
Load DB data from disk (mainly for initial data load and testing scenarios)
swift::misc::aviation::CLivery smartLiverySelector(const swift::misc::aviation::CLivery &livery) const
Use a livery as template and select the best complete livery from DB for it.
swift::misc::aviation::CAirlineIcaoCode getAirlineIcaoCodeForUniqueDesignatorOrDefault(const QString &designator, bool preferOperatingAirlines) const
ICAO code if unique, otherwise default.
int getAirlineIcaoCodesCount() const
Airline ICAO codes count.
int getLiveriesCount() const
Liveries count.
swift::misc::CCountry getCountryForName(const QString &name) const
Country by name (France, China ..)
void swiftDbAircraftIcaoRead()
Aircraft ICAO data read.
QStringList getModelStrings(bool sort=false) const
Model strings.
void triggerReadOfDbInfoObjects()
Trigger read of DB info objects.
bool hasDbIcaoData() const
Are all DB ICAO data available?
swift::misc::aviation::CAirlineIcaoCodeList getAirlineIcaoCodes() const
Airline ICAO codes.
void swiftDbAllDataRead()
All swift DB data have been read.
QStringList getAirlineNames() const
Airline names.
swift::misc::simulation::CAircraftModelList getModelsForAircraftDesignatorAndLiveryCombinedCode(const QString &aircraftDesignator, const QString &combinedCode) const
Models for combined code and aircraft designator.
void admitDbCaches(swift::misc::network::CEntityFlags::Entity entities)
Admit all DB caches specified.
swift::misc::aviation::CAircraftIcaoCodeList getAircraftIcaoCodes() const
Aircraft ICAO codes.
@ AirportReader
reader for airport list
@ VatsimStatusReader
reader for VATSIM status file
@ ModelReader
reader for model data such as liveries, models, etc
@ IcaoDataReader
reader for ICAO data
@ DbInfoDataReader
DB info data (metdata, how many data, when updated)
@ VatsimServerFileReader
reader for VATSIM server file
static swift::misc::network::CEntityFlags::Entity allEntitiesForReaders(WebReader readers)
All entities readers can read.
static WebReader entitiesToReaders(swift::misc::network::CEntityFlags::Entity entities)
Relationship between readers and entities.
const swift::misc::network::CUrl & getDbRootDirectoryUrl() const
Root directory of DB.
Definition: globalsetup.h:65
Reader for airport database data.
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::CEntityFlags::Entity getEntitiesWithCacheTimestampNewerThan(const QDateTime &threshold) const
Entities already having data in cache (based on timestamp assumption)
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.
swift::misc::aviation::CAirportList getAirports() const
Returns a list of all airports in the database.
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 swift::misc::network::CEntityFlags::Entity getEntitiesWithCacheCount() const
Entities already having data in cache.
Value object encapsulating a list of reader configs.
bool needsSharedInfoObjects(swift::misc::network::CEntityFlags::Entity entities) const
Needs any shared info object.
bool needsSharedInfoFile(swift::misc::network::CEntityFlags::Entity entities) const
Needs any shared header loaded before continued.
swift::misc::network::CEntityFlags::Entity getEntitesCachedOrReadFromDB() const
Entities which will use cache or DB, so no canceled or ignored ones.
bool needsSharedInfoObjectsIfCachesEmpty(swift::misc::network::CEntityFlags::Entity entities, swift::misc::network::CEntityFlags::Entity cachedEntities) const
Needs any shared info object, but only if the cache is empty.
bool possiblyWritesToSwiftDb() const
Will write to swift DB.
bool possiblyReadsFromSwiftDb() const
Will read from swift DB.
Specialized version of threaded reader for DB data.
virtual QDateTime getCacheTimestamp(swift::misc::network::CEntityFlags::Entity entity) const =0
Get cache timestamp.
swift::misc::CStatusMessageList initFromLocalResourceFiles(bool inBackground)
Init from local resource file.
bool hasReceivedOkReply() const
Has received Ok response from server at least once?
virtual int getCacheCount(swift::misc::network::CEntityFlags::Entity entity) const =0
Cache`s number of entities.
QDateTime getLatestEntityTimestampFromSharedInfoObjects(swift::misc::network::CEntityFlags::Entity entity) const
Obtain latest object timestamp from shared info objects.
QDateTime getLatestEntityTimestampFromDbInfoObjects(swift::misc::network::CEntityFlags::Entity entity) const
Obtain latest object timestamp from DB info objects.
bool supportsAnyOfEntities(swift::misc::network::CEntityFlags::Entity entities) const
Is any of the given entities supported here by this reader.
QString getSupportedEntitiesAsString() const
Supported entities as string.
swift::misc::network::CEntityFlags::Entity getEntitesWithNewerSharedInfoObject(swift::misc::network::CEntityFlags::Entity entities) const
Those entities where the timestamp of a shared info object is newer than the cache timestamp.
swift::misc::network::CEntityFlags::Entity maskBySupportedEntities(swift::misc::network::CEntityFlags::Entity entities) const
Mask by supported entities.
swift::misc::network::CEntityFlags::Entity triggerLoadingDirectlyFromSharedFiles(swift::misc::network::CEntityFlags::Entity entities, bool checkCacheTsUpfront)
Start loading from shared files in own thread.
bool hasReceivedFirstReply() const
Has received 1st reply?
void readInBackgroundThread(swift::misc::network::CEntityFlags::Entity entities, const QDateTime &newerThan)
Start reading in own thread.
swift::misc::network::CEntityFlags::Entity triggerLoadingDirectlyFromDb(swift::misc::network::CEntityFlags::Entity entities, const QDateTime &newerThan)
Start loading from DB in own thread.
void setSeverityNoWorkingUrl(swift::misc::CStatusMessage::StatusSeverity s)
Severity used for log messages in case of no URLs.
const QString & getStatusMessage() const
Status message (error message)
Write to the swift DB.
const swift::misc::network::CUrlLogList & getWriteLog() const
Write log.
const QString & getName()
Name of the worker.
swift::misc::CStatusMessageList asyncPublishModels(const swift::misc::simulation::CAircraftModelList &models, const QString &extraInfo)
Write models to DB.
swift::misc::CStatusMessageList asyncAutoPublish(const swift::misc::simulation::CAutoPublishData &data)
Write auto publis data.
Read ICAO data from Database.
swift::misc::CCountry getCountryForName(const QString &name) const
Get country for ISO name.
swift::misc::CCountry getCountryForIsoCode(const QString &isoCode) const
Get country for ISO code.
bool containsAirlineIcaoDesignator(const QString &designator) const
Contains given designator?
int getCountriesCount() const
Get countries count.
swift::misc::aviation::CAirlineIcaoCode getAirlineIcaoCodeForDbKey(int key) const
Get airline ICAO information for key.
swift::misc::aviation::CAirlineIcaoCode getAirlineIcaoCodeForUniqueIataCodeOrDefault(const QString &iataCode) const
Find by IATA code if this is unique, otherwise return default object.
virtual swift::misc::CStatusMessageList readFromJsonFiles(const QString &dir, swift::misc::network::CEntityFlags::Entity whatToRead, bool overrideNewerOnly)
Data read from local data.
int getAirlineIcaoCodesCount() const
Get airline ICAO information count.
int getAircraftCategoryCount() const
Get aircraft category count.
swift::misc::aviation::CAircraftIcaoCodeList getAircraftIcaoCodes() const
Get aircraft ICAO information.
virtual swift::misc::network::CEntityFlags::Entity getEntitiesWithCacheCount() const
Entities already having data in cache.
swift::misc::aviation::CAircraftIcaoCode getAircraftIcaoCodeForDesignator(const QString &designator) const
Get aircraft ICAO information for designator.
swift::misc::aviation::CAirlineIcaoCodeList getAirlineIcaoCodesForDesignator(const QString &designator) const
Find by v-designator, this should be unique.
swift::misc::aviation::CAirlineIcaoCodeList getAirlineIcaoCodes() const
Get airline ICAO information.
virtual swift::misc::network::CEntityFlags::Entity getSupportedEntities() const
Supported entities by this reader.
virtual bool readFromJsonFilesInBackground(const QString &dir, swift::misc::network::CEntityFlags::Entity whatToRead, bool overrideNewerOnly)
Data read from local data.
swift::misc::aviation::CAircraftIcaoCodeList getAircraftIcaoCodesForDesignator(const QString &designator) const
Get aircraft ICAO information for designator.
virtual void admitCaches(swift::misc::network::CEntityFlags::Entity entities)
Admit caches for given entities.
swift::misc::aviation::CAircraftCategoryList getAircraftCategories() const
Get aircraft categories.
swift::misc::aviation::CAirlineIcaoCode getAirlineIcaoCodeForUniqueDesignatorOrDefault(const QString &designator, bool preferOperatingAirlines) const
Find by ICAO code if this is unique, otherwise return default object.
virtual swift::misc::network::CEntityFlags::Entity getEntitiesWithCacheTimestampNewerThan(const QDateTime &threshold) const
Entities already having data in cache (based on timestamp assumption)
swift::misc::CCountryList getCountries() const
Get countries.
int getAircraftIcaoCodesCount() const
Get aircraft ICAO information count.
bool containsAircraftIcaoDesignator(const QString &designator) const
Contains designator?
virtual void synchronizeCaches(swift::misc::network::CEntityFlags::Entity entities)
Admit caches for given entities.
swift::misc::aviation::CAirlineIcaoCode smartAirlineIcaoSelector(const swift::misc::aviation::CAirlineIcaoCode &icaoPattern, const swift::misc::aviation::CCallsign &callsign=swift::misc::aviation::CCallsign()) const
Get best match for airline ICAO code.
swift::misc::aviation::CAircraftIcaoCode getAircraftIcaoCodeForDbKey(int key) const
Get aircraft ICAO information for key.
swift::misc::aviation::CAircraftIcaoCode smartAircraftIcaoSelector(const swift::misc::aviation::CAircraftIcaoCode &icaoPattern) const
Get best match for incomplete aircraft ICAO code.
Read information about data from Database or shared files such as when updated and number of entries.
int getInfoObjectCount() const
Get info list size (either shared or from DB)
swift::misc::db::CDbInfoList getInfoObjects() const
Get info list (either shared or from DB)
void readInfoData()
Allow to call directly, special for info objects reader.
swift::misc::network::CUrl getInfoObjectsUrl() const
URL depending on mode, i.e. shared/DB.
bool areAllInfoObjectsRead() const
All data read?
Read model related data from Database.
bool containsModelString(const QString &modelString) const
Contains modelstring?
swift::misc::simulation::CAircraftModel getModelForModelString(const QString &modelString) const
Get model for string.
swift::misc::simulation::CAircraftModel getModelForDbKey(int dbKey) const
Get model for DB key.
swift::misc::aviation::CLivery getLiveryForCombinedCode(const QString &combinedCode) const
Get aircraft livery for code.
int getLiveriesCount() const
Get aircraft liveries count.
swift::misc::simulation::CDistributor getDistributorForDbKey(const QString &dbKey) const
Get distributor for id.
QSet< int > getModelDbKeys() const
Get model keys.
QStringList getModelStringList(bool sort=false) const
Get model keys.
swift::misc::aviation::CLivery smartLiverySelector(const swift::misc::aviation::CLivery &livery) const
Best match specified by livery.
int getDistributorsCount() const
Get model distributors count.
virtual swift::misc::network::CEntityFlags::Entity getEntitiesWithCacheCount() const
Entities already having data in cache.
virtual void admitCaches(swift::misc::network::CEntityFlags::Entity entities)
Admit caches for given entities.
swift::misc::simulation::CDistributorList getDistributors() const
Get distributors (of models)
swift::misc::simulation::CAircraftModelList getModelsForAircraftDesignatorAndLiveryCombinedCode(const QString &aircraftDesignator, const QString &combinedCode)
Get model for designator/combined code.
swift::misc::aviation::CAircraftIcaoCodeList getAicraftIcaoCodesForAirline(const swift::misc::aviation::CAirlineIcaoCode &code) const
Get aircraft ICAO designators (e.g. B737, ..) for given airline.
swift::misc::simulation::CDistributor smartDistributorSelector(const swift::misc::simulation::CDistributor &distributorPattern) const
Best match specified by distributor.
virtual swift::misc::network::CEntityFlags::Entity getSupportedEntities() const
Supported entities by this reader.
int getModelsCount() const
Get models count.
swift::misc::aviation::CLivery getStdLiveryForAirlineVDesignator(const swift::misc::aviation::CAirlineIcaoCode &icao) const
Get aircraft livery for ICAO code.
QSet< QString > getAircraftDesignatorsForAirline(const swift::misc::aviation::CAirlineIcaoCode &code) const
Get aircraft ICAO designators (e.g. B737, ..) for given airline.
virtual void synchronizeCaches(swift::misc::network::CEntityFlags::Entity entities)
Admit caches for given entities.
swift::misc::aviation::CLivery getLiveryForDbKey(int id) const
Get aircraft livery for id.
swift::misc::simulation::CAircraftModelList getModels() const
Get models.
virtual bool readFromJsonFilesInBackground(const QString &dir, swift::misc::network::CEntityFlags::Entity whatToRead, bool overrideNewerOnly)
Data read from local data.
swift::misc::aviation::CLiveryList getLiveries() const
Get aircraft liveries.
virtual swift::misc::network::CEntityFlags::Entity getEntitiesWithCacheTimestampNewerThan(const QDateTime &threshold) const
Entities already having data in cache (based on timestamp assumption)
virtual swift::misc::CStatusMessageList readFromJsonFiles(const QString &dir, swift::misc::network::CEntityFlags::Entity whatToRead, bool overrideNewerOnly)
Data read from local data.
swift::misc::aviation::CAtcStationList getAtcStationsForCallsign(const swift::misc::aviation::CCallsign &callsign) const
Get ATC stations for callsign.
swift::misc::network::CVoiceCapabilities getVoiceCapabilityForCallsign(const swift::misc::aviation::CCallsign &callsign) const
Voice capability for callsign.
void updateWithVatsimDataFileData(swift::misc::simulation::CSimulatedAircraft &aircraftToBeUdpated) const
Update aircraft with VATSIM aircraft data from data file.
swift::misc::network::CUserList getUsersForCallsign(const swift::misc::aviation::CCallsign &callsign) const
User for callsign.
virtual swift::misc::weather::CMetarList getMetars() const
Get METARs.
virtual swift::misc::weather::CMetar getMetarForAirport(const swift::misc::aviation::CAirportIcaoCode &icao) const
Get METAR for airport.
void readInBackgroundThread()
Start reading in own thread.
swift::misc::network::CServerList getFsdServers() const
Get all VATSIM FSD servers.
Sole purpose is to read the URLs where VATSIM data can be downloaded.
swift::misc::network::CUrl getDataFileUrl() const
Data file URL.
swift::misc::network::CUrl getMetarFileUrl() const
METAR URL.
void readInBackgroundThread()
Start reading in own thread.
const QString & getName()
Name of the worker.
Definition: worker.h:327
void quitAndWait() noexcept final
Calls quit() and blocks until the thread is finished.
Definition: worker.cpp:203
void start(QThread::Priority priority=QThread::InheritPriority)
Starts a thread and moves the worker into it.
Definition: worker.cpp:165
Value object encapsulating a list of countries.
Definition: countrylist.h:32
static bool writeStringToFile(const QString &content, const QString &fileNameAndPath)
Write string to text file.
Definition: fileutils.cpp:40
static QString appendFilePaths(const QString &path1, const QString &path2)
Append file paths.
Definition: fileutils.cpp:95
static const QString & webservice()
Webservice.
Class for emitting a log message.
Definition: logmessage.h:27
static void preformatted(const CStatusMessage &statusMessage)
Sends a verbatim, preformatted message to the log.
Derived & warning(const char16_t(&format)[N])
Set the severity to warning, providing a format string.
bool isEmpty() const
Message empty.
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.
Definition: sequence.h:273
void push_back(const T &value)
Appends an element at the end of the sequence.
Definition: sequence.h:305
bool isEmpty() const
Synonym for empty.
Definition: sequence.h:285
Streamable status message, e.g.
constexpr static auto SeverityError
Status severities.
constexpr static auto SeverityWarning
Status severities.
Status messages, e.g. from Core -> GUI.
bool isSuccess() const
All messages are marked as success.
void warningToError()
Turn warnings into errors.
static bool thisIsMainThread()
Is the current thread the application thread?
Definition: threadutils.cpp:21
static bool isInThisThread(const QObject *toBeTested)
Is the current thread the object's thread?
Definition: threadutils.cpp:16
static CWorker * fromTask(QObject *owner, const QString &name, F &&task)
Returns a new worker object which lives in a new thread.
Definition: worker.h:225
Value object encapsulating a list of ICAO codes.
Value object for ICAO classification.
Value object encapsulating a list of ICAO codes.
Value object for ICAO classification.
bool hasValidDesignator() const
Airline designator available?
Value object encapsulating a list of ICAO codes.
CAirlineIcaoCode findBestMatchByCallsign(const CCallsign &callsign) const
Use callsign to conclude airline.
Value object encapsulating information about an airpot.
Definition: airport.h:36
Value object encapsulating information of airport ICAO data.
Value object for a list of airports.
Definition: airportlist.h:29
Value object for a list of ATC stations.
Value object encapsulating information of a callsign.
Definition: callsign.h:30
bool isEmpty() const
Is empty?
Definition: callsign.h:63
Value object encapsulating information about an airpot.
Definition: livery.h:29
Value object for a list of airports.
Definition: liverylist.h:29
Info about the latest models.
Definition: dbinfo.h:22
int getEntries() const
Entry count.
Definition: dbinfo.h:60
CDbInfo findFirstByEntityOrDefault(swift::misc::network::CEntityFlags::Entity entity) const
Find by entity.
Definition: dbinfolist.cpp:16
bool isLoadedFromDb() const
Loaded from DB.
Definition: datastore.cpp:49
QString toQString(bool i18n=false) const
Cast as QString.
Definition: mixinstring.h:74
What and state of reading from web services.
Definition: entityflags.h:22
QSet< CEntityFlags::Entity > EntitySet
Set of CEntityFlags::Entity.
Definition: entityflags.h:57
Value object encapsulating a list of servers.
Definition: serverlist.h:23
Value object encapsulating information of a location, kind of simplified CValueObject compliant versi...
Definition: url.h:27
QString getSummary() const
Summary.
Definition: urlloglist.cpp:129
Value object encapsulating a list of voice rooms.
Definition: userlist.h:26
Value object encapsulating information for voice capabilities.
Aircraft model (used by another pilot, my models on disk)
Definition: aircraftmodel.h:71
const QString & getModelString() const
Model key, either queried or loaded from simulator model.
bool isEqualForPublishing(const CAircraftModel &dbModel, CStatusMessageList *details=nullptr) const
Considered equal for publishing, compares if livery etc. are the same DB values.
Value object encapsulating a list of aircraft models.
QStringList toCompleterStrings(bool sorted=true, const CSimulatorInfo &simulator={ CSimulatorInfo::All }) const
Completer strings.
CStatusMessageList validateDistributors(const CDistributorList &distributors, CAircraftModelList &validModels, CAircraftModelList &invalidModels) const
Validate distributors.
CStatusMessageList validateForPublishing() const
Validate for publishing.
Objects that can be use for auto-publishing. Auto publishing means we sent those data to the DB.
Value object encapsulating information of software distributor.
Definition: distributor.h:33
Value object encapsulating a list of distributors.
Comprehensive information of an aircraft.
Simple hardcoded info about the corresponding simulator.
Definition: simulatorinfo.h:41
Value object encapsulating information about METAR FIXME: runway visibilities FIXME: runway wind shea...
Definition: metar.h:38
Sequence of Metars.
Definition: metarlist.h:24
Core data traits (aka cached values) and classes.
Classes interacting with the swift database (aka "datastore").
Backend services of the swift project, like dealing with the network or the simulators.
Definition: actionbind.cpp:7
Free functions in swift::misc.
StatusSeverity
Status severities.
Definition: statusmessage.h:35
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...
Definition: threadutils.h:30