X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FNavaids%2FNavDataCache.cxx;h=f6756613bd6c19130d5c308b44c36282add9852f;hb=5c659b3970e9a4542519e0d528016c08f7ecb6c1;hp=4431fa67df3d7dbe860a6977ddd1fb0aef7e89a9;hpb=6adb8b22dfdbc1ffffab94c19079307623134644;p=flightgear.git diff --git a/src/Navaids/NavDataCache.cxx b/src/Navaids/NavDataCache.cxx index 4431fa67d..f6756613b 100644 --- a/src/Navaids/NavDataCache.cxx +++ b/src/Navaids/NavDataCache.cxx @@ -300,6 +300,8 @@ public: SG_LOG(SG_NAVCACHE, SG_INFO, "NavDataCache integrity check took:" << st.elapsedMSec()); finalize(stmt); } + + bool isCachedFileModified(const SGPath& path, bool verbose); void callSqlite(int result, const string& sql) { @@ -474,7 +476,6 @@ public: setRunwayReciprocal = prepare("UPDATE runway SET reciprocal=?2 WHERE rowid=?1"); setRunwayILS = prepare("UPDATE runway SET ils=?2 WHERE rowid=?1"); setNavaidColocated = prepare("UPDATE navaid SET colocated=?2 WHERE rowid=?1"); - updateRunwayThreshold = prepare("UPDATE runway SET heading=?2, displaced_threshold=?3, stopway=?4 WHERE rowid=?1"); insertPositionedQuery = prepare("INSERT INTO positioned " "(type, ident, name, airport, lon, lat, elev_m, octree_node, " @@ -486,7 +487,6 @@ public: 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 (?, ?, ?)"); @@ -536,6 +536,11 @@ public: sqlite3_bind_int(searchAirports, 2, FGPositioned::AIRPORT); sqlite3_bind_int(searchAirports, 3, FGPositioned::SEAPORT); + getAllAirports = prepare("SELECT ident, name FROM positioned WHERE type>=?1 AND type <=?2"); + sqlite3_bind_int(getAllAirports, 1, FGPositioned::AIRPORT); + sqlite3_bind_int(getAllAirports, 2, FGPositioned::SEAPORT); + + getAirportItemByIdent = prepare("SELECT rowid FROM positioned WHERE airport=?1 AND ident=?2 AND type=?3"); findAirportRunway = prepare("SELECT airport, rowid FROM positioned WHERE ident=?2 AND type=?3 AND airport=" @@ -620,7 +625,7 @@ public: } - FGPositioned* loadById(sqlite_int64 rowId); + FGPositioned* loadById(sqlite_int64 rowId, sqlite3_int64& aptId); FGAirport* loadAirport(sqlite_int64 rowId, FGPositioned::Type ty, @@ -711,10 +716,15 @@ public: PositionedID colocated = sqlite3_column_int64(loadNavaid, 4); reset(loadNavaid); - FGNavRecord* n = new FGNavRecord(rowId, ty, id, name, pos, freq, rangeNm, mulituse, runway); - if (colocated) { - n->setColocatedDME(colocated); - } + FGNavRecord* n = + (ty == FGPositioned::MOBILE_TACAN) + ? new FGMobileNavRecord + (rowId, ty, id, name, pos, freq, rangeNm, mulituse, runway) + : new FGNavRecord + (rowId, ty, id, name, pos, freq, rangeNm, mulituse, runway); + + if (colocated) + n->setColocatedDME(colocated); return n; } @@ -889,7 +899,7 @@ public: sqlite3_stmt_ptr insertPositionedQuery, insertAirport, insertTower, insertRunway, insertCommStation, insertNavaid; sqlite3_stmt_ptr setAirportMetar, setRunwayReciprocal, setRunwayILS, setNavaidColocated, - setAirportPos, updateRunwayThreshold, updateILS; + setAirportPos; sqlite3_stmt_ptr removePOIQuery; sqlite3_stmt_ptr findClosestWithIdent; @@ -897,7 +907,7 @@ public: sqlite3_stmt_ptr getOctreeChildren, insertOctree, updateOctreeChildren, getOctreeLeafChildren; - sqlite3_stmt_ptr searchAirports; + sqlite3_stmt_ptr searchAirports, getAllAirports; sqlite3_stmt_ptr findCommByFreq, findNavsByFreq, findNavsByFreqNoPos, findNavaidForRunway; sqlite3_stmt_ptr getAirportItems, getAirportItemByIdent; @@ -931,9 +941,10 @@ public: std::auto_ptr rebuilder; }; - ////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////// -FGPositioned* NavDataCache::NavDataCachePrivate::loadById(sqlite3_int64 rowid) +FGPositioned* NavDataCache::NavDataCachePrivate::loadById(sqlite3_int64 rowid, + sqlite3_int64& aptId) { sqlite3_bind_int64(loadPositioned, 1, rowid); @@ -945,7 +956,7 @@ FGPositioned* NavDataCache::NavDataCachePrivate::loadById(sqlite3_int64 rowid) PositionedID prowid = static_cast(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); @@ -978,18 +989,7 @@ FGPositioned* NavDataCache::NavDataCachePrivate::loadById(sqlite3_int64 rowid) case FGPositioned::DME: case FGPositioned::TACAN: case FGPositioned::MOBILE_TACAN: - { - if (aptId > 0) { - FGAirport* apt = FGPositioned::loadById(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); @@ -1024,7 +1024,37 @@ FGPositioned* NavDataCache::NavDataCachePrivate::loadById(sqlite3_int64 rowid) return NULL; } } - + +bool NavDataCache::NavDataCachePrivate::isCachedFileModified(const SGPath& path, bool verbose) +{ + if (!path.exists()) { + throw sg_io_exception("isCachedFileModified: Missing file:" + path.str()); + } + + sqlite_bind_temp_stdstring(statCacheCheck, 1, path.str()); + bool isModified = true; + sgDebugPriority logLevel = verbose ? SG_WARN : SG_DEBUG; + if (execSelect(statCacheCheck)) { + time_t modtime = sqlite3_column_int64(statCacheCheck, 0); + time_t delta = std::labs(modtime - path.modTime()); + if (delta != 0) + { + SG_LOG(SG_NAVCACHE, logLevel, "NavCache: rebuild required for " << path << + ". Timestamps: " << modtime << " != " << path.modTime()); + } + else + { + SG_LOG(SG_NAVCACHE, SG_DEBUG, "NavCache: no rebuild required for " << path); + } + + isModified = (delta != 0); + } else { + SG_LOG(SG_NAVCACHE, logLevel, "NavCache: initial build required for " << path); + } + + reset(statCacheCheck); + return isModified; +} static NavDataCache* static_instance = NULL; @@ -1116,30 +1146,40 @@ bool NavDataCache::isRebuildRequired() return true; } - if (isCachedFileModified(d->aptDatPath) || - isCachedFileModified(d->metarDatPath) || - isCachedFileModified(d->navDatPath) || - isCachedFileModified(d->fixDatPath) || + if (d->isCachedFileModified(d->aptDatPath, true) || + d->isCachedFileModified(d->metarDatPath, true) || + d->isCachedFileModified(d->navDatPath, true) || + d->isCachedFileModified(d->fixDatPath, true) || + d->isCachedFileModified(d->carrierDatPath, true) || // since POI loading is disabled on Windows, don't check for it // this caused: https://code.google.com/p/flightgear-bugs/issues/detail?id=1227 #ifndef SG_WINDOWS - isCachedFileModified(d->poiDatPath) || + d->isCachedFileModified(d->poiDatPath, true) || #endif - isCachedFileModified(d->airwayDatPath)) + d->isCachedFileModified(d->airwayDatPath, true)) { SG_LOG(SG_NAVCACHE, SG_INFO, "NavCache: main cache rebuild required"); return true; } - string sceneryPaths = simgear::strutils::join(globals->get_fg_scenery(), ";"); - if (readStringProperty("scenery_paths") != sceneryPaths) { - SG_LOG(SG_NAVCACHE, SG_INFO, "NavCache: scenery paths changed, main cache rebuild required"); - return true; - } - + dropGroundnetsIfRequired(); + SG_LOG(SG_NAVCACHE, SG_INFO, "NavCache: no main cache rebuild required"); return false; } + +bool NavDataCache::dropGroundnetsIfRequired() +{ + string sceneryPaths = simgear::strutils::join(globals->get_fg_scenery(), ";"); + if (readStringProperty("scenery_paths") != sceneryPaths) { + SG_LOG(SG_NAVCACHE, SG_INFO, "NavCache: scenery paths changed, dropping ground nets"); + dropAllGroundnets(); + writeStringProperty("scenery_paths", sceneryPaths); + return true; + } + + return false; +} bool NavDataCache::rebuild() { @@ -1330,32 +1370,7 @@ void NavDataCache::writeStringListProperty(const string& key, const string_list& bool NavDataCache::isCachedFileModified(const SGPath& path) const { - if (!path.exists()) { - throw sg_io_exception("isCachedFileModified: Missing file:" + path.str()); - } - - sqlite_bind_temp_stdstring(d->statCacheCheck, 1, path.str()); - bool isModified = true; - - if (d->execSelect(d->statCacheCheck)) { - time_t modtime = sqlite3_column_int64(d->statCacheCheck, 0); - time_t delta = std::labs(modtime - path.modTime()); - if (delta != 0) - { - SG_LOG(SG_NAVCACHE, SG_DEBUG, "NavCache: rebuild required for " << path << ". Timestamps: " << modtime << " != " << path.modTime()); - } - else - { - SG_LOG(SG_NAVCACHE, SG_DEBUG, "NavCache: no rebuild required for " << path); - } - - isModified = (delta != 0); - } else { - SG_LOG(SG_NAVCACHE, SG_DEBUG, "NavCache: initial build required for " << path); - } - - d->reset(d->statCacheCheck); - return isModified; + return d->isCachedFileModified(path, false); } void NavDataCache::stampCacheFile(const SGPath& path) @@ -1446,9 +1461,17 @@ FGPositionedRef NavDataCache::loadById(PositionedID rowid) return it->second; // cache it } - FGPositioned* pos = d->loadById(rowid); + sqlite3_int64 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(aptId); + apt->validateILSData(); + } + return pos; } @@ -1555,21 +1578,6 @@ void NavDataCache::setRunwayILS(PositionedID runway, PositionedID ils) } } -void NavDataCache::updateRunwayThreshold(PositionedID runwayID, const SGGeod &aThreshold, - double aHeading, double aDisplacedThreshold, - double aStopway) -{ -// update the runway information - sqlite3_bind_int64(d->updateRunwayThreshold, 1, runwayID); - sqlite3_bind_double(d->updateRunwayThreshold, 2, aHeading); - sqlite3_bind_double(d->updateRunwayThreshold, 3, aDisplacedThreshold); - sqlite3_bind_double(d->updateRunwayThreshold, 4, aStopway); - d->execUpdate(d->updateRunwayThreshold); - - // now update the positional data - updatePosition(runwayID, aThreshold); -} - PositionedID NavDataCache::insertNavaid(FGPositioned::Type ty, const string& ident, const string& name, const SGGeod& pos, @@ -1605,14 +1613,6 @@ void NavDataCache::setNavaidColocated(PositionedID navaid, PositionedID colocate 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, @@ -1756,13 +1756,19 @@ NavDataCache::getOctreeLeafChildren(int64_t octreeNodeId) */ char** NavDataCache::searchAirportNamesAndIdents(const std::string& aFilter) { - string s = "%" + aFilter + "%"; - sqlite_bind_stdstring(d->searchAirports, 1, s); - + sqlite3_stmt_ptr stmt; unsigned int numMatches = 0, numAllocated = 16; - char** result = (char**) malloc(sizeof(char*) * numAllocated); + string searchTerm("%" + aFilter + "%"); + if (aFilter.empty()) { + stmt = d->getAllAirports; + numAllocated = 4096; // start much larger for all airports + } else { + stmt = d->searchAirports; + sqlite_bind_stdstring(stmt, 1, searchTerm); + } - while (d->stepSelect(d->searchAirports)) { + char** result = (char**) malloc(sizeof(char*) * numAllocated); + while (d->stepSelect(stmt)) { if ((numMatches + 1) >= numAllocated) { numAllocated <<= 1; // double in size! // reallocate results array @@ -1780,18 +1786,18 @@ char** NavDataCache::searchAirportNamesAndIdents(const std::string& aFilter) // which gives a grand total of 7 + name-length + icao-length. // note the ident can be three letters (non-ICAO local strip), four // (default ICAO) or more (extended format ICAO) - int nameLength = sqlite3_column_bytes(d->searchAirports, 1); - int icaoLength = sqlite3_column_bytes(d->searchAirports, 0); + int nameLength = sqlite3_column_bytes(stmt, 1); + int icaoLength = sqlite3_column_bytes(stmt, 0); char* entry = (char*) malloc(7 + nameLength + icaoLength); char* dst = entry; *dst++ = ' '; - memcpy(dst, sqlite3_column_text(d->searchAirports, 1), nameLength); + memcpy(dst, sqlite3_column_text(stmt, 1), nameLength); dst += nameLength; *dst++ = ' '; *dst++ = ' '; *dst++ = ' '; *dst++ = '('; - memcpy(dst, sqlite3_column_text(d->searchAirports, 0), icaoLength); + memcpy(dst, sqlite3_column_text(stmt, 0), icaoLength); dst += icaoLength; *dst++ = ')'; *dst++ = 0; @@ -1800,7 +1806,7 @@ char** NavDataCache::searchAirportNamesAndIdents(const std::string& aFilter) } result[numMatches] = NULL; // end of list marker - d->reset(d->searchAirports); + d->reset(stmt); return result; } @@ -1918,7 +1924,7 @@ NavDataCache::findAirportRunway(const std::string& aName) AirportRunwayPair result; sqlite_bind_stdstring(d->findAirportRunway, 1, parts[0]); - sqlite_bind_stdstring(d->findAirportRunway, 2, parts[1]); + sqlite_bind_stdstring(d->findAirportRunway, 2, cleanRunwayNo(parts[1])); if (d->execSelect(d->findAirportRunway)) { result = AirportRunwayPair(sqlite3_column_int64(d->findAirportRunway, 0), @@ -1933,8 +1939,10 @@ NavDataCache::findAirportRunway(const std::string& aName) } PositionedID -NavDataCache::findILS(PositionedID airport, const string& runway, const string& navIdent) +NavDataCache::findILS(PositionedID airport, const string& aRunway, const string& navIdent) { + string runway(cleanRunwayNo(aRunway)); + sqlite_bind_stdstring(d->findILS, 1, navIdent); sqlite3_bind_int64(d->findILS, 2, airport); sqlite_bind_stdstring(d->findILS, 3, runway); @@ -2161,6 +2169,21 @@ void NavDataCache::dropGroundnetFor(PositionedID aAirport) sqlite3_bind_int64(q, 1, aAirport); d->execUpdate(q); } + +void NavDataCache::dropAllGroundnets() +{ + SG_LOG(SG_NAVCACHE, SG_INFO, "dropping ground-net data"); + beginTransaction(); + d->runSQL("DELETE FROM groundnet_edge"); + d->runSQL("DELETE FROM parking"); + d->runSQL("DELETE FROM taxi_node"); + + sqlite3_stmt_ptr q = d->prepare("DELETE FROM positioned WHERE (type=?1 OR type=?2)"); + sqlite3_bind_int(q, 1, FGPositioned::TAXI_NODE); + sqlite3_bind_int(q, 2, FGPositioned::PARKING); + d->execUpdate(q); + commitTransaction(); +} bool NavDataCache::isReadOnly() const {