NavData poly-lines: split out from main Octree
Use a transient index for the poly-lines. This avoids NavCache disk contention when multiple copies of FG race after the rebuild completes. Should reduce locking errors early in startup.
This commit is contained in:
parent
ef07f26023
commit
7935d5d97c
6 changed files with 91 additions and 73 deletions
|
@ -218,21 +218,9 @@ private:
|
|||
if (m_abandoned)
|
||||
return;
|
||||
|
||||
flightgear::PolyLineList::const_iterator begin = m_parsedLines.begin() + m_lineInsertCount;
|
||||
|
||||
// add lines in batches of 100; this is a tradeoff to ensure we don't lock
|
||||
// the database for too long. (Which triggers SQLITE_BUSY)
|
||||
const int lineInsertBatchSize = 100U;
|
||||
unsigned int numToAdd = std::min<unsigned int>(100U, static_cast<unsigned int>(m_parsedLines.size()) - m_lineInsertCount);
|
||||
flightgear::PolyLineList::const_iterator end = begin + numToAdd;
|
||||
flightgear::PolyLine::bulkAddToSpatialIndex(begin, end);
|
||||
|
||||
if (end == m_parsedLines.end()) {
|
||||
flightgear::PolyLine::bulkAddToSpatialIndex(m_parsedLines.begin(), m_parsedLines.end());
|
||||
deleteLater(); // commit suicide
|
||||
} else {
|
||||
m_lineInsertCount += lineInsertBatchSize;
|
||||
QTimer::singleShot(50, this, SLOT(onFinished()));
|
||||
}
|
||||
}
|
||||
|
||||
void loadNaturalEarthFile(const std::string& aFileName,
|
||||
|
@ -245,7 +233,6 @@ private:
|
|||
if (!path.exists())
|
||||
return; // silently fail for now
|
||||
|
||||
flightgear::PolyLineList lines;
|
||||
flightgear::SHPParser::parsePolyLines(path, aType, m_parsedLines, areClosed);
|
||||
}
|
||||
|
||||
|
|
|
@ -796,7 +796,7 @@ public:
|
|||
sqlite3_bind_double(insertPositionedQuery, 7, pos.getElevationM());
|
||||
|
||||
if (spatialIndex) {
|
||||
Octree::Leaf* octreeLeaf = Octree::global_spatialOctree->findLeafForPos(cartPos);
|
||||
Octree::Leaf* octreeLeaf = Octree::globalPersistentOctree()->findLeafForPos(cartPos);
|
||||
assert(intersects(octreeLeaf->bbox(), cartPos));
|
||||
sqlite3_bind_int64(insertPositionedQuery, 8, octreeLeaf->guid());
|
||||
} else {
|
||||
|
@ -1292,11 +1292,6 @@ NavDataCache::NavDataCache()
|
|||
}
|
||||
} // of retry loop
|
||||
|
||||
double RADIUS_EARTH_M = 7000 * 1000.0; // 7000km is plenty
|
||||
SGVec3d earthExtent(RADIUS_EARTH_M, RADIUS_EARTH_M, RADIUS_EARTH_M);
|
||||
Octree::global_spatialOctree =
|
||||
new Octree::Branch(SGBox<double>(-earthExtent, earthExtent), 1);
|
||||
|
||||
// Update d->aptDatFilesInfo, d->metarDatPath, d->navDatPath, etc.
|
||||
updateListsOfDatFiles();
|
||||
}
|
||||
|
@ -1995,7 +1990,7 @@ void NavDataCache::updatePosition(PositionedID item, const SGGeod &pos)
|
|||
// structures alone. This is fine providing items do no move very far, since
|
||||
// all the spatial searches ultimately use the items' real cartesian position,
|
||||
// which was updated above.
|
||||
Octree::Leaf* octreeLeaf = Octree::global_spatialOctree->findLeafForPos(cartPos);
|
||||
Octree::Leaf* octreeLeaf = Octree::globalPersistentOctree()->findLeafForPos(cartPos);
|
||||
sqlite3_bind_int64(d->setAirportPos, 5, octreeLeaf->guid());
|
||||
|
||||
sqlite3_bind_double(d->setAirportPos, 6, cartPos.x());
|
||||
|
|
|
@ -103,17 +103,15 @@ PolyLineRef PolyLine::create(PolyLine::Type aTy, const SGGeodVec &aRawPoints)
|
|||
void PolyLine::bulkAddToSpatialIndex(PolyLineList::const_iterator begin,
|
||||
PolyLineList::const_iterator end)
|
||||
{
|
||||
NavDataCache::Transaction txn( NavDataCache::instance());
|
||||
flightgear::PolyLineList::const_iterator it;
|
||||
for (it=begin; it != end; ++it) {
|
||||
(*it)->addToSpatialIndex();
|
||||
}
|
||||
txn.commit();
|
||||
}
|
||||
|
||||
void PolyLine::addToSpatialIndex() const
|
||||
{
|
||||
Octree::Node* node = Octree::global_spatialOctree->findNodeForBox(cartesianBox());
|
||||
Octree::Node* node = Octree::globalTransientOctree()->findNodeForBox(cartesianBox());
|
||||
node->addPolyLine(const_cast<PolyLine*>(this));
|
||||
}
|
||||
|
||||
|
@ -155,7 +153,7 @@ PolyLineList PolyLine::linesNearPos(const SGGeod& aPos, double aRangeNm, const T
|
|||
SGVec3d cart = SGVec3d::fromGeod(aPos);
|
||||
double cutoffM = aRangeNm * SG_NM_TO_METER;
|
||||
Octree::FindLinesDeque deque;
|
||||
deque.push_back(Octree::global_spatialOctree);
|
||||
deque.push_back(Octree::globalTransientOctree());
|
||||
|
||||
while (!deque.empty()) {
|
||||
Octree::Node* nd = deque.front();
|
||||
|
|
|
@ -38,7 +38,6 @@ typedef std::vector<SGGeod> SGGeodVec;
|
|||
class PolyLine;
|
||||
|
||||
typedef SGSharedPtr<PolyLine> PolyLineRef;
|
||||
|
||||
typedef std::vector<PolyLineRef> PolyLineList;
|
||||
|
||||
/**
|
||||
|
|
|
@ -21,9 +21,7 @@
|
|||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "PositionedOctree.hxx"
|
||||
#include "positioned.hxx"
|
||||
|
@ -37,14 +35,48 @@
|
|||
#include <simgear/structure/exception.hxx>
|
||||
#include <simgear/timing/timestamp.hxx>
|
||||
|
||||
#include "PolyLine.hxx"
|
||||
|
||||
namespace flightgear
|
||||
{
|
||||
|
||||
namespace Octree
|
||||
{
|
||||
|
||||
Node* global_spatialOctree = NULL;
|
||||
std::unique_ptr<Node> global_spatialOctree;
|
||||
std::unique_ptr<Node> global_transientOctree;
|
||||
|
||||
double RADIUS_EARTH_M = 7000 * 1000.0; // 7000km is plenty
|
||||
|
||||
Node* globalTransientOctree()
|
||||
{
|
||||
if (!global_transientOctree) {
|
||||
SGVec3d earthExtent(RADIUS_EARTH_M, RADIUS_EARTH_M, RADIUS_EARTH_M);
|
||||
global_transientOctree.reset(new Octree::Branch(SGBox<double>(-earthExtent, earthExtent), 1, false));
|
||||
}
|
||||
|
||||
return global_transientOctree.get();
|
||||
}
|
||||
|
||||
Node* globalPersistentOctree()
|
||||
{
|
||||
if (!global_spatialOctree) {
|
||||
SGVec3d earthExtent(RADIUS_EARTH_M, RADIUS_EARTH_M, RADIUS_EARTH_M);
|
||||
global_spatialOctree.reset(new Octree::Branch(SGBox<double>(-earthExtent, earthExtent), 1, true));
|
||||
}
|
||||
|
||||
return global_spatialOctree.get();
|
||||
}
|
||||
|
||||
Node::Node(const SGBoxd& aBox, int64_t aIdent, bool persistent) : _ident(aIdent),
|
||||
_persistent(persistent),
|
||||
_box(aBox)
|
||||
{
|
||||
}
|
||||
|
||||
Node::~Node()
|
||||
{
|
||||
}
|
||||
|
||||
void Node::addPolyLine(const PolyLineRef& aLine)
|
||||
{
|
||||
|
@ -66,8 +98,7 @@ Node *Node::findNodeForBox(const SGBoxd&) const
|
|||
return const_cast<Node*>(this);
|
||||
}
|
||||
|
||||
Leaf::Leaf(const SGBoxd& aBox, int64_t aIdent) :
|
||||
Node(aBox, aIdent),
|
||||
Leaf::Leaf(const SGBoxd& aBox, int64_t aIdent, bool persistent) : Node(aBox, aIdent, persistent),
|
||||
childrenLoaded(false)
|
||||
{
|
||||
}
|
||||
|
@ -136,8 +167,7 @@ void Leaf::loadChildren()
|
|||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Branch::Branch(const SGBoxd& aBox, int64_t aIdent) :
|
||||
Node(aBox, aIdent),
|
||||
Branch::Branch(const SGBoxd& aBox, int64_t aIdent, bool persistent) : Node(aBox, aIdent, persistent),
|
||||
childrenLoaded(false)
|
||||
{
|
||||
memset(children, 0, sizeof(Node*) * 8);
|
||||
|
@ -249,15 +279,15 @@ Node* Branch::childAtIndex(int childIndex) const
|
|||
|
||||
if (d2 < LEAF_SIZE_SQR) {
|
||||
// REVIEW: Memory Leak - 480 bytes in 3 blocks are still reachable
|
||||
child = new Leaf(cb, childIdent);
|
||||
child = new Leaf(cb, childIdent, _persistent);
|
||||
} else {
|
||||
// REVIEW: Memory Leak - 9,152 bytes in 52 blocks are still reachable
|
||||
child = new Branch(cb, childIdent);
|
||||
child = new Branch(cb, childIdent, _persistent);
|
||||
}
|
||||
|
||||
children[childIndex] = child;
|
||||
|
||||
if (childrenLoaded) {
|
||||
if (_persistent && childrenLoaded) {
|
||||
// childrenLoad is done, so we're defining a new node - add it to the
|
||||
// cache too.
|
||||
NavDataCache::instance()->defineOctreeNode(const_cast<Branch*>(this), child);
|
||||
|
@ -273,6 +303,10 @@ void Branch::loadChildren() const
|
|||
return;
|
||||
}
|
||||
|
||||
if (!_persistent) {
|
||||
childrenLoaded = true;
|
||||
}
|
||||
|
||||
int childrenMask = NavDataCache::instance()->getOctreeBranchChildren(guid());
|
||||
for (int i=0; i<8; ++i) {
|
||||
if ((1 << i) & childrenMask) {
|
||||
|
@ -302,7 +336,7 @@ bool findNearestN(const SGVec3d& aPos, unsigned int aN, double aCutoffM, FGPosit
|
|||
aResults.clear();
|
||||
FindNearestPQueue pq;
|
||||
FindNearestResults results;
|
||||
pq.push(Ordered<Node*>(global_spatialOctree, 0));
|
||||
pq.push(Ordered<Node*>(globalPersistentOctree(), 0));
|
||||
double cut = aCutoffM;
|
||||
|
||||
SGTimeStamp tm;
|
||||
|
@ -343,7 +377,7 @@ bool findAllWithinRange(const SGVec3d& aPos, double aRangeM, FGPositioned::Filte
|
|||
aResults.clear();
|
||||
FindNearestPQueue pq;
|
||||
FindNearestResults results;
|
||||
pq.push(Ordered<Node*>(global_spatialOctree, 0));
|
||||
pq.push(Ordered<Node*>(globalPersistentOctree(), 0));
|
||||
double rng = aRangeM;
|
||||
|
||||
SGTimeStamp tm;
|
||||
|
|
|
@ -37,11 +37,16 @@
|
|||
|
||||
#include <Navaids/positioned.hxx>
|
||||
#include <Navaids/NavDataCache.hxx>
|
||||
#include <Navaids/PolyLine.hxx>
|
||||
|
||||
namespace flightgear
|
||||
{
|
||||
|
||||
// forward decls
|
||||
class PolyLine;
|
||||
typedef SGSharedPtr<PolyLine> PolyLineRef;
|
||||
typedef std::vector<PolyLineRef> PolyLineList;
|
||||
|
||||
|
||||
namespace Octree
|
||||
{
|
||||
|
||||
|
@ -117,7 +122,9 @@ namespace Octree
|
|||
// we're always grabbing all the lines in an area
|
||||
typedef std::deque<Node*> FindLinesDeque;
|
||||
|
||||
extern Node* global_spatialOctree;
|
||||
Node* globalPersistentOctree();
|
||||
|
||||
Node* globalTransientOctree();
|
||||
|
||||
class Leaf;
|
||||
|
||||
|
@ -156,17 +163,15 @@ namespace Octree
|
|||
|
||||
virtual Node* findNodeForBox(const SGBoxd& box) const;
|
||||
|
||||
virtual ~Node() {}
|
||||
virtual ~Node();
|
||||
|
||||
void addPolyLine(const PolyLineRef&);
|
||||
protected:
|
||||
Node(const SGBoxd &aBox, int64_t aIdent) :
|
||||
_ident(aIdent),
|
||||
_box(aBox)
|
||||
{
|
||||
}
|
||||
Node(const SGBoxd& aBox, int64_t aIdent, bool persistent);
|
||||
|
||||
|
||||
const int64_t _ident;
|
||||
const bool _persistent = false;
|
||||
const SGBoxd _box;
|
||||
|
||||
PolyLineList lines;
|
||||
|
@ -175,7 +180,7 @@ namespace Octree
|
|||
class Leaf : public Node
|
||||
{
|
||||
public:
|
||||
Leaf(const SGBoxd& aBox, int64_t aIdent);
|
||||
Leaf(const SGBoxd& aBox, int64_t aIdent, bool persistent);
|
||||
|
||||
virtual void visit(const SGVec3d& aPos, double aCutoff,
|
||||
FGPositioned::Filter* aFilter,
|
||||
|
@ -200,7 +205,7 @@ namespace Octree
|
|||
class Branch : public Node
|
||||
{
|
||||
public:
|
||||
Branch(const SGBoxd& aBox, int64_t aIdent);
|
||||
Branch(const SGBoxd& aBox, int64_t aIdent, bool persistent);
|
||||
|
||||
virtual void visit(const SGVec3d& aPos, double aCutoff,
|
||||
FGPositioned::Filter*,
|
||||
|
|
Loading…
Add table
Reference in a new issue