From 32174034e869a1314ec010464859766467197da1 Mon Sep 17 00:00:00 2001 From: Craig Taverner Date: Sat, 14 Oct 2017 18:48:30 +0200 Subject: [PATCH] Do not use traversal API to delete nodes This can cause the traversal to fail on an already deleted node --- .../neo4j/gis/spatial/rtree/RTreeIndex.java | 25 ++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/neo4j/gis/spatial/rtree/RTreeIndex.java b/src/main/java/org/neo4j/gis/spatial/rtree/RTreeIndex.java index 7cd53d411..417c7a7ea 100644 --- a/src/main/java/org/neo4j/gis/spatial/rtree/RTreeIndex.java +++ b/src/main/java/org/neo4j/gis/spatial/rtree/RTreeIndex.java @@ -186,11 +186,8 @@ public void add(List geomNodes) { nodesToAdd.add(n); } nodesToAdd.addAll(geomNodes); - for (Node n : getAllIndexInternalNodes()) { - if (!n.equals(getIndexRoot())) { - deleteNode(n); - } - } + detachGeometryNodes( false, getIndexRoot(), new NullListener() ); + deleteTreeBelow( getIndexRoot() ); buildRtreeFromScratch(getIndexRoot(), decodeGeometryNodeEnvelopes(nodesToAdd), 0.7); countSaved = false; totalGeometryCount = nodesToAdd.size(); @@ -601,10 +598,7 @@ private Node deleteEmptyTreeNodes(Node indexNode, RelationshipType relType) { } } - @Override - public void removeAll(final boolean deleteGeomNodes, final Listener monitor) { - Node indexRoot = getIndexRoot(); - + private void detachGeometryNodes(final boolean deleteGeomNodes, Node indexRoot, final Listener monitor) { monitor.begin(count()); try { // delete all geometry nodes @@ -625,6 +619,13 @@ public void onIndexReference(Node geomNode) { } finally { monitor.done(); } + } + + @Override + public void removeAll(final boolean deleteGeomNodes, final Listener monitor) { + Node indexRoot = getIndexRoot(); + + detachGeometryNodes( deleteGeomNodes, indexRoot, monitor ); try (Transaction tx = database.beginTx()) { // delete index root relationship @@ -1346,6 +1347,12 @@ private double getArea(Envelope e) { // TODO why not e.getArea(); ? } + private void deleteTreeBelow( Node rootNode ) { + for ( Relationship relationship : rootNode.getRelationships( RTreeRelationshipTypes.RTREE_CHILD, Direction.OUTGOING )) { + deleteRecursivelySubtree( relationship.getEndNode(), relationship ); + } + } + private void deleteRecursivelySubtree(Node node, Relationship incoming) { for (Relationship relationship : node.getRelationships(RTreeRelationshipTypes.RTREE_CHILD, Direction.OUTGOING)) { deleteRecursivelySubtree(relationship.getEndNode(),relationship);