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 readers,
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 && readers.testFlag(CWebReaderFlags::DbInfoDataReader))
69  {
70  // will remove info reader because not needed
71  readers &= ~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(readers);
77  if (entities.testFlag(CEntityFlags::DbInfoObjectEntity))
78  {
79  Q_ASSERT_X(readers.testFlag(CWebReaderFlags::DbInfoDataReader), Q_FUNC_INFO, "info object but no reader");
80  CLogMessage(this).info(u"Using info objects for swift DB entities");
81  }
82 
83  this->initReaders(readers, entities); // reads info objects if required
84  if (writeToSwiftDb) { this->initWriters(); }
85 
86  // make sure this is called in event queue, so pending tasks cam be performed
87  entities &= ~CEntityFlags::DbInfoObjectEntity; // triggered in init readers
88  entities &= ~CEntityFlags::VatsimStatusFile; // triggered in init readers
89  entities &= ~m_entitiesPeriodicallyRead; // will be triggered by timers
90 
91  // trigger reading
92  // but do not start all at the same time
93  const CEntityFlags::Entity icaoPart = entities & CEntityFlags::AllIcaoCountriesCategory;
94  const CEntityFlags::Entity modelPart = entities & CEntityFlags::DistributorLiveryModel;
95  CEntityFlags::Entity remainingEntities = entities & ~icaoPart;
96  remainingEntities &= ~modelPart;
97  this->readDeferredInBackground(icaoPart, 500);
98  this->readDeferredInBackground(modelPart, 1000);
99  this->readDeferredInBackground(remainingEntities, 1500);
100  }
101 
103 
105  {
106  if (m_vatsimServerFileReader) { return m_vatsimServerFileReader->getFsdServers(); }
107  return CServerList();
108  }
109 
111  {
112  if (m_vatsimStatusReader) { return m_vatsimStatusReader->getMetarFileUrl(); }
113  return {};
114  }
115 
117  {
118  if (m_vatsimStatusReader) { return m_vatsimStatusReader->getDataFileUrl(); }
119  return {};
120  }
121 
123  {
124  if (m_vatsimDataFileReader) { return m_vatsimDataFileReader->getUsersForCallsign(callsign); }
125  return CUserList();
126  }
127 
129  {
130  if (m_vatsimDataFileReader) { return m_vatsimDataFileReader->getAtcStationsForCallsign(callsign); }
131  return CAtcStationList();
132  }
133 
135  {
136  if (m_vatsimDataFileReader) { return m_vatsimDataFileReader->getVoiceCapabilityForCallsign(callsign); }
137  return CVoiceCapabilities();
138  }
139 
141  {
142  if (m_vatsimDataFileReader) { m_vatsimDataFileReader->updateWithVatsimDataFileData(aircraftToBeUdpated); }
143  }
144 
146  {
147  if (m_databaseWriter) { return m_databaseWriter->asyncPublishModels(modelsToBePublished, ""); }
148  return CStatusMessageList();
149  }
150 
152  {
153  if (m_databaseWriter) { return m_databaseWriter->asyncAutoPublish(data); }
154  return CStatusMessageList();
155  }
156 
157  void CWebDataServices::triggerReadOfDbInfoObjects() { initDbInfoObjectReaderAndTriggerRead(); }
158 
159  void CWebDataServices::triggerReadOfSharedInfoObjects() { initSharedInfoObjectReaderAndTriggerRead(); }
160 
162  {
163  if (!m_icaoDataReader && !m_modelDataReader && !m_airportDataReader && !m_dbInfoDataReader) { return false; }
164 
165  // use the first one to test
166  if (m_dbInfoDataReader) { return m_dbInfoDataReader->hasReceivedOkReply(); }
167  if (m_icaoDataReader) { return m_icaoDataReader->hasReceivedOkReply(); }
168  if (m_modelDataReader) { return m_modelDataReader->hasReceivedOkReply(); }
169  if (m_airportDataReader) { return m_airportDataReader->hasReceivedOkReply(); }
170  return false;
171  }
172 
173  bool CWebDataServices::hasDbAircraftData() const { return this->hasDbIcaoData() && this->hasDbModelData(); }
174 
176  {
177  return (this->getModelsCount() > 0) && (this->getLiveriesCount() > 0) && (this->getDistributorsCount() > 0);
178  }
179 
181  {
182  return (this->getAircraftIcaoCodesCount() > 0) && (this->getAirlineIcaoCodesCount() > 0) &&
183  (this->getCountriesCount() > 0);
184  }
185 
186  void CWebDataServices::admitDbCaches(CEntityFlags::Entity entities)
187  {
188  if (m_shuttingDown) { return; }
189 
190  // hint: those 2 are currently doing nothing, but this might change in the future
191  // if (m_dbInfoDataReader) { m_dbInfoDataReader->admitCaches(entities); }
192  // if (m_sharedInfoDataReader) { m_sharedInfoDataReader->admitCaches(entities); }
193 
194  // hint: all the readers use own threads
195  if (m_modelDataReader) { m_modelDataReader->admitCaches(entities); }
196  if (m_icaoDataReader) { m_icaoDataReader->admitCaches(entities); }
197  if (m_airportDataReader) { m_airportDataReader->admitCaches(entities); }
198  }
199 
200  void CWebDataServices::synchronizeDbCaches(CEntityFlags::Entity entities)
201  {
202  if (m_shuttingDown) { return; }
203 
204  // hint: those 2 are currently doing nothing, but this might change in the future
205  // if (m_dbInfoDataReader) { m_dbInfoDataReader->synchronizeCaches(entities); }
206  // if (m_sharedInfoDataReader) { m_sharedInfoDataReader->synchronizeCaches(entities); }
207 
208  // hint: all the readers use own threads
209  if (m_modelDataReader) { m_modelDataReader->synchronizeCaches(entities); }
210  if (m_icaoDataReader) { m_icaoDataReader->synchronizeCaches(entities); }
211  if (m_airportDataReader) { m_airportDataReader->synchronizeCaches(entities); }
212  }
213 
214  CEntityFlags::Entity CWebDataServices::triggerRead(CEntityFlags::Entity whatToRead, const QDateTime &newerThan)
215  {
216  if (m_shuttingDown) { return CEntityFlags::NoEntity; }
217 
218  Q_ASSERT_X(!whatToRead.testFlag(CEntityFlags::DbInfoObjectEntity), Q_FUNC_INFO,
219  "Info object must be read upfront");
220  CEntityFlags::Entity triggeredRead = CEntityFlags::NoEntity;
221  if (m_vatsimDataFileReader)
222  {
223  if (whatToRead.testFlag(CEntityFlags::VatsimDataFile))
224  {
225  m_vatsimDataFileReader->readInBackgroundThread();
226  triggeredRead |= CEntityFlags::VatsimDataFile;
227  }
228  }
229 
230  if (m_vatsimMetarReader)
231  {
232  if (whatToRead.testFlag(CEntityFlags::MetarEntity))
233  {
234  m_vatsimMetarReader->readInBackgroundThread();
235  triggeredRead |= CEntityFlags::MetarEntity;
236  }
237  }
238 
239  if (m_airportDataReader)
240  {
241  if (whatToRead.testFlag(CEntityFlags::AirportEntity))
242  {
243  CEntityFlags::Entity airportEntities = whatToRead & CEntityFlags::AirportEntity;
244  m_airportDataReader->readInBackgroundThread(airportEntities, newerThan);
245  triggeredRead |= CEntityFlags::AirportEntity;
246  }
247  }
248 
249  if (m_icaoDataReader)
250  {
251  if (whatToRead.testFlag(CEntityFlags::AircraftIcaoEntity) ||
252  whatToRead.testFlag(CEntityFlags::AircraftCategoryEntity) ||
253  whatToRead.testFlag(CEntityFlags::AirlineIcaoEntity) ||
254  whatToRead.testFlag(CEntityFlags::CountryEntity))
255  {
256  CEntityFlags::Entity icaoEntities = whatToRead & CEntityFlags::AllIcaoCountriesCategory;
257  m_icaoDataReader->readInBackgroundThread(icaoEntities, newerThan);
258  triggeredRead |= icaoEntities;
259  }
260  }
261 
262  if (m_modelDataReader)
263  {
264  if (whatToRead.testFlag(CEntityFlags::LiveryEntity) ||
265  whatToRead.testFlag(CEntityFlags::DistributorEntity) || whatToRead.testFlag(CEntityFlags::ModelEntity))
266  {
267  CEntityFlags::Entity modelEntities = whatToRead & CEntityFlags::DistributorLiveryModel;
268  m_modelDataReader->readInBackgroundThread(modelEntities, newerThan);
269  triggeredRead |= modelEntities;
270  }
271  }
272 
273  return triggeredRead;
274  }
275 
276  CEntityFlags::Entity CWebDataServices::triggerLoadingDirectlyFromDb(CEntityFlags::Entity whatToRead,
277  const QDateTime &newerThan)
278  {
279  if (m_shuttingDown) { return CEntityFlags::NoEntity; }
280  if (!sApp || sApp->isShuttingDown()) { return CEntityFlags::NoEntity; }
281 
282  CEntityFlags::Entity triggeredRead = CEntityFlags::NoEntity;
283  if (m_dbInfoDataReader)
284  {
286  triggeredRead |= CEntityFlags::DbInfoObjectEntity;
287  }
288 
289  if (m_icaoDataReader)
290  {
291  if (m_icaoDataReader->supportsAnyOfEntities(whatToRead))
292  {
293  const CEntityFlags::Entity icaoEntities = m_icaoDataReader->maskBySupportedEntities(whatToRead);
294  m_icaoDataReader->triggerLoadingDirectlyFromDb(icaoEntities, newerThan);
295  triggeredRead |= icaoEntities;
296  }
297  }
298 
299  if (m_modelDataReader)
300  {
301  if (m_modelDataReader->supportsAnyOfEntities(whatToRead))
302  {
303  const CEntityFlags::Entity modelEntities = m_modelDataReader->maskBySupportedEntities(whatToRead);
304  m_modelDataReader->triggerLoadingDirectlyFromDb(modelEntities, newerThan);
305  triggeredRead |= modelEntities;
306  }
307  }
308 
309  if (m_airportDataReader)
310  {
311  if (m_airportDataReader->supportsAnyOfEntities(whatToRead))
312  {
313  const CEntityFlags::Entity airportEntities = m_airportDataReader->maskBySupportedEntities(whatToRead);
314  m_airportDataReader->triggerLoadingDirectlyFromDb(airportEntities, newerThan);
315  triggeredRead |= airportEntities;
316  }
317  }
318 
319  return triggeredRead;
320  }
321 
322  CEntityFlags::Entity CWebDataServices::triggerLoadingDirectlyFromSharedFiles(CEntityFlags::Entity whatToRead,
323  bool checkCacheTsUpfront)
324  {
325  if (m_shuttingDown) { return CEntityFlags::NoEntity; }
326  if (!sApp || sApp->isShuttingDown()) { return CEntityFlags::NoEntity; }
327 
328  CEntityFlags::Entity triggeredRead = CEntityFlags::NoEntity;
329  this->triggerReadOfSharedInfoObjects(); // trigger reload of info objects (for shared)
330 
331  if (m_icaoDataReader)
332  {
333  if (m_icaoDataReader->supportsAnyOfEntities(whatToRead))
334  {
335  CEntityFlags::Entity icaoEntities = m_icaoDataReader->maskBySupportedEntities(whatToRead);
336  triggeredRead |=
337  m_icaoDataReader->triggerLoadingDirectlyFromSharedFiles(icaoEntities, checkCacheTsUpfront);
338  }
339  }
340 
341  if (m_modelDataReader)
342  {
343  if (m_modelDataReader->supportsAnyOfEntities(whatToRead))
344  {
345  CEntityFlags::Entity modelEntities = m_modelDataReader->maskBySupportedEntities(whatToRead);
346  triggeredRead |=
347  m_modelDataReader->triggerLoadingDirectlyFromSharedFiles(modelEntities, checkCacheTsUpfront);
348  }
349  }
350 
351  if (m_airportDataReader)
352  {
353  if (m_airportDataReader->supportsAnyOfEntities(whatToRead))
354  {
355  CEntityFlags::Entity airportEntities = m_airportDataReader->maskBySupportedEntities(whatToRead);
356  triggeredRead |=
357  m_airportDataReader->triggerLoadingDirectlyFromSharedFiles(airportEntities, checkCacheTsUpfront);
358  }
359  }
360 
361  return triggeredRead;
362  }
363 
364  QDateTime CWebDataServices::getCacheTimestamp(CEntityFlags::Entity entity) const
365  {
366  Q_ASSERT_X(CEntityFlags::isSingleEntity(entity), Q_FUNC_INFO, "Need single entity");
367  if (!CEntityFlags::anySwiftDbEntity(entity)) { return QDateTime(); }
368  const CDatabaseReader *dr = this->getDbReader(entity);
369  if (!dr) { return QDateTime(); }
370  return dr->getCacheTimestamp(entity);
371  }
372 
373  QDateTime CWebDataServices::getLatestDbEntityTimestamp(CEntityFlags::Entity entity) const
374  {
375  Q_ASSERT_X(CEntityFlags::isSingleEntity(entity), Q_FUNC_INFO, "Need single entity");
376  if (!CEntityFlags::anySwiftDbEntity(entity)) { return QDateTime(); }
377  const CInfoDataReader *ir = this->getDbInfoDataReader();
378  if (!ir) { return QDateTime(); }
380  }
381 
382  QDateTime CWebDataServices::getLatestSharedInfoObjectTimestamp(CEntityFlags::Entity entity) const
383  {
384  const CDatabaseReader *reader = this->getDbReader(entity);
385  if (!reader) { return QDateTime(); }
386  Q_ASSERT_X(CEntityFlags::isSingleEntity(entity), Q_FUNC_INFO, "need single entity");
387  return reader->getLatestEntityTimestampFromSharedInfoObjects(entity);
388  }
389 
391  {
392  QDateTime latest;
393  const CEntityFlags::EntitySet set = CEntityFlags::asSingleEntities(CEntityFlags::AllDbEntitiesNoInfoObjects);
394  for (CEntityFlags::Entity e : set)
395  {
396  const QDateTime ts = this->getCacheTimestamp(e);
397  if (!ts.isValid()) { continue; }
398  if (!latest.isValid() || latest < ts) { latest = ts; }
399  }
400  return latest;
401  }
402 
403  CEntityFlags::Entity CWebDataServices::getEntitiesWithNewerSharedFile(CEntityFlags::Entity entities) const
404  {
405  Q_ASSERT_X(m_sharedInfoDataReader, Q_FUNC_INFO, "Shared info reader was not initialized");
406  if (m_sharedInfoDataReader->getInfoObjectCount() < 1) { return CEntityFlags::NoEntity; }
407  return m_sharedInfoDataReader->getEntitesWithNewerSharedInfoObject(entities);
408  }
409 
410  CEntityFlags::Entity CWebDataServices::getEmptyEntities(CEntityFlags::Entity entities) const
411  {
412  entities &= CEntityFlags::AllDbEntities; // handled by this reader
413  CEntityFlags::Entity currentEntity = CEntityFlags::iterateDbEntities(entities);
414  CEntityFlags::Entity emptyEntities = CEntityFlags::NoEntity;
415  while (currentEntity != CEntityFlags::NoEntity)
416  {
417  const int c = this->getCacheCount(currentEntity);
418  if (c < 1) { emptyEntities |= currentEntity; }
419  currentEntity = CEntityFlags::iterateDbEntities(entities);
420  }
421  return emptyEntities;
422  }
423 
424  CEntityFlags::Entity
425  CWebDataServices::getSynchronizedEntitiesWithNewerSharedFileOrEmpty(bool syncData, CEntityFlags::Entity entities)
426  {
427  CEntityFlags::Entity loadEntities = this->getEntitiesWithNewerSharedFile(entities);
428  const CEntityFlags::Entity checkForEmptyEntities =
429  CEntityFlags::entityFlagToEntity(CEntityFlags::AllDbEntitiesNoInfoObjects) & ~loadEntities;
430 
431  // it can happen the timestamps are not newer, but the data are empty
432  // - can happen if caches are copied and the TS does not represent the DB timestamp
433  // - cache files have been deleted
434  // - sync all DB entities
435  // - fast if there are no data
436  // - no impact if already synced
437  // - slow if newer synced before and all has to be done now
438  if (syncData) { this->synchronizeDbCaches(checkForEmptyEntities); }
439 
440  // we have no newer timestamps, but incomplete data
441  loadEntities |= this->getEmptyEntities();
442  return loadEntities;
443  }
444 
445  int CWebDataServices::getCacheCount(CEntityFlags::Entity entity) const
446  {
447  Q_ASSERT_X(CEntityFlags::isSingleEntity(entity), Q_FUNC_INFO, "Need single entity");
448  if (CEntityFlags::anySwiftDbEntity(entity))
449  {
450  const CDatabaseReader *dr = this->getDbReader(entity);
451  if (!dr) { return -1; }
452  return dr->getCacheCount(entity);
453  }
454  else
455  {
456  // non DB/shared entities would go here
457  return -1;
458  }
459  }
460 
461  int CWebDataServices::getDbInfoObjectCount(CEntityFlags::Entity entity) const
462  {
463  if (!m_dbInfoDataReader) { return -1; }
464  return this->getInfoObjectCount(entity, m_dbInfoDataReader);
465  }
466 
467  int CWebDataServices::getDbInfoObjectsCount(CEntityFlags::Entity entities, bool stopIfNotFound) const
468  {
469  if (!m_dbInfoDataReader) { return -1; }
470  int total = 0;
471  CEntityFlags::EntitySet set = CEntityFlags::asSingleEntities(entities);
472  for (CEntityFlags::Entity single : set)
473  {
474  const int c = this->getDbInfoObjectCount(single);
475  if (c < 0 && stopIfNotFound) { return -1; }
476  if (c > 0) { total += c; }
477  }
478  return total;
479  }
480 
481  int CWebDataServices::getSharedInfoObjectCount(CEntityFlags::Entity entity) const
482  {
483  if (!m_sharedInfoDataReader) return -1;
484  return this->getInfoObjectCount(entity, m_sharedInfoDataReader);
485  }
486 
487  QString CWebDataServices::getDbReadersLog(const QString &separator) const
488  {
489  QStringList report;
490  if (m_dbInfoDataReader)
491  {
492  report << m_dbInfoDataReader->getName() + ": " + m_dbInfoDataReader->getReadLog().getSummary();
493  }
494  if (m_sharedInfoDataReader)
495  {
496  report << m_sharedInfoDataReader->getName() + ": " + m_sharedInfoDataReader->getReadLog().getSummary();
497  }
498 
499  if (m_airportDataReader)
500  {
501  report << m_airportDataReader->getName() + ": " + m_airportDataReader->getReadLog().getSummary();
502  }
503  if (m_icaoDataReader)
504  {
505  report << m_icaoDataReader->getName() + ": " + m_icaoDataReader->getReadLog().getSummary();
506  }
507  if (m_modelDataReader)
508  {
509  report << m_modelDataReader->getName() + ": " + m_modelDataReader->getReadLog().getSummary();
510  }
511  if (m_databaseWriter)
512  {
513  report << m_databaseWriter->getName() + ": " + m_databaseWriter->getWriteLog().getSummary();
514  }
515  return report.join(separator);
516  }
517 
518  QString CWebDataServices::getReadersLog(const QString &separator) const
519  {
520  const QString db = this->getDbReadersLog(separator);
521  QStringList report;
522  if (m_vatsimMetarReader)
523  {
524  report << m_vatsimMetarReader->getName() + ": " + m_vatsimMetarReader->getReadLog().getSummary();
525  }
526  if (m_vatsimStatusReader)
527  {
528  report << m_vatsimStatusReader->getName() + ": " + m_vatsimStatusReader->getReadLog().getSummary();
529  }
530  if (report.isEmpty()) { return db; }
531  return report.join(separator) + separator + db;
532  }
533 
535  {
536  if (m_modelDataReader) { return m_modelDataReader->getDistributors(); }
537  return CDistributorList();
538  }
539 
541  {
542  if (m_modelDataReader) { return m_modelDataReader->getDistributorsCount(); }
543  return 0;
544  }
545 
547  {
548  if (m_modelDataReader) { return m_modelDataReader->getDistributorForDbKey(key); }
549  return CDistributor();
550  }
551 
553  {
554  if (m_modelDataReader) { return m_modelDataReader->smartDistributorSelector(distributor); }
555  return CDistributor();
556  }
557 
559  const CAircraftModel &model) const
560  {
561  if (m_modelDataReader) { return m_modelDataReader->smartDistributorSelector(distributor, model); }
562  return CDistributor();
563  }
564 
566  {
567  if (m_modelDataReader) { return m_modelDataReader->getLiveries(); }
568  return CLiveryList();
569  }
570 
572  {
573  if (m_modelDataReader) { return m_modelDataReader->getLiveriesCount(); }
574  return 0;
575  }
576 
577  CLivery CWebDataServices::getLiveryForCombinedCode(const QString &combinedCode) const
578  {
579  if (m_modelDataReader) { return m_modelDataReader->getLiveryForCombinedCode(combinedCode); }
580  return CLivery();
581  }
582 
584  {
585  if (m_modelDataReader) { return m_modelDataReader->getLiveryForCombinedCode(CLivery::tempLiveryCode()); }
586  return CLivery();
587  }
588 
590  {
591  if (m_modelDataReader) { return m_modelDataReader->getStdLiveryForAirlineVDesignator(icao); }
592  return CLivery();
593  }
594 
596  {
597  if (m_modelDataReader) { return m_modelDataReader->getLiveryForDbKey(id); }
598  return CLivery();
599  }
600 
602  {
603  if (m_modelDataReader) { return m_modelDataReader->smartLiverySelector(livery); }
604  return livery;
605  }
606 
608  {
609  if (m_modelDataReader) { return m_modelDataReader->getModels(); }
610  return CAircraftModelList();
611  }
612 
614  {
615  if (m_modelDataReader) { return m_modelDataReader->getModelsCount(); }
616  return 0;
617  }
618 
620  {
621  if (m_modelDataReader) { return m_modelDataReader->getModelDbKeys(); }
622  return QSet<int>();
623  }
624 
625  QStringList CWebDataServices::getModelStrings(bool sort) const
626  {
627  if (m_modelDataReader) { return m_modelDataReader->getModelStringList(sort); }
628  return QStringList();
629  }
630 
631  QStringList CWebDataServices::getModelCompleterStrings(bool sorted, const CSimulatorInfo &simulator) const
632  {
633  if (m_modelDataReader) { return m_modelDataReader->getModels().toCompleterStrings(sorted, simulator); }
634  return QStringList();
635  }
636 
639  const QString &combinedCode) const
640  {
641  if (m_modelDataReader)
642  {
643  return m_modelDataReader->getModelsForAircraftDesignatorAndLiveryCombinedCode(aircraftDesignator,
644  combinedCode);
645  }
646  return CAircraftModelList();
647  }
648 
650  {
651  if (m_modelDataReader) { return m_modelDataReader->getModelForModelString(modelString); }
652  return CAircraftModel();
653  }
654 
655  bool CWebDataServices::containsModelString(const QString &modelString) const
656  {
657  if (m_modelDataReader) { return m_modelDataReader->containsModelString(modelString); }
658  return false;
659  }
660 
662  {
663  if (m_modelDataReader) { return m_modelDataReader->getModelForDbKey(dbKey); }
664  return CAircraftModel();
665  }
666 
668  {
669  if (m_icaoDataReader) { return m_icaoDataReader->getAircraftIcaoCodes(); }
670  return CAircraftIcaoCodeList();
671  }
672 
674  {
675  if (m_icaoDataReader) { return m_icaoDataReader->getAircraftIcaoCodesCount(); }
676  return 0;
677  }
678 
680  {
681  if (m_icaoDataReader) { return m_icaoDataReader->getAircraftIcaoCodeForDesignator(designator); }
682  return CAircraftIcaoCode();
683  }
684 
685  int CWebDataServices::getAircraftIcaoCodesForDesignatorCount(const QString &designator) const
686  {
687  return this->getAircraftIcaoCodesForDesignator(designator).size();
688  }
689 
691  {
692  if (!airline.hasValidDesignator()) { return QSet<QString>(); }
693  if (m_modelDataReader) { return m_modelDataReader->getAircraftDesignatorsForAirline(airline); }
694  return QSet<QString>();
695  }
696 
698  {
699  if (!airline.hasValidDesignator()) { return CAircraftIcaoCodeList(); }
700  if (m_modelDataReader) { return m_modelDataReader->getAicraftIcaoCodesForAirline(airline); }
701  return CAircraftIcaoCodeList();
702  }
703 
705  {
706  if (m_icaoDataReader) { return m_icaoDataReader->getAircraftCategories(); }
707  return CAircraftCategoryList();
708  }
709 
711  {
712  if (m_icaoDataReader) { return m_icaoDataReader->getAircraftCategoryCount(); }
713  return 0;
714  }
715 
716  bool CWebDataServices::containsAircraftIcaoDesignator(const QString &designator) const
717  {
718  if (designator.isEmpty()) { return false; }
719  if (m_icaoDataReader) { return m_icaoDataReader->containsAircraftIcaoDesignator(designator); }
720  return false;
721  }
722 
724  {
725  if (m_icaoDataReader) { return m_icaoDataReader->getAircraftIcaoCodesForDesignator(designator); }
726  return CAircraftIcaoCodeList();
727  }
728 
730  {
731  if (m_icaoDataReader) { return m_icaoDataReader->getAircraftIcaoCodeForDbKey(key); }
732  return CAircraftIcaoCode();
733  }
734 
736  {
737  if (m_icaoDataReader) { return m_icaoDataReader->smartAircraftIcaoSelector(icao); }
738  return icao;
739  }
740 
742  {
743  if (m_icaoDataReader) { return m_icaoDataReader->getAirlineIcaoCodes(); }
744  return CAirlineIcaoCodeList();
745  }
746 
747  bool CWebDataServices::containsAirlineIcaoDesignator(const QString &designator) const
748  {
749  if (designator.isEmpty()) { return false; }
750  if (m_icaoDataReader) { return m_icaoDataReader->containsAirlineIcaoDesignator(designator); }
751  return false;
752  }
753 
756  bool preferOperatingAirlines) const
757  {
758  if (designator.isEmpty()) { return CAirlineIcaoCode(); }
759  if (m_icaoDataReader)
760  {
761  return m_icaoDataReader->getAirlineIcaoCodeForUniqueDesignatorOrDefault(designator,
762  preferOperatingAirlines);
763  }
764  return CAirlineIcaoCode();
765  }
766 
768  {
769  if (iataCode.isEmpty()) { return CAirlineIcaoCode(); }
770  if (m_icaoDataReader) { return m_icaoDataReader->getAirlineIcaoCodeForUniqueIataCodeOrDefault(iataCode); }
771  return CAirlineIcaoCode();
772  }
773 
775  {
776  if (m_icaoDataReader) { return m_icaoDataReader->getAirlineIcaoCodesCount(); }
777  return 0;
778  }
779 
781  {
782  QStringList names;
783  if (!m_icaoDataReader) { return names; }
784  for (const CAirlineIcaoCode &code : this->getAirlineIcaoCodes())
785  {
786  if (code.hasName()) { names.push_back(code.getName()); }
787  }
788  return names;
789  }
790 
792  {
793  QStringList designators;
794  if (!m_icaoDataReader) { return designators; }
795  for (const CAirlineIcaoCode &code : this->getAirlineIcaoCodes())
796  {
797  if (code.hasTelephonyDesignator()) { designators.push_back(code.getTelephonyDesignator()); }
798  }
799  return designators;
800  }
801 
803  const CCallsign &callsign) const
804  {
805  if (m_icaoDataReader) { return m_icaoDataReader->smartAirlineIcaoSelector(icaoPattern, callsign); }
806  return CAirlineIcaoCode();
807  }
808 
810  {
811  if (callsign.isEmpty()) { return CAirlineIcaoCode(); }
812  const CAirlineIcaoCodeList icaos(this->getAirlineIcaoCodes());
813  return icaos.findBestMatchByCallsign(callsign);
814  }
815 
817  {
818  if (m_icaoDataReader) { return m_icaoDataReader->getAirlineIcaoCodeForDbKey(key); }
819  return CAirlineIcaoCode();
820  }
821 
823  {
824  if (m_icaoDataReader) { return m_icaoDataReader->getCountries(); }
825  return CCountryList();
826  }
827 
829  {
830  if (m_icaoDataReader) { return m_icaoDataReader->getCountriesCount(); }
831  return 0;
832  }
833 
835  {
836  if (m_icaoDataReader) { return m_icaoDataReader->getCountryForName(name); }
837  return CCountry();
838  }
839 
841  {
842  if (m_airportDataReader) { return m_airportDataReader->getAirports(); }
843  return CAirportList();
844  }
845 
847  {
848  if (m_airportDataReader) { return m_airportDataReader->getAirportsCount(); }
849  return 0;
850  }
851 
853  {
854  if (m_airportDataReader) { return m_airportDataReader->getAirportForIcaoDesignator(icao); }
855  return CAirport();
856  }
857 
858  CAirport CWebDataServices::getAirportForNameOrLocation(const QString &nameOrLocation) const
859  {
860  if (m_airportDataReader) { return m_airportDataReader->getAirportForNameOrLocation(nameOrLocation); }
861  return CAirport();
862  }
863 
865  {
866  if (m_icaoDataReader) { return m_icaoDataReader->getCountryForIsoCode(iso); }
867  return CCountry();
868  }
869 
871  {
872  if (m_vatsimMetarReader) { return m_vatsimMetarReader->getMetars(); }
873  return {};
874  }
875 
877  {
878  if (m_vatsimMetarReader) { return m_vatsimMetarReader->getMetarForAirport(icao); }
879  return CMetar();
880  }
881 
883  bool ignoreEqual, CAircraftModelList &validModels,
884  CAircraftModelList &invalidModels) const
885  {
886  CStatusMessageList msgs(
887  modelsToBePublished.validateForPublishing(validModels, invalidModels)); // technical validation
888 
889  // check against existing distributors
890  const CDistributorList distributors(this->getDistributors());
891  if (!distributors.isEmpty())
892  {
893  // only further check the valid ones
894  CAircraftModelList newValidModels;
895  const CStatusMessageList msgsDistributors(
896  validModels.validateDistributors(distributors, newValidModels, invalidModels));
897  validModels = newValidModels;
898  msgs.push_back(msgsDistributors);
899  }
900 
901  // check if model is changed
902  // in case of not ignoreEqual we just check create the messages
903  {
904  CAircraftModelList newValidModels;
905  for (const CAircraftModel &publishModel : validModels)
906  {
907  CStatusMessageList equalMessages;
908  const bool changed = !this->isDbModelEqualForPublishing(publishModel, &equalMessages);
909  if (changed)
910  {
911  // all good
912  newValidModels.push_back(publishModel);
913  continue;
914  }
915  if (ignoreEqual) { equalMessages.warningToError(); }
916  msgs.push_back(
918  u"Model: '%1', there is no change")
919  << publishModel.getModelString());
920  if (ignoreEqual) { invalidModels.push_back(publishModel); }
921  else { newValidModels.push_back(publishModel); }
922  }
923  validModels = newValidModels;
924  }
925  return msgs;
926  }
927 
929  CStatusMessageList *details) const
930  {
931  const CAircraftModel compareDbModel = modelToBeChecked.isLoadedFromDb() ?
932  this->getModelForDbKey(modelToBeChecked.getDbKey()) :
933  this->getModelForModelString(modelToBeChecked.getModelString());
934  return modelToBeChecked.isEqualForPublishing(compareDbModel, details);
935  }
936 
938  {
939  if (m_icaoDataReader) { return m_icaoDataReader->getAirlineIcaoCodesForDesignator(designator); }
940  return CAirlineIcaoCodeList();
941  }
942 
943  int CWebDataServices::getAirlineIcaoCodesForDesignatorCount(const QString &designator) const
944  {
945  return this->getAirlineIcaoCodesForDesignator(designator).size();
946  }
947 
949  {
950  if (m_shuttingDown) { return; }
951  m_shuttingDown = true;
952  this->disconnect(); // all signals
953  if (m_vatsimMetarReader)
954  {
955  m_vatsimMetarReader->quitAndWait();
956  m_vatsimMetarReader = nullptr;
957  }
958  if (m_vatsimDataFileReader)
959  {
960  m_vatsimDataFileReader->quitAndWait();
961  m_vatsimDataFileReader = nullptr;
962  }
963  if (m_vatsimStatusReader)
964  {
965  m_vatsimStatusReader->quitAndWait();
966  m_vatsimStatusReader = nullptr;
967  }
968  if (m_vatsimServerFileReader)
969  {
970  m_vatsimServerFileReader->quitAndWait();
971  m_vatsimServerFileReader = nullptr;
972  }
973  if (m_modelDataReader)
974  {
975  m_modelDataReader->quitAndWait();
976  m_modelDataReader = nullptr;
977  }
978  if (m_airportDataReader)
979  {
980  m_airportDataReader->quitAndWait();
981  m_airportDataReader = nullptr;
982  }
983  if (m_icaoDataReader)
984  {
985  m_icaoDataReader->quitAndWait();
986  m_icaoDataReader = nullptr;
987  }
988  if (m_dbInfoDataReader)
989  {
990  m_dbInfoDataReader->quitAndWait();
991  m_dbInfoDataReader = nullptr;
992  }
993 
994  // DB writer is no threaded reader, it has a special role
995  if (m_databaseWriter)
996  {
997  m_databaseWriter->gracefulShutdown();
998  m_databaseWriter = nullptr;
999  }
1000  }
1001 
1003  {
1004  // obtain entities from real readers (means when reader is really used)
1005  CEntityFlags::Entity entities = CEntityFlags::NoEntity;
1006  if (m_icaoDataReader) { entities |= CWebReaderFlags::allEntitiesForReaders(CWebReaderFlags::IcaoDataReader); }
1007  if (m_modelDataReader) { entities |= CWebReaderFlags::allEntitiesForReaders(CWebReaderFlags::ModelReader); }
1008  if (m_airportDataReader) { entities |= CWebReaderFlags::allEntitiesForReaders(CWebReaderFlags::AirportReader); }
1009 
1010  // when we have a config, we ignore the ones not from cache or DB
1011  if (!m_dbReaderConfig.isEmpty())
1012  {
1013  CEntityFlags::Entity configuredEntities = m_dbReaderConfig.getEntitesCachedOrReadFromDB();
1014  entities &= configuredEntities;
1015  }
1016 
1017  entities &= CEntityFlags::AllDbEntities; // make sure to only use DB data
1018  return entities;
1019  }
1020 
1022  {
1023  static const QStringList cats { "swift.datareader", CLogCategories::webservice() };
1024  return cats;
1025  }
1026 
1027  void CWebDataServices::initReaders(CWebReaderFlags::WebReader readersNeeded, CEntityFlags::Entity entities)
1028  {
1029  Q_ASSERT_X(CThreadUtils::thisIsMainThread(), Q_FUNC_INFO, "shall run in main application thread");
1030 
1031  //
1032  // ---- "metadata" reader, 1 will trigger read directly during init
1033  //
1034  CDatabaseReaderConfigList dbReaderConfig(m_dbReaderConfig);
1035  const CEntityFlags::Entity dbEntities = entities & CEntityFlags::AllDbEntitiesNoInfoObjects;
1036  const bool anyDbEntities = CEntityFlags::anySwiftDbEntity(dbEntities); // contains any DB entities
1037  const bool needsSharedInfoObjects = dbReaderConfig.needsSharedInfoObjects(dbEntities);
1038  const bool needsDbInfoObjects = dbReaderConfig.possiblyReadsFromSwiftDb();
1039  bool c = false; // for signal connect
1040 
1041  // 1a. If any DB data, read the info objects upfront
1042  if (needsDbInfoObjects)
1043  {
1044  if (anyDbEntities && readersNeeded.testFlag(CWebReaderFlags::WebReaderFlag::DbInfoDataReader))
1045  {
1046  // info data reader has a special role, it will not be triggered in triggerRead()
1047  this->initDbInfoObjectReaderAndTriggerRead();
1048  }
1049  }
1050 
1051  // 1b. Read info objects if needed
1052  if (needsSharedInfoObjects) { this->initSharedInfoObjectReaderAndTriggerRead(); }
1053 
1054  // 2. Status and server file, updating the VATSIM related caches
1055  // Read as soon as initReaders is done
1056  if (readersNeeded.testFlag(CWebReaderFlags::VatsimStatusReader) ||
1057  readersNeeded.testFlag(CWebReaderFlags::VatsimDataReader) ||
1058  readersNeeded.testFlag(CWebReaderFlags::VatsimMetarReader))
1059  {
1060  m_vatsimStatusReader = new CVatsimStatusFileReader(this);
1061  c = connect(m_vatsimStatusReader, &CVatsimStatusFileReader::statusFileRead, this,
1062  &CWebDataServices::vatsimStatusFileRead, Qt::QueuedConnection);
1063  CLogMessage(this).info(u"Trigger read of VATSIM status file");
1064  m_vatsimStatusReader->start(QThread::LowPriority);
1065 
1066  // run single shot in main loop, so readInBackgroundThread is not called before initReaders completes
1067  const QPointer<CWebDataServices> myself(this);
1068  QTimer::singleShot(0, this, [=]() {
1069  if (!myself || m_shuttingDown) { return; }
1070  if (!sApp || sApp->isShuttingDown()) { return; }
1071  m_vatsimStatusReader->readInBackgroundThread();
1072  });
1073 
1074  startVatsimServerFileReader();
1075  }
1076 
1077  // ---- "normal data", triggerRead will start read, not starting directly
1078 
1079  // 3. VATSIM data file
1080  if (readersNeeded.testFlag(CWebReaderFlags::WebReaderFlag::VatsimDataReader))
1081  {
1082  m_vatsimDataFileReader = new CVatsimDataFileReader(this);
1083  c = connect(m_vatsimDataFileReader, &CVatsimDataFileReader::dataFileRead, this,
1084  &CWebDataServices::vatsimDataFileRead, Qt::QueuedConnection);
1085  Q_ASSERT_X(c, Q_FUNC_INFO, "VATSIM data reader signals");
1086  c = connect(m_vatsimDataFileReader, &CVatsimDataFileReader::dataRead, this, &CWebDataServices::dataRead,
1087  Qt::QueuedConnection);
1088  Q_ASSERT_X(c, Q_FUNC_INFO, "connect failed VATSIM data file");
1089  m_entitiesPeriodicallyRead |= CEntityFlags::VatsimDataFile;
1090  m_vatsimDataFileReader->start(QThread::LowPriority);
1091  m_vatsimDataFileReader->startReader();
1092  }
1093 
1094  // 4. VATSIM METAR data
1095  if (readersNeeded.testFlag(CWebReaderFlags::WebReaderFlag::VatsimMetarReader))
1096  {
1097  m_vatsimMetarReader = new CVatsimMetarReader(this);
1098  c = connect(m_vatsimMetarReader, &CVatsimMetarReader::metarsRead, this, &CWebDataServices::receivedMetars,
1099  Qt::QueuedConnection);
1100  Q_ASSERT_X(c, Q_FUNC_INFO, "VATSIM METAR reader signals");
1101  c = connect(m_vatsimMetarReader, &CVatsimMetarReader::dataRead, this, &CWebDataServices::dataRead,
1102  Qt::QueuedConnection);
1103  Q_ASSERT_X(c, Q_FUNC_INFO, "connect failed VATSIM METAR");
1104  m_entitiesPeriodicallyRead |= CEntityFlags::MetarEntity;
1105  m_vatsimMetarReader->start(QThread::LowPriority);
1106  m_vatsimMetarReader->startReader();
1107  }
1108 
1109  // 5. ICAO data reader
1110  if (readersNeeded.testFlag(CWebReaderFlags::WebReaderFlag::IcaoDataReader))
1111  {
1112  m_icaoDataReader = new CIcaoDataReader(this, dbReaderConfig);
1113  c = connect(m_icaoDataReader, &CIcaoDataReader::dataRead, this, &CWebDataServices::readFromSwiftReader,
1114  Qt::QueuedConnection);
1115  Q_ASSERT_X(c, Q_FUNC_INFO, "Cannot connect ICAO reader signals");
1116  c = connect(m_icaoDataReader, &CIcaoDataReader::dataRead, this, &CWebDataServices::dataRead,
1117  Qt::QueuedConnection);
1118  Q_ASSERT_X(c, Q_FUNC_INFO, "Cannot connect ICAO reader signals");
1119  c = connect(m_icaoDataReader, &CIcaoDataReader::swiftDbDataRead, this, &CWebDataServices::swiftDbDataRead,
1120  Qt::QueuedConnection);
1121  Q_ASSERT_X(c, Q_FUNC_INFO, "Cannot connect Model reader signals");
1122  c = connect(m_icaoDataReader, &CIcaoDataReader::entityDownloadProgress, this,
1123  &CWebDataServices::entityDownloadProgress, Qt::QueuedConnection);
1124  Q_ASSERT_X(c, Q_FUNC_INFO, "Cannot connect Model reader signals");
1125  m_icaoDataReader->start(QThread::LowPriority);
1126  }
1127 
1128  // 6. Model reader
1129  if (readersNeeded.testFlag(CWebReaderFlags::WebReaderFlag::ModelReader))
1130  {
1131  m_modelDataReader = new CModelDataReader(this, dbReaderConfig);
1132  c = connect(m_modelDataReader, &CModelDataReader::dataRead, this, &CWebDataServices::readFromSwiftReader,
1133  Qt::QueuedConnection);
1134  Q_ASSERT_X(c, Q_FUNC_INFO, "Cannot connect Model reader signals");
1135  c = connect(m_modelDataReader, &CModelDataReader::dataRead, this, &CWebDataServices::dataRead,
1136  Qt::QueuedConnection);
1137  Q_ASSERT_X(c, Q_FUNC_INFO, "Cannot connect Model reader signals");
1138  c = connect(m_modelDataReader, &CModelDataReader::swiftDbDataRead, this, &CWebDataServices::swiftDbDataRead,
1139  Qt::QueuedConnection);
1140  Q_ASSERT_X(c, Q_FUNC_INFO, "Cannot connect Model reader signals");
1141  c = connect(m_modelDataReader, &CModelDataReader::entityDownloadProgress, this,
1142  &CWebDataServices::entityDownloadProgress, Qt::QueuedConnection);
1143  Q_ASSERT_X(c, Q_FUNC_INFO, "Cannot connect Model reader signals");
1144  m_modelDataReader->start(QThread::LowPriority);
1145  }
1146 
1147  // 7. Airport reader
1148  if (readersNeeded.testFlag(CWebReaderFlags::WebReaderFlag::AirportReader))
1149  {
1150  m_airportDataReader = new CAirportDataReader(this, dbReaderConfig);
1151  c = connect(m_airportDataReader, &CAirportDataReader::dataRead, this,
1152  &CWebDataServices::readFromSwiftReader, Qt::QueuedConnection);
1153  Q_ASSERT_X(c, Q_FUNC_INFO, "Cannot connect Model reader signals");
1154  c = connect(m_airportDataReader, &CAirportDataReader::dataRead, this, &CWebDataServices::dataRead,
1155  Qt::QueuedConnection);
1156  Q_ASSERT_X(c, Q_FUNC_INFO, "Cannot connect Model reader signals");
1157  c = connect(m_airportDataReader, &CAirportDataReader::swiftDbDataRead, this,
1158  &CWebDataServices::swiftDbDataRead, Qt::QueuedConnection);
1159  Q_ASSERT_X(c, Q_FUNC_INFO, "Cannot connect Model reader signals");
1160  c = connect(m_airportDataReader, &CAirportDataReader::entityDownloadProgress, this,
1161  &CWebDataServices::entityDownloadProgress, Qt::QueuedConnection);
1162  Q_ASSERT_X(c, Q_FUNC_INFO, "Cannot connect Model reader signals");
1163  m_airportDataReader->start(QThread::LowPriority);
1164  }
1165  Q_UNUSED(c) // signal connect flag
1166 
1167  const QDateTime threshold =
1168  QDateTime::currentDateTimeUtc().addDays(-365); // country and airports are "semi static"
1169  const CEntityFlags::Entity cachedDbEntities =
1170  this->getDbEntitiesWithCachedData(); // those caches are already read
1171  const CEntityFlags::Entity validTsDbEntities =
1172  this->getDbEntitiesWithTimestampNewerThan(threshold); // those caches are not read, but have a timestamp
1173  const bool needsSharedInfoObjectsWithoutCache =
1174  dbReaderConfig.needsSharedInfoObjectsIfCachesEmpty(dbEntities, cachedDbEntities | validTsDbEntities);
1175  if (m_sharedInfoDataReader && !needsSharedInfoObjectsWithoutCache)
1176  {
1177  // demote error message
1178  // Rational: we cannot read shared info objects, but we have and use cached objects
1180  }
1181  }
1182 
1183  void CWebDataServices::startVatsimServerFileReader()
1184  {
1185  m_vatsimServerFileReader = new CVatsimServerFileReader(this);
1186  connect(m_vatsimServerFileReader, &CVatsimServerFileReader::dataFileRead, this,
1187  &CWebDataServices::vatsimServerFileRead, Qt::QueuedConnection);
1188  CLogMessage(this).info(u"Trigger read of VATSIM server file");
1189  m_vatsimServerFileReader->start(QThread::LowPriority);
1190 
1191  // run single shot in main loop, so readInBackgroundThread is not called before initReaders completes
1192  const QPointer<CWebDataServices> myself(this);
1193  QTimer::singleShot(0, this, [=]() {
1194  if (!myself || m_shuttingDown) { return; }
1195  if (!sApp || sApp->isShuttingDown()) { return; }
1196  m_vatsimServerFileReader->readInBackgroundThread();
1197  });
1198  }
1199 
1200  void CWebDataServices::initDbInfoObjectReaderAndTriggerRead()
1201  {
1202  // run in correct thread
1203  if (m_shuttingDown) { return; }
1204  if (!CThreadUtils::isInThisThread(this))
1205  {
1206  const QPointer<CWebDataServices> myself(this);
1207  QTimer::singleShot(0, this, [=] {
1208  if (!myself || m_shuttingDown) { return; }
1209  if (!sApp || sApp->isShuttingDown()) { return; }
1210  this->initDbInfoObjectReaderAndTriggerRead();
1211  });
1212  return;
1213  }
1214 
1215  if (!m_dbInfoDataReader)
1216  {
1217  m_dbInfoDataReader = new CInfoDataReader(this, m_dbReaderConfig, CDbFlags::DbReading);
1218  m_dbInfoDataReader->setObjectName(m_dbInfoDataReader->objectName() + " (DB)");
1219  bool c =
1220  connect(m_dbInfoDataReader, &CInfoDataReader::dataRead, this, &CWebDataServices::readFromSwiftReader);
1221  Q_ASSERT_X(c, Q_FUNC_INFO, "Info reader connect failed");
1222 
1223  // relay signal
1224  c = connect(m_dbInfoDataReader, &CInfoDataReader::dataRead, this, &CWebDataServices::dataRead);
1225  Q_ASSERT_X(c, Q_FUNC_INFO, "Info reader connect failed");
1226  c = connect(m_dbInfoDataReader, &CInfoDataReader::databaseReaderMessages, this,
1228  Q_UNUSED(c)
1229 
1230  // start in own thread
1231  m_dbInfoDataReader->start(QThread::LowPriority);
1232 
1233  const QPointer<CWebDataServices> myself(this);
1234  QTimer::singleShot(25, m_dbInfoDataReader, [=]() {
1235  if (!myself || m_shuttingDown) { return; }
1236  if (!sApp || sApp->isShuttingDown()) { return; }
1237  m_dbInfoDataReader->readInfoData(); // trigger read of info objects
1238  });
1239  }
1240  }
1241 
1242  void CWebDataServices::initSharedInfoObjectReaderAndTriggerRead()
1243  {
1244  // run in correct thread
1245  if (m_shuttingDown) { return; }
1246  if (!CThreadUtils::isInThisThread(this))
1247  {
1248  const QPointer<CWebDataServices> myself(this);
1249  QTimer::singleShot(0, this, [=] {
1250  if (!myself || m_shuttingDown) { return; }
1251  this->initSharedInfoObjectReaderAndTriggerRead();
1252  });
1253  return;
1254  }
1255 
1256  if (!m_sharedInfoDataReader)
1257  {
1258  m_sharedInfoDataReader = new CInfoDataReader(this, m_dbReaderConfig, CDbFlags::Shared);
1259  m_sharedInfoDataReader->setObjectName(m_sharedInfoDataReader->objectName() + " (shared)");
1260  bool c = connect(m_sharedInfoDataReader, &CInfoDataReader::dataRead, this,
1261  &CWebDataServices::readFromSwiftReader);
1262  Q_ASSERT_X(c, Q_FUNC_INFO, "Info reader connect failed");
1263 
1264  // relay signal
1265  c = connect(m_sharedInfoDataReader, &CInfoDataReader::dataRead, this, &CWebDataServices::dataRead);
1266  Q_ASSERT_X(c, Q_FUNC_INFO, "Info reader connect failed");
1267  Q_UNUSED(c)
1268 
1269  // start in own thread
1270  m_sharedInfoDataReader->start(QThread::LowPriority);
1271  }
1272 
1273  // and trigger read
1274  const QPointer<CWebDataServices> myself(this);
1275  QTimer::singleShot(25, m_sharedInfoDataReader, [=]() {
1276  if (!myself || m_shuttingDown) { return; }
1277  m_sharedInfoDataReader->readInfoData();
1278  });
1279  }
1280 
1281  CDatabaseReader *CWebDataServices::getDbReader(CEntityFlags::Entity entity) const
1282  {
1283  Q_ASSERT_X(CEntityFlags::isSingleEntity(entity), Q_FUNC_INFO, "Need single entity");
1284  Q_ASSERT_X(CEntityFlags::anySwiftDbEntity(entity), Q_FUNC_INFO, "No swift DB entity");
1285 
1286  const CWebReaderFlags::WebReader wr = CWebReaderFlags::entitiesToReaders(entity);
1287  switch (wr)
1288  {
1289  case CWebReaderFlags::IcaoDataReader: return m_icaoDataReader;
1290  case CWebReaderFlags::ModelReader: return m_modelDataReader;
1291  case CWebReaderFlags::AirportReader: return m_airportDataReader;
1292  default: break;
1293  }
1294  return nullptr;
1295  }
1296 
1297  void CWebDataServices::initWriters()
1298  {
1299  m_databaseWriter = new CDatabaseWriter(sApp->getGlobalSetup().getDbRootDirectoryUrl(), this);
1300  }
1301 
1302  bool CWebDataServices::signalEntitiesAlreadyRead(CEntityFlags::Entity entities)
1303  {
1304  if (m_signalledEntities.contains(entities)) { return false; }
1305  m_signalledEntities.insert(entities);
1306  return true;
1307  }
1308 
1309  int CWebDataServices::getInfoObjectCount(CEntityFlags::Entity entity, CInfoDataReader *reader) const
1310  {
1311  Q_ASSERT_X(CEntityFlags::isSingleEntity(entity), Q_FUNC_INFO, "Need single entity");
1312  Q_ASSERT_X(reader, Q_FUNC_INFO, "Need reader");
1313  if (CEntityFlags::anySwiftDbEntity(entity))
1314  {
1315  const CDbInfo info = reader->getInfoObjects().findFirstByEntityOrDefault(entity);
1316  return info.getEntries();
1317  }
1318  else
1319  {
1320  // non DB entities would go here
1321  return -1;
1322  }
1323  }
1324 
1325  CEntityFlags::Entity CWebDataServices::getDbEntitiesWithCachedData() const
1326  {
1327  CEntityFlags::Entity entities = CEntityFlags::NoEntity;
1328  if (m_airportDataReader) { entities |= m_airportDataReader->getEntitiesWithCacheCount(); }
1329  if (m_icaoDataReader) { entities |= m_icaoDataReader->getEntitiesWithCacheCount(); }
1330  if (m_modelDataReader) { entities |= m_modelDataReader->getEntitiesWithCacheCount(); }
1331  return entities;
1332  }
1333 
1334  CEntityFlags::Entity CWebDataServices::getDbEntitiesWithTimestampNewerThan(const QDateTime &threshold) const
1335  {
1336  CEntityFlags::Entity entities = CEntityFlags::NoEntity;
1337  if (m_airportDataReader) { entities |= m_airportDataReader->getEntitiesWithCacheTimestampNewerThan(threshold); }
1338  if (m_icaoDataReader) { entities |= m_icaoDataReader->getEntitiesWithCacheTimestampNewerThan(threshold); }
1339  if (m_modelDataReader) { entities |= m_modelDataReader->getEntitiesWithCacheTimestampNewerThan(threshold); }
1340  return entities;
1341  }
1342 
1343  void CWebDataServices::receivedMetars(const CMetarList &metars)
1344  {
1345  CLogMessage(this).info(u"Read %1 METARs") << metars.size();
1346  }
1347 
1348  void CWebDataServices::vatsimDataFileRead(int kB) { CLogMessage(this).info(u"Read VATSIM data file, %1 kB") << kB; }
1349 
1350  void CWebDataServices::vatsimStatusFileRead(int bytes)
1351  {
1352  CLogMessage(this).info(u"Read VATSIM status file, %1 bytes") << bytes;
1353  }
1354 
1355  void CWebDataServices::vatsimServerFileRead(int bytes)
1356  {
1357  CLogMessage(this).info(u"Read VATSIM server file, %1 bytes") << bytes;
1358  }
1359 
1360  void CWebDataServices::readFromSwiftReader(CEntityFlags::Entity entities, CEntityFlags::ReadState state, int number,
1361  const QUrl &url)
1362  {
1363  if (state == CEntityFlags::ReadStarted) { return; } // just started
1364 
1365  const QString from = url.isEmpty() ? QStringLiteral("") : QStringLiteral(" from '%1'").arg(url.toString());
1366  const QString entStr = CEntityFlags::entitiesToString(entities);
1367 
1368  if (CEntityFlags::isWarningOrAbove(state))
1369  {
1370  const CStatusMessage::StatusSeverity severity = CEntityFlags::flagToSeverity(state);
1371  if (severity == CStatusMessage::SeverityWarning)
1372  {
1373  CLogMessage(this).warning(u"Read data '%1' entries: %2 state: %3%4")
1374  << entStr << number << CEntityFlags::stateToString(state) << from;
1375  }
1376  else
1377  {
1378  CLogMessage(this).error(u"Read data '%1' entries: %2 state: %3%4")
1379  << entStr << number << CEntityFlags::stateToString(state) << from;
1380  }
1381  }
1382  else
1383  {
1384  CLogMessage(this).info(u"Read data '%1' entries: %2 state: %3%4")
1385  << entStr << number << CEntityFlags::stateToString(state) << from;
1386  }
1387 
1388  m_swiftDbEntitiesRead |= entities;
1389  const int allUsedEntities = static_cast<int>(this->allDbEntitiesForUsedReaders());
1390  if (((static_cast<int>(m_swiftDbEntitiesRead)) & allUsedEntities) == allUsedEntities)
1391  {
1392  emit this->swiftDbAllDataRead();
1393  }
1394 
1395  // individual signals
1396  if (CEntityFlags::isFinishedReadState(state))
1397  {
1398  // emit one time only
1399  if (entities.testFlag(CEntityFlags::AirportEntity) &&
1400  signalEntitiesAlreadyRead(CEntityFlags::AirportEntity))
1401  {
1402  emit swiftDbAirportsRead();
1403  }
1404  if (entities.testFlag(CEntityFlags::AirlineIcaoEntity) &&
1405  signalEntitiesAlreadyRead(CEntityFlags::AirlineIcaoEntity))
1406  {
1407  emit swiftDbAirlineIcaoRead();
1408  }
1409  if (entities.testFlag(CEntityFlags::AircraftIcaoEntity) &&
1410  signalEntitiesAlreadyRead(CEntityFlags::AircraftIcaoEntity))
1411  {
1412  emit swiftDbAircraftIcaoRead();
1413  }
1414  if (entities.testFlag(CEntityFlags::ModelEntity) && signalEntitiesAlreadyRead(CEntityFlags::ModelEntity))
1415  {
1416  emit swiftDbModelsRead();
1417  }
1418  if (entities.testFlag(CEntityFlags::SharedInfoObjectEntity)) { emit sharedInfoObjectsRead(); }
1419 
1420  if (m_swiftDbEntitiesRead.testFlag(CEntityFlags::AllIcaoEntities) &&
1421  signalEntitiesAlreadyRead(CEntityFlags::AllIcaoEntities))
1422  {
1423  emit this->swiftDbAllIcaoEntitiesRead();
1424  }
1425  if (m_swiftDbEntitiesRead.testFlag(CEntityFlags::ModelMatchingEntities) &&
1426  signalEntitiesAlreadyRead(CEntityFlags::ModelMatchingEntities))
1427  {
1428  emit this->swiftDbModelMatchingEntitiesRead();
1429  }
1430  }
1431  }
1432 
1433  void CWebDataServices::readDeferredInBackground(CEntityFlags::Entity entities, int delayMs)
1434  {
1435  if (m_shuttingDown) { return; }
1436  if (entities == CEntityFlags::NoEntity) { return; }
1437  const QPointer<CWebDataServices> myself(this);
1438  QTimer::singleShot(delayMs, [=]() // clazy:exclude=connect-3arg-lambda
1439  {
1440  if (!myself || m_shuttingDown) { return; }
1441  this->readInBackground(entities); // deferred
1442  });
1443  }
1444 
1445  void CWebDataServices::readInBackground(CEntityFlags::Entity entities)
1446  {
1447  if (m_shuttingDown) { return; }
1448 
1449  if (CEntityFlags::anySwiftDbEntity(entities))
1450  {
1451  // with info objects wait until info objects are loaded
1452  Q_ASSERT_X(!entities.testFlag(CEntityFlags::DbInfoObjectEntity), Q_FUNC_INFO,
1453  "Info object must be read upfront, do not pass as entity here");
1454  const bool waitForDbInfoReader = m_dbInfoDataReader && !m_dbInfoDataReader->areAllInfoObjectsRead() &&
1455  !m_dbInfoDataReader->isMarkedAsFailed();
1456  if (waitForDbInfoReader)
1457  {
1458  // do not read yet, will call this function again after some time
1459  // see CWebDataServices::waitForInfoObjects
1460  if (!this->waitForDbInfoObjectsThenRead(entities)) { return; }
1461  }
1462 
1463  const bool waitForSharedInfoFile =
1464  m_dbReaderConfig.needsSharedInfoFile(entities) && !m_sharedInfoDataReader->areAllInfoObjectsRead();
1465  if (waitForSharedInfoFile)
1466  {
1467  // do not read yet, will call this function again after some time
1468  // CWebDataServices::waitForInfoObjects
1469  if (!this->waitForSharedInfoObjectsThenRead(entities)) { return; }
1470  }
1471  }
1472 
1473  // read entities
1474  this->triggerRead(entities);
1475  }
1476 
1477  bool CWebDataServices::waitForDbInfoObjectsThenRead(CEntityFlags::Entity entities)
1478  {
1479  if (m_shuttingDown) { return false; }
1480 
1481  Q_ASSERT_X(m_dbInfoDataReader, Q_FUNC_INFO, "need reader");
1482 
1483  // in a dev build all symbols are loaded which sometimes causes unnecessary timeout
1484  if (m_dbInfoDataReader->areAllInfoObjectsRead()) { return true; }
1485  const int timeOutMs = 30 * 1000;
1486  if (!m_dbInfoObjectTimeout.isValid())
1487  {
1488  m_dbInfoObjectTimeout = QDateTime::currentDateTimeUtc().addMSecs(timeOutMs);
1489  CLogMessage(this).info(u"Set DbInfoObjects timeout %1ms to %2")
1490  << timeOutMs << m_dbInfoObjectTimeout.toString("dd.MM.yyyy hh:mm:ss");
1491  }
1492  const bool read = this->waitForInfoObjectsThenRead(entities, "DB", m_dbInfoDataReader, m_dbInfoObjectTimeout);
1493  return read;
1494  }
1495 
1496  bool CWebDataServices::waitForSharedInfoObjectsThenRead(CEntityFlags::Entity entities)
1497  {
1498  if (m_shuttingDown) { return false; }
1499 
1500  Q_ASSERT_X(m_sharedInfoDataReader, Q_FUNC_INFO, "need reader");
1501  if (m_sharedInfoDataReader->areAllInfoObjectsRead()) { return true; }
1502  const int timeOutMs = 30 * 1000;
1503  if (!m_sharedInfoObjectsTimeout.isValid())
1504  {
1505  m_sharedInfoObjectsTimeout = QDateTime::currentDateTimeUtc().addMSecs(timeOutMs);
1506  CLogMessage(this).info(u"Set SharedInfoObjects timeout %1ms to %2")
1507  << timeOutMs << m_sharedInfoObjectsTimeout.toString("dd.MM.yyyy hh:mm:ss");
1508  }
1509  const bool read =
1510  this->waitForInfoObjectsThenRead(entities, "shared", m_sharedInfoDataReader, m_sharedInfoObjectsTimeout);
1511  return read;
1512  }
1513 
1514  bool CWebDataServices::waitForInfoObjectsThenRead(CEntityFlags::Entity entities, const QString &info,
1515  CInfoDataReader *infoReader, QDateTime &timeOut)
1516  {
1517  if (m_shuttingDown) { return false; }
1518 
1519  // this will called for each entity readers, i.e. model reader, ICAO reader ...
1520  Q_ASSERT_X(infoReader, Q_FUNC_INFO, "Need info data reader");
1521  const int waitForInfoObjectsMs = 1000; // ms
1522 
1523  if (infoReader->areAllInfoObjectsRead())
1524  {
1525  // we have all data and carry on
1526  CLogMessage(this).info(u"Info objects (%1) triggered for '%2' loaded from '%3'")
1527  << info << CEntityFlags::entitiesToString(entities) << infoReader->getInfoObjectsUrl().toQString();
1528  timeOut = QDateTime(); // reset to null
1529  return true; // no need to wait any longer
1530  }
1531 
1532  // try to read if not timed out
1533  if (timeOut.isValid() && QDateTime::currentDateTimeUtc() > timeOut)
1534  {
1535  const QString timeOutString = timeOut.toString();
1536  const CStatusMessage m =
1537  CLogMessage(this).warning(u"Could not read '%1' info objects for '%2' from '%3', time out '%4'. "
1538  u"Marking reader '%5' as failed and continue.")
1539  << info << CEntityFlags::entitiesToString(entities) << infoReader->getInfoObjectsUrl().toQString()
1540  << timeOutString << infoReader->getName();
1541  emit this->databaseReaderMessages(m);
1542 
1543  // continue here and read data without info objects
1544  infoReader->setMarkedAsFailed(true);
1545  // no timeout reset here
1546  return true; // carry on, regardless of situation
1547  }
1548 
1549  if (infoReader->hasReceivedFirstReply())
1550  {
1551  // we have received a response, but not all data yet
1552  if (infoReader->hasReceivedOkReply())
1553  {
1554  // ok, this means we are parsing
1555  this->readDeferredInBackground(entities, waitForInfoObjectsMs);
1556  const CStatusMessage m = CLogMessage(this).info(u"Parsing objects (%1) for '%2' from '%3'")
1557  << info << CEntityFlags::entitiesToString(entities)
1558  << infoReader->getInfoObjectsUrl().toQString();
1559  emit this->databaseReaderMessages(m);
1560  return false; // wait
1561  }
1562  else
1563  {
1564  // we have a response, but a failure, means server is alive, but responded with error
1565  // such an error (access, ...) normally will not go away
1566  const CStatusMessage m =
1567  CLogMessage(this).error(u"Info objects (%1) loading for '%2' failed from '%3', '%4'")
1568  << info << CEntityFlags::entitiesToString(entities) << infoReader->getInfoObjectsUrl().toQString()
1569  << infoReader->getStatusMessage();
1570  infoReader->setMarkedAsFailed(true);
1571  emit this->databaseReaderMessages(m);
1572  return true; // carry on, regardless of situation
1573  }
1574  }
1575  else
1576  {
1577  // wait for 1st reply
1578  // we call read again in some time
1579  this->readDeferredInBackground(entities, waitForInfoObjectsMs);
1580  return false; // wait
1581  }
1582  }
1583 
1584  bool CWebDataServices::writeDbDataToDisk(const QString &dir)
1585  {
1586  if (dir.isEmpty()) { return false; }
1587  const QDir directory(dir);
1588  if (!directory.exists())
1589  {
1590  const bool s = directory.mkpath(dir);
1591  if (!s) { return false; }
1592  }
1593  QList<QPair<QString, QString>> fileContents;
1594 
1595  if (this->getModelsCount() > 0)
1596  {
1597  const QString json(QJsonDocument(this->getModels().toJson()).toJson());
1598  fileContents.push_back({ "models.json", json });
1599  }
1600 
1601  if (this->getLiveriesCount() > 0)
1602  {
1603  const QString json(QJsonDocument(this->getLiveries().toJson()).toJson());
1604  fileContents.push_back({ "liveries.json", json });
1605  }
1606 
1607  if (this->getAirportsCount() > 0)
1608  {
1609  const QString json(QJsonDocument(this->getAirports().toJson()).toJson());
1610  fileContents.push_back({ "airports.json", json });
1611  }
1612 
1613  for (const auto &pair : fileContents)
1614  {
1615  CWorker::fromTask(this, Q_FUNC_INFO, [pair, directory] {
1616  CFileUtils::writeStringToFile(CFileUtils::appendFilePaths(directory.absolutePath(), pair.first),
1617  pair.second);
1618  });
1619  }
1620  return true;
1621  }
1622 
1623  bool CWebDataServices::readDbDataFromDisk(const QString &dir, bool inBackground, bool overrideNewerOnly)
1624  {
1625  if (dir.isEmpty()) { return false; }
1626  const QDir directory(dir);
1627  if (!directory.exists()) { return false; }
1628 
1629  bool s1 = !m_icaoDataReader;
1630  if (m_icaoDataReader)
1631  {
1632  // force update to background reading if reader is already in another thread
1633  bool ib = inBackground || !CThreadUtils::isInThisThread(m_icaoDataReader);
1634  if (ib)
1635  {
1636  CLogMessage(this).info(u"Reading from disk in background: %1")
1637  << m_icaoDataReader->getSupportedEntitiesAsString();
1638  s1 = m_icaoDataReader->readFromJsonFilesInBackground(dir, m_icaoDataReader->getSupportedEntities(),
1639  overrideNewerOnly);
1640  }
1641  else
1642  {
1643  const CStatusMessageList msgs = m_icaoDataReader->readFromJsonFiles(
1644  dir, m_icaoDataReader->getSupportedEntities(), overrideNewerOnly);
1646  s1 = msgs.isSuccess();
1647  }
1648  }
1649 
1650  bool s2 = !m_modelDataReader;
1651  if (m_modelDataReader)
1652  {
1653  // force update to background reading if reader is already in another thread
1654  bool ib = inBackground || !CThreadUtils::isInThisThread(m_modelDataReader);
1655  if (ib)
1656  {
1657  CLogMessage(this).info(u"Reading from disk in background: %1")
1658  << m_modelDataReader->getSupportedEntitiesAsString();
1659  s2 = m_modelDataReader->readFromJsonFilesInBackground(dir, m_modelDataReader->getSupportedEntities(),
1660  overrideNewerOnly);
1661  }
1662  else
1663  {
1664  const CStatusMessageList msgs = m_modelDataReader->readFromJsonFiles(
1665  dir, m_modelDataReader->getSupportedEntities(), overrideNewerOnly);
1667  s2 = msgs.isSuccess();
1668  }
1669  }
1670 
1671  bool s3 = !m_airportDataReader;
1672  if (m_airportDataReader)
1673  {
1674  // force update to background reading if reader is already in another thread
1675  bool ib = inBackground || !CThreadUtils::isInThisThread(m_airportDataReader);
1676  if (ib)
1677  {
1678  CLogMessage(this).info(u"Reading from disk in background: %1")
1679  << m_airportDataReader->getSupportedEntitiesAsString();
1680  s3 = m_airportDataReader->readFromJsonFilesInBackground(
1681  dir, m_airportDataReader->getSupportedEntities(), overrideNewerOnly);
1682  }
1683  else
1684  {
1685  const CStatusMessageList msgs = m_airportDataReader->readFromJsonFiles(
1686  dir, m_airportDataReader->getSupportedEntities(), overrideNewerOnly);
1688  s3 = msgs.isSuccess();
1689  }
1690  }
1691 
1692  return s1 && s2 && s3;
1693  }
1694 
1696  {
1697  CStatusMessageList msgs;
1698  msgs.push_back(m_icaoDataReader ? m_icaoDataReader->initFromLocalResourceFiles(inBackground) :
1699  CStatusMessage(this).info(u"No ICAO reader"));
1700  msgs.push_back(m_modelDataReader ? m_modelDataReader->initFromLocalResourceFiles(inBackground) :
1701  CStatusMessage(this).info(u"No model reader"));
1702  msgs.push_back(m_airportDataReader ? m_airportDataReader->initFromLocalResourceFiles(inBackground) :
1703  CStatusMessage(this).info(u"No airport reader"));
1704  return msgs;
1705  }
1706 
1709  bool inBackground)
1710  {
1711  CStatusMessageList msgs;
1712  msgs.push_back(m_icaoDataReader && m_icaoDataReader->supportsAnyOfEntities(entities) ?
1713  m_icaoDataReader->initFromLocalResourceFiles(entities, inBackground) :
1714  CStatusMessage(this).info(u"No ICAO reader or not supporting entities"));
1715  msgs.push_back(m_modelDataReader && m_modelDataReader->supportsAnyOfEntities(entities) ?
1716  m_modelDataReader->initFromLocalResourceFiles(entities, inBackground) :
1717  CStatusMessage(this).info(u"No model reader or not supporting entities"));
1718  msgs.push_back(m_airportDataReader && m_airportDataReader->supportsAnyOfEntities(entities) ?
1719  m_airportDataReader->initFromLocalResourceFiles(entities, inBackground) :
1720  CStatusMessage(this).info(u"No airport reader or not supporting entities"));
1721  return msgs;
1722  }
1724 } // 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 startReader()
Starts the reader.
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::aviation::CAirlineIcaoCode getAirlineIcaoCodeForDbKey(int id) const
ICAO code for id.
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)
void readDeferredInBackground(swift::misc::network::CEntityFlags::Entity entities, int delayMs)
Call CWebDataServices::readInBackground by single shot.
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.
swift::misc::aviation::CAircraftIcaoCode getAircraftIcaoCodeForDbKey(int id) const
ICAO code for id.
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::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::aviation::CAirlineIcaoCode smartAirlineIcaoSelector(const swift::misc::aviation::CAirlineIcaoCode &code, const swift::misc::aviation::CCallsign &callsign=swift::misc::aviation::CCallsign()) const
Smart airline selector.
swift::misc::simulation::CAircraftModel getModelForDbKey(int dbKey) const
Model for key if any.
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::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...)
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
@ VatsimMetarReader
reader for VATSIM metar data
@ 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)
@ VatsimDataReader
reader for VATSIM data
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 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 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.
void readInBackgroundThread()
Start reading in own thread.
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.
void readInBackgroundThread()
Read / re-read 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:311
void quitAndWait() noexcept final
Calls quit() and blocks until the thread is finished.
Definition: worker.cpp:205
void start(QThread::Priority priority=QThread::InheritPriority)
Starts a thread and moves the worker into it.
Definition: worker.cpp:166
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:201
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:76
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