#include <Navaids/waypoint.hxx>
#include <ATC/CommStation.hxx>
#include <Navaids/NavDataCache.hxx>
+#include <Navaids/navrecord.hxx>
using std::vector;
using std::pair;
mHelipadsLoaded(false),
mTaxiwaysLoaded(false),
mProceduresLoaded(false),
+ mThresholdDataLoaded(false),
mILSDataLoaded(false)
{
}
return; // already loaded, great
}
- loadSceneryDefinitions();
-
mHelipadsLoaded = true;
mHelipads = itemsOfType(FGPositioned::HELIPAD);
}
void FGAirport::loadSceneryDefinitions() const
{
+ if (mThresholdDataLoaded) {
+ return;
+ }
+
+ mThresholdDataLoaded = true;
+
SGPath path;
if (!XMLLoader::findAirportData(ident(), "threshold", path)) {
return; // no XML threshold data
mTowerPosition = SGGeod::fromDegM(lon, lat, fieldElevationM + elevM);
}
-bool FGAirport::validateILSData()
+void FGAirport::validateILSData()
{
if (mILSDataLoaded) {
- return false;
+ return;
}
+ // to avoid re-entrancy on this code-path, ensure we set loaded
+ // immediately.
mILSDataLoaded = true;
- NavDataCache* cache = NavDataCache::instance();
- if (cache->isReadOnly()) {
- return false;
- }
SGPath path;
if (!XMLLoader::findAirportData(ident(), "ils", path)) {
- return false; // no XML tower data
+ return; // no XML tower data
}
- if (!cache->isCachedFileModified(path)) {
- // cached values are correct, we're all done
- return false;
+ try {
+ SGPropertyNode_ptr rootNode = new SGPropertyNode;
+ readProperties(path.str(), rootNode);
+ readILSData(rootNode);
+ } catch (sg_exception& e){
+ SG_LOG(SG_NAVAID, SG_WARN, ident() << "loading ils XML failed:" << e.getFormattedMessage());
}
-
- try {
- SGPropertyNode_ptr rootNode = new SGPropertyNode;
- readProperties(path.str(), rootNode);
-
- flightgear::NavDataCache::Transaction txn(cache);
- readILSData(rootNode);
- cache->stampCacheFile(path);
- txn.commit();
-// we loaded data, tell the caller it might need to reload things
- return true;
- } catch (sg_exception& e){
- SG_LOG(SG_NAVAID, SG_WARN, ident() << "loading ils XML failed:" << e.getFormattedMessage());
- }
-
- return false;
}
void FGAirport::readILSData(SGPropertyNode* aRoot)
-{
+{
NavDataCache* cache = NavDataCache::instance();
-
// find the entry matching the runway
SGPropertyNode* runwayNode, *ilsNode;
for (int i=0; (runwayNode = aRoot->getChild("runway", i)) != NULL; ++i) {
ilsNode->getStringValue("nav-id"));
if (ils == 0) {
SG_LOG(SG_GENERAL, SG_INFO, "reading ILS data for " << ident() <<
- ", couldn;t find runway/navaid for:" <<
+ ", couldn't find runway/navaid for:" <<
ilsNode->getStringValue("rwy") << "/" <<
ilsNode->getStringValue("nav-id"));
continue;
lat = ilsNode->getDoubleValue("lat"),
elevM = ilsNode->getDoubleValue("elev-m");
- cache->updateILS(ils, SGGeod::fromDegM(lon, lat, elevM), hdgDeg);
+ FGNavRecordRef nav(FGPositioned::loadById<FGNavRecord>(ils));
+ assert(nav.valid());
+ nav->updateFromXML(SGGeod::fromDegM(lon, lat, elevM), hdgDeg);
} // of ILS iteration
} // of runway iteration
}
/**
* reload the ILS data from XML if required.
- * @result true if the data was refreshed, false if no data was loaded
- * or previously cached data is still correct.
*/
- bool validateILSData();
+ void validateILSData();
SGGeod getTowerLocation() const;
mutable bool mHelipadsLoaded;
mutable bool mTaxiwaysLoaded;
mutable bool mProceduresLoaded;
+
+ mutable bool mThresholdDataLoaded;
bool mILSDataLoaded;
mutable std::vector<FGRunwayRef> mRunways;
insertAirport = prepare("INSERT INTO airport (rowid, has_metar) VALUES (?, ?)");
insertNavaid = prepare("INSERT INTO navaid (rowid, freq, range_nm, multiuse, runway, colocated)"
" VALUES (?1, ?2, ?3, ?4, ?5, ?6)");
- updateILS = prepare("UPDATE navaid SET multiuse=?2 WHERE rowid=?1");
insertCommStation = prepare("INSERT INTO comm (rowid, freq_khz, range_nm)"
" VALUES (?, ?, ?)");
}
- FGPositioned* loadById(sqlite_int64 rowId);
+ FGPositioned* loadById(sqlite_int64 rowId, sqlite3_int64& aptId);
FGAirport* loadAirport(sqlite_int64 rowId,
FGPositioned::Type ty,
sqlite3_stmt_ptr insertPositionedQuery, insertAirport, insertTower, insertRunway,
insertCommStation, insertNavaid;
sqlite3_stmt_ptr setAirportMetar, setRunwayReciprocal, setRunwayILS, setNavaidColocated,
- setAirportPos, updateILS;
+ setAirportPos;
sqlite3_stmt_ptr removePOIQuery;
sqlite3_stmt_ptr findClosestWithIdent;
//////////////////////////////////////////////////////////////////////
-FGPositioned* NavDataCache::NavDataCachePrivate::loadById(sqlite3_int64 rowid)
+FGPositioned* NavDataCache::NavDataCachePrivate::loadById(sqlite3_int64 rowid,
+ sqlite3_int64& aptId)
{
sqlite3_bind_int64(loadPositioned, 1, rowid);
PositionedID prowid = static_cast<PositionedID>(rowid);
string ident = (char*) sqlite3_column_text(loadPositioned, 2);
string name = (char*) sqlite3_column_text(loadPositioned, 3);
- sqlite3_int64 aptId = sqlite3_column_int64(loadPositioned, 4);
+ aptId = sqlite3_column_int64(loadPositioned, 4);
double lon = sqlite3_column_double(loadPositioned, 5);
double lat = sqlite3_column_double(loadPositioned, 6);
double elev = sqlite3_column_double(loadPositioned, 7);
case FGPositioned::DME:
case FGPositioned::TACAN:
case FGPositioned::MOBILE_TACAN:
- {
- if (aptId > 0) {
- FGAirport* apt = FGPositioned::loadById<FGAirport>(aptId);
- if (apt->validateILSData()) {
- // queried data above is probably invalid, force us to go around again
- // (the next time through, validateILSData will return false)
- return outer->loadById(rowid);
- }
- }
-
return loadNav(rowid, ty, ident, name, pos);
- }
case FGPositioned::FIX:
return new FGFix(rowid, ident, pos);
return it->second; // cache it
}
- FGPositioned* pos = d->loadById(rowid);
+ PositionedID aptId;
+ FGPositioned* pos = d->loadById(rowid, aptId);
d->cache.insert(it, PositionedCache::value_type(rowid, pos));
- d->cacheMisses++;
+ d->cacheMisses++;
+
+ // when we loaded an ILS, we must apply per-airport changes
+ if ((pos->type() == FGPositioned::ILS) && (aptId > 0)) {
+ FGAirport* apt = FGPositioned::loadById<FGAirport>(aptId);
+ apt->validateILSData();
+ }
+
return pos;
}
rec->setColocatedDME(colocatedDME);
}
}
-
-void NavDataCache::updateILS(PositionedID ils, const SGGeod& newPos, double aHdg)
-{
- sqlite3_bind_int64(d->updateILS, 1, ils);
- sqlite3_bind_double(d->updateILS, 2, aHdg);
- d->execUpdate(d->updateILS);
- updatePosition(ils, newPos);
-}
PositionedID NavDataCache::insertCommStation(FGPositioned::Type ty,
const string& name, const SGGeod& pos, int freq, int range,
PositionedID insertNavaid(FGPositioned::Type ty, const std::string& ident,
const std::string& name, const SGGeod& pos, int freq, int range, double multiuse,
PositionedID apt, PositionedID runway);
- void updateILS(PositionedID ils, const SGGeod& newPos, double aHdg);
-
// Assign colocated DME to a navaid
void setNavaidColocated(PositionedID navaid, PositionedID colocatedDME);
bool loadTacan(const SGPath& path, FGTACANList *channellist);
-/**
- * Return the property node corresponding to the runway ILS installation,
- * from the Airports/I/C/A/ICAO.ils.xml file (loading it if necessary)
- * returns NULL is no ILS data is defined for the runway.
- */
-SGPropertyNode* ilsDataForRunwayAndNavaid(FGRunway* aRunway, const std::string& aNavIdent);
-
} // of namespace flightgear
#endif // _FG_NAVDB_HXX