#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>
outer(o),
db(NULL),
path(p),
+ readOnly(false),
cacheHits(0),
cacheMisses(0),
transactionLevel(0),
{
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'");
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;
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, "
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="
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;
}
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
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;
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;
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);
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:
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
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
}
}
-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,
*/
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
// 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;
}
result[numMatches] = NULL; // end of list marker
- d->reset(d->searchAirports);
+ d->reset(stmt);
return result;
}
d->execUpdate(q);
}
+bool NavDataCache::isReadOnly() const
+{
+ return d->readOnly;
+}
+
/////////////////////////////////////////////////////////////////////////////////////////
// Transaction RAII object