]> git.mxchange.org Git - flightgear.git/blobdiff - src/Navaids/NavDataCache.cxx
ICAO.threshold.xml works read-only.
[flightgear.git] / src / Navaids / NavDataCache.cxx
index da943aa28a0cf6652492b232c14365e96ad06821..1772de951e85d0475f56f2a076c24cc09b164a5b 100644 (file)
@@ -58,6 +58,8 @@
 #include <simgear/threads/SGGuard.hxx>
 
 #include <Main/globals.hxx>
+#include <Main/fg_props.hxx>
+#include <Main/options.hxx>
 #include "markerbeacon.hxx"
 #include "navrecord.hxx"
 #include <Airports/airport.hxx>
@@ -208,6 +210,7 @@ public:
     outer(o),
     db(NULL),
     path(p),
+    readOnly(false),
     cacheHits(0),
     cacheMisses(0),
     transactionLevel(0),
@@ -224,12 +227,14 @@ public:
   {
     SG_LOG(SG_NAVCACHE, SG_INFO, "NavCache at:" << path);
        
-       // see http://code.google.com/p/flightgear-bugs/issues/detail?id=1055
-       // for the logic here. Sigh.
+      readOnly = fgGetBool("/sim/fghome-readonly", false);
+
+      int openFlags = readOnly ? SQLITE_OPEN_READONLY :
+        SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
+      // see http://code.google.com/p/flightgear-bugs/issues/detail?id=1055
+      // for the UTF8 / path logic here
        std::string pathUtf8 = simgear::strutils::convertWindowsLocal8BitToUtf8(path.str());
-    sqlite3_open_v2(pathUtf8.c_str(), &db,
-                    SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
-    
+    sqlite3_open_v2(pathUtf8.c_str(), &db, openFlags, NULL);
     
     sqlite3_stmt_ptr checkTables =
       prepare("SELECT count(*) FROM sqlite_master WHERE name='properties'");
@@ -239,7 +244,7 @@ public:
     
     execSelect(checkTables);
     bool didCreate = false;
-    if (sqlite3_column_int(checkTables, 0) == 0) {
+    if (!readOnly && (sqlite3_column_int(checkTables, 0) == 0)) {
       SG_LOG(SG_NAVCACHE, SG_INFO, "will create tables");
       initTables();
       didCreate = true;
@@ -469,7 +474,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, "
@@ -531,6 +535,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="
@@ -706,10 +715,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;
   }
@@ -857,7 +871,8 @@ public:
   NavDataCache* outer;
   sqlite3* db;
   SGPath path;
-  
+    bool readOnly;
+    
   /// the actual cache of ID -> instances. This holds an owning reference,
   /// so once items are in the cache they will never be deleted until
   /// the cache drops its reference
@@ -883,7 +898,7 @@ public:
   sqlite3_stmt_ptr insertPositionedQuery, insertAirport, insertTower, insertRunway,
   insertCommStation, insertNavaid;
   sqlite3_stmt_ptr setAirportMetar, setRunwayReciprocal, setRunwayILS, setNavaidColocated,
-    setAirportPos, updateRunwayThreshold, updateILS;
+    setAirportPos, updateILS;
   sqlite3_stmt_ptr removePOIQuery;
   
   sqlite3_stmt_ptr findClosestWithIdent;
@@ -891,7 +906,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;
@@ -936,6 +951,7 @@ FGPositioned* NavDataCache::NavDataCachePrivate::loadById(sqlite3_int64 rowid)
   assert(rowid == sqlite3_column_int64(loadPositioned, 0));
   FGPositioned::Type ty = (FGPositioned::Type) sqlite3_column_int(loadPositioned, 1);
   
+  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);
@@ -953,7 +969,7 @@ FGPositioned* NavDataCache::NavDataCachePrivate::loadById(sqlite3_int64 rowid)
       return loadAirport(rowid, ty, ident, name, pos);
       
     case FGPositioned::TOWER:
-      return new AirportTower(rowid, aptId, ident, pos);
+      return new AirportTower(prowid, aptId, ident, pos);
       
     case FGPositioned::RUNWAY:
     case FGPositioned::HELIPAD:
@@ -1047,7 +1063,11 @@ NavDataCache::NavDataCache()
       SG_LOG(SG_NAVCACHE, t == 0 ? SG_WARN : SG_ALERT, "NavCache: init failed:" << e.what()
              << " (attempt " << t << ")");
       d.reset();
-      homePath.remove();
+        
+        // only wipe the existing if not readonly
+        if (!fgGetBool("/sim/fghome-readonly", false)) {
+            homePath.remove();
+        }
     }
   } // of retry loop
     
@@ -1096,11 +1116,25 @@ NavDataCache* NavDataCache::instance()
   
 bool NavDataCache::isRebuildRequired()
 {
+    if (d->readOnly) {
+        return false;
+    }
+    
+    if (flightgear::Options::sharedInstance()->isOptionSet("restore-defaults")) {
+        SG_LOG(SG_NAVCACHE, SG_INFO, "NavCache: restore-defaults requested, will rebuild cache");
+        return true;
+    }
+    
   if (isCachedFileModified(d->aptDatPath) ||
       isCachedFileModified(d->metarDatPath) ||
       isCachedFileModified(d->navDatPath) ||
+      isCachedFileModified(d->carrierDatPath) ||
       isCachedFileModified(d->fixDatPath) ||
+// 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) ||
+#endif
       isCachedFileModified(d->airwayDatPath))
   {
     SG_LOG(SG_NAVCACHE, SG_INFO, "NavCache: main cache rebuild required");
@@ -1531,21 +1565,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,
@@ -1732,13 +1751,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);
+  if (aFilter.empty()) {
+    stmt = d->getAllAirports;
+    numAllocated = 4096; // start much larger for all airports
+  } else {
+    stmt = d->searchAirports;
+    string s = "%" + aFilter + "%";
+    sqlite_bind_stdstring(stmt, 1, s);
+  }
   
-  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
@@ -1756,18 +1781,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;
@@ -1776,7 +1801,7 @@ char** NavDataCache::searchAirportNamesAndIdents(const std::string& aFilter)
   }
   
   result[numMatches] = NULL; // end of list marker
-  d->reset(d->searchAirports);
+  d->reset(stmt);
   return result;
 }
   
@@ -2138,6 +2163,11 @@ void NavDataCache::dropGroundnetFor(PositionedID aAirport)
   d->execUpdate(q);
 }
 
+bool NavDataCache::isReadOnly() const
+{
+    return d->readOnly;
+}
+
 /////////////////////////////////////////////////////////////////////////////////////////
 // Transaction RAII object