#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>
#include "poidb.hxx"
#include <Airports/parking.hxx>
#include <Airports/gnnode.hxx>
+#include "CacheSchema.h"
using std::string;
namespace {
const int MAX_RETRIES = 10;
-const int SCHEMA_VERSION = 8;
+
const int CACHE_SIZE_KBYTES= 32 * 1024;
// bind a std::string to a sqlite statement. The std::string must live the
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;
execSelect(stmt);
reset(stmt);
}
-
+
void initTables()
{
- runSQL("CREATE TABLE properties ("
- "key VARCHAR,"
- "value VARCHAR"
- ")");
-
- runSQL("CREATE TABLE stat_cache ("
- "path VARCHAR unique,"
- "stamp INT"
- ")");
-
- runSQL("CREATE TABLE positioned ("
- "type INT,"
- "ident VARCHAR collate nocase,"
- "name VARCHAR collate nocase,"
- "airport INT64,"
- "lon FLOAT,"
- "lat FLOAT,"
- "elev_m FLOAT,"
- "octree_node INT,"
- "cart_x FLOAT,"
- "cart_y FLOAT,"
- "cart_z FLOAT"
- ")");
-
- runSQL("CREATE INDEX pos_octree ON positioned(octree_node)");
- runSQL("CREATE INDEX pos_ident ON positioned(ident collate nocase)");
- runSQL("CREATE INDEX pos_name ON positioned(name collate nocase)");
- // allow efficient querying of 'all ATIS at this airport' or
- // 'all towers at this airport'
- runSQL("CREATE INDEX pos_apt_type ON positioned(airport, type)");
-
- runSQL("CREATE TABLE airport ("
- "has_metar BOOL"
- ")"
- );
-
- runSQL("CREATE TABLE comm ("
- "freq_khz INT,"
- "range_nm INT"
- ")"
- );
-
- runSQL("CREATE INDEX comm_freq ON comm(freq_khz)");
-
- runSQL("CREATE TABLE runway ("
- "heading FLOAT,"
- "length_ft FLOAT,"
- "width_m FLOAT,"
- "surface INT,"
- "displaced_threshold FLOAT,"
- "stopway FLOAT,"
- "reciprocal INT64,"
- "ils INT64"
- ")"
- );
-
- runSQL("CREATE TABLE navaid ("
- "freq INT,"
- "range_nm INT,"
- "multiuse FLOAT,"
- "runway INT64,"
- "colocated INT64"
- ")"
- );
-
- runSQL("CREATE INDEX navaid_freq ON navaid(freq)");
-
- runSQL("CREATE TABLE octree (children INT)");
-
- runSQL("CREATE TABLE airway ("
- "ident VARCHAR collate nocase,"
- "network INT" // high-level or low-level
- ")");
-
- runSQL("CREATE INDEX airway_ident ON airway(ident)");
-
- runSQL("CREATE TABLE airway_edge ("
- "network INT,"
- "airway INT64,"
- "a INT64,"
- "b INT64"
- ")");
-
- runSQL("CREATE INDEX airway_edge_from ON airway_edge(a)");
-
- runSQL("CREATE TABLE taxi_node ("
- "hold_type INT,"
- "on_runway BOOL,"
- "pushback BOOL"
- ")");
-
- runSQL("CREATE TABLE parking ("
- "heading FLOAT,"
- "radius INT,"
- "gate_type VARCHAR,"
- "airlines VARCHAR,"
- "pushback INT64"
- ")");
-
- runSQL("CREATE TABLE groundnet_edge ("
- "airport INT64,"
- "a INT64,"
- "b INT64"
- ")");
-
- runSQL("CREATE INDEX groundnet_edge_airport ON groundnet_edge(airport)");
- runSQL("CREATE INDEX groundnet_edge_from ON groundnet_edge(a)");
+ string_list commands = simgear::strutils::split(SCHEMA_SQL, ";");
+ BOOST_FOREACH(std::string sql, commands) {
+ if (sql.empty()) {
+ continue;
+ }
+
+ runSQL(sql);
+ } // of commands in scheme loop
}
void prepareQueries()
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
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->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");
d->execUpdate(q);
}
+bool NavDataCache::isReadOnly() const
+{
+ return d->readOnly;
+}
+
/////////////////////////////////////////////////////////////////////////////////////////
// Transaction RAII object