1
0
Fork 0

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:
James Turner 2021-06-04 16:58:02 +01:00
parent ef07f26023
commit 7935d5d97c
6 changed files with 91 additions and 73 deletions

View file

@ -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);
}

View file

@ -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());

View file

@ -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();

View file

@ -38,7 +38,6 @@ typedef std::vector<SGGeod> SGGeodVec;
class PolyLine;
typedef SGSharedPtr<PolyLine> PolyLineRef;
typedef std::vector<PolyLineRef> PolyLineList;
/**

View file

@ -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;

View file

@ -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*,