namespace {
-const int SCHEMA_VERSION = 5;
+const int SCHEMA_VERSION = 6;
// bind a std::string to a sqlite statement. The std::string must live the
// entire duration of the statement execution - do not pass a temporary
}
readPropertyQuery = prepare("SELECT value FROM properties WHERE key=?");
- writePropertyQuery = prepare("INSERT OR REPLACE INTO properties "
- "(key, value) VALUES (?,?)");
+ writePropertyQuery = prepare("INSERT INTO properties (key, value) VALUES (?,?)");
+ clearProperty = prepare("DELETE FROM properties WHERE key=?1");
if (didCreate) {
writeIntProperty("schema-version", SCHEMA_VERSION);
return stepSelect(stmt);
}
+ static const int MAX_RETRIES = 10;
+
bool stepSelect(sqlite3_stmt_ptr stmt)
{
- int result = sqlite3_step(stmt);
- if (result == SQLITE_ROW) {
- return true; // at least one result row
- }
+ int retries = 0;
+ int result;
+ while (retries < MAX_RETRIES) {
+ result = sqlite3_step(stmt);
+ if (result == SQLITE_ROW) {
+ return true; // at least one result row
+ }
+
+ if (result == SQLITE_DONE) {
+ return false; // no result rows
+ }
+
+ if (result != SQLITE_LOCKED) {
+ break;
+ }
+
+ ++retries;
+ } // of retry loop for DB locked
- if (result == SQLITE_DONE) {
- return false; // no result rows
+ if (retries >= MAX_RETRIES) {
+ SG_LOG(SG_NAVCACHE, SG_ALERT, "exceeded maximum number of SQLITE_LOCKED retries");
+ return false;
}
string errMsg;
void prepareQueries()
{
- clearProperty = prepare("DELETE FROM properties WHERE key=?1");
writePropertyMulti = prepare("INSERT INTO properties (key, value) VALUES(?1,?2)");
#define POSITIONED_COLS "rowid, type, ident, name, airport, lon, lat, elev_m, octree_node"
void writeIntProperty(const string& key, int value)
{
+ reset(clearProperty);
+ sqlite_bind_stdstring(clearProperty, 1, key);
+ execUpdate(clearProperty);
+
sqlite_bind_stdstring(writePropertyQuery, 1, key);
sqlite3_bind_int(writePropertyQuery, 2, value);
execSelect(writePropertyQuery);
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;
+ }
+
SG_LOG(SG_NAVCACHE, SG_INFO, "NavCache: no main cache rebuild required");
return false;
}
d->flushDeferredOctreeUpdates();
+ string sceneryPaths = simgear::strutils::join(globals->get_fg_scenery(), ";");
+ writeStringProperty("scenery_paths", sceneryPaths);
+
d->runSQL("COMMIT");
} catch (sg_exception& e) {
SG_LOG(SG_NAVCACHE, SG_ALERT, "caught exception rebuilding navCache:" << e.what());
void NavDataCache::writeStringProperty(const string& key, const string& value)
{
+ d->reset(d->clearProperty);
+ sqlite_bind_stdstring(d->clearProperty, 1, key);
+ d->execUpdate(d->clearProperty);
+
d->reset(d->writePropertyQuery);
sqlite_bind_stdstring(d->writePropertyQuery, 1, key);
sqlite_bind_stdstring(d->writePropertyQuery, 2, value);
void NavDataCache::writeDoubleProperty(const string& key, const double& value)
{
+ d->reset(d->clearProperty);
+ sqlite_bind_stdstring(d->clearProperty, 1, key);
+ d->execUpdate(d->clearProperty);
+
d->reset(d->writePropertyQuery);
sqlite_bind_stdstring(d->writePropertyQuery, 1, key);
sqlite3_bind_double(d->writePropertyQuery, 2, value);