#include <simgear/bucket/newbucket.hxx>
#include <simgear/misc/sg_path.hxx>
#include <simgear/misc/strutils.hxx>
+#include <simgear/threads/SGThread.hxx>
+#include <simgear/threads/SGGuard.hxx>
#include <Main/globals.hxx>
#include "markerbeacon.hxx"
namespace flightgear
{
+/**
+ * Thread encapsulating a cache rebuild. This is not used to parallelise
+ * the rebuild - we must still wait until completion before doing other
+ * startup, since many things rely on a complete cache. The thread is used
+ * so we don't block the main event loop for an unacceptable duration,
+ * which causes 'not responding' / spinning beachballs on Windows & Mac
+ */
+class RebuildThread : public SGThread
+{
+public:
+ RebuildThread(NavDataCache* cache) :
+ _cache(cache),
+ _isFinished(false)
+ {
+
+ }
+
+ bool isFinished() const
+ {
+ SGGuard<SGMutex> g(_lock);
+ return _isFinished;
+ }
+
+ virtual void run()
+ {
+ SGTimeStamp st;
+ st.stamp();
+ _cache->doRebuild();
+ SG_LOG(SG_GENERAL, SG_INFO, "cache rebuild took:" << st.elapsedMSec() << "msec");
+
+ SGGuard<SGMutex> g(_lock);
+ _isFinished = true;
+ }
+private:
+ NavDataCache* _cache;
+ mutable SGMutex _lock;
+ bool _isFinished;
+};
+
+////////////////////////////////////////////////////////////////////////////
+
typedef std::map<PositionedID, FGPositionedRef> PositionedCache;
class AirportTower : public FGPositioned
try {
execSelect(stmt);
- } catch (sg_exception& e) {
+ } catch (sg_exception&) {
sqlite3_finalize(stmt);
throw; // re-throw
}
findNavsByFreqNoPos = prepare("SELECT positioned.rowid FROM positioned, navaid WHERE "
"positioned.rowid=navaid.rowid AND freq=?1 " AND_TYPED);
+ findNavaidForRunway = prepare("SELECT positioned.rowid FROM positioned, navaid WHERE "
+ "positioned.rowid=navaid.rowid AND runway=?1 AND type=?2");
+
// for an octree branch, return the child octree nodes which exist,
// described as a bit-mask
getOctreeChildren = prepare("SELECT children FROM octree WHERE rowid=?1");
reset(loadAirportStmt);
sqlite3_bind_int64(loadAirportStmt, 1, rowId);
execSelect1(loadAirportStmt);
- bool hasMetar = sqlite3_column_int(loadAirportStmt, 0);
+ bool hasMetar = (sqlite3_column_int(loadAirportStmt, 0) > 0);
return new FGAirport(rowId, id, pos, name, hasMetar, ty);
}
int range = sqlite3_column_int(loadCommStation, 0);
int freqKhz = sqlite3_column_int(loadCommStation, 1);
- CommStation* c = new CommStation(rowId, id, ty, pos, freqKhz, range);
+ CommStation* c = new CommStation(rowId, name, ty, pos, freqKhz, range);
c->setAirport(airport);
return c;
}
sqlite3_stmt_ptr searchAirports;
sqlite3_stmt_ptr findCommByFreq, findNavsByFreq,
- findNavsByFreqNoPos;
+ findNavsByFreqNoPos, findNavaidForRunway;
sqlite3_stmt_ptr getAirportItems, getAirportItemByIdent;
sqlite3_stmt_ptr findAirportRunway,
findILS;
StmtVec prepared;
std::set<Octree::Branch*> deferredOctreeUpdates;
+
+ // if we're performing a rebuild, the thread that is doing the work.
+ // otherwise, NULL
+ std::auto_ptr<RebuildThread> rebuilder;
};
//////////////////////////////////////////////////////////////////////
// reached this point with no exception, success
break;
} catch (sg_exception& e) {
- SG_LOG(SG_NAVCACHE, SG_WARN, "NavCache: init failed:" << e.what()
+ SG_LOG(SG_NAVCACHE, t == 0 ? SG_WARN : SG_ALERT, "NavCache: init failed:" << e.what()
<< " (attempt " << t << ")");
- homePath.remove();
d.reset();
+ homePath.remove();
}
} // of retry loop
return false;
}
-void NavDataCache::rebuild()
+bool NavDataCache::rebuild()
+{
+ if (!d->rebuilder.get()) {
+ d->rebuilder.reset(new RebuildThread(this));
+ d->rebuilder->start();
+ }
+
+// poll the rebuild thread
+ bool fin = d->rebuilder->isFinished();
+ if (fin) {
+ d->rebuilder.reset(); // all done!
+ }
+ return fin;
+}
+
+void NavDataCache::doRebuild()
{
try {
d->runSQL("BEGIN");
sqlite3_bind_double(d->findCommByFreq, 5, cartPos.y());
sqlite3_bind_double(d->findCommByFreq, 6, cartPos.z());
- if (!d->execSelect(d->findCommByFreq)) {
- return NULL;
+ while (d->execSelect(d->findCommByFreq)) {
+ FGPositioned* p = loadById(sqlite3_column_int64(d->findCommByFreq, 0));
+ if (aFilter && !aFilter->pass(p)) {
+ continue;
+ }
+
+ return p;
}
- return loadById(sqlite3_column_int64(d->findCommByFreq, 0));
+ return NULL;
}
PositionedIDVec
}
return result;
}
+
+PositionedID NavDataCache::findNavaidForRunway(PositionedID runway, FGPositioned::Type ty)
+{
+ d->reset(d->findNavaidForRunway);
+ sqlite3_bind_int64(d->findNavaidForRunway, 1, runway);
+ sqlite3_bind_int(d->findNavaidForRunway, 2, ty);
+ if (!d->execSelect(d->findNavaidForRunway)) {
+ return 0;
+ }
+
+ return sqlite3_column_int64(d->findNavaidForRunway, 0);
+}
} // of namespace flightgear