From bf646a30668588d25c97d449239d2f338e92c5c8 Mon Sep 17 00:00:00 2001 From: Masajiro Iwasaki Date: Wed, 11 Dec 2024 14:37:18 +0900 Subject: [PATCH] fix a bug in saving the tree index after removal. --- VERSION | 2 +- lib/NGT/Command.cpp | 4 ++-- lib/NGT/Graph.cpp | 39 +++++++++++++++++++++++++++++++++++---- lib/NGT/Node.h | 9 ++++++--- lib/NGT/Tree.cpp | 1 + lib/NGT/Tree.h | 5 ++++- 6 files changed, 49 insertions(+), 11 deletions(-) diff --git a/VERSION b/VERSION index 3f684d2..cc6c9a4 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.3.4 +2.3.5 diff --git a/lib/NGT/Command.cpp b/lib/NGT/Command.cpp index 4e4ff1e..83345e9 100644 --- a/lib/NGT/Command.cpp +++ b/lib/NGT/Command.cpp @@ -1188,8 +1188,8 @@ void NGT::Command::repair(Args &args) { } } else { if (removedIDs.find(id) == removedIDs.end() && id < objSize) { - std::cerr << "Not found an object in the tree. However, it might be a duplicated object. " << id - << std::endl; + std::cerr << "Not found an object in the tree. However, it might be a duplicated same object. " << id + << "/" << removedIDs.size() << std::endl; uninsertedTreeObjectCount++; if (repair) { try { diff --git a/lib/NGT/Graph.cpp b/lib/NGT/Graph.cpp index 9fc4924..4de4181 100644 --- a/lib/NGT/Graph.cpp +++ b/lib/NGT/Graph.cpp @@ -1001,8 +1001,23 @@ void NeighborhoodGraph::removeEdgesReliably(ObjectID id) { #else GraphNode::iterator ei = std::lower_bound(n.begin(), n.end(), obj); if ((ei == n.end()) || ((*ei).id != obj.id)) { - n.insert(ei, obj); - insertionA = true; + auto idx = distance(n.begin(), ei); + bool found = false; + for (int i = idx - 1; idx >= 0 && found == false; i--) { + if (n[idx - 1].distance != n[i].distance) break; + if (n[i].id == obj.id) found = true; + } + for (int i = idx + 1; idx < (static_cast(n.size()) - 1) && found == false; i++) { + if (n[idx + 1].distance != n[i].distance) break; + if (n[i].id == obj.id) found = true; + } + if (found) { + std::cerr << "Warning! The distances calculated earlier are different now, " + << "therefore the index might be inconsistent." << std::endl; + } else { + n.insert(ei, obj); + insertionA = true; + } } #endif } @@ -1024,8 +1039,24 @@ void NeighborhoodGraph::removeEdgesReliably(ObjectID id) { #else GraphNode::iterator ei = std::lower_bound(n.begin(), n.end(), obj); if ((ei == n.end()) || ((*ei).id != obj.id)) { - n.insert(ei, obj); - insertionB = true; + auto idx = distance(n.begin(), ei); + bool found = false; + for (int i = idx - 1; idx >= 0 && found == false; i--) { + if (n[idx - 1].distance != n[i].distance) break; + if (n[i].id == obj.id) found = true; + } + for (int i = idx + 1; idx < (static_cast(n.size()) - 1) && found == false; i++) { + if (n[idx + 1].distance != n[i].distance) break; + if (n[i].id == obj.id) found = true; + } + if (found) { + std::cerr << "Warning! The distances calculated earlier are different now, " + << "therefore the index might be inconsistent." << std::endl; + } else { + n.insert(ei, obj); + insertionB = true; + } + } #endif } diff --git a/lib/NGT/Node.h b/lib/NGT/Node.h index 54bfd76..b25bcea 100644 --- a/lib/NGT/Node.h +++ b/lib/NGT/Node.h @@ -456,10 +456,13 @@ class LeafNode : public Node { } #endif // NGT_NODE_USE_VECTOR if (pivot == 0) { - // Before insertion, parent ID == 0 and object size == 0, that indicates an empty index - if (parent.getID() != 0 || objectSize != 0) { - NGTThrowException("Node::write: pivot is null!"); + if (parent.getID() != 0) { + NGTThrowException("Node::write: The pivot is null and the parent is invalid."); + } + if (objectSize != 0) { + NGTThrowException("Node::write: The pivot is null with no object assigned."); } + // Before insertion, parent ID == 0 and object size == 0, that indicates an empty index } else { #ifdef NGT_SHARED_MEMORY_ALLOCATOR std::cerr << "not implemented" << std::endl; diff --git a/lib/NGT/Tree.cpp b/lib/NGT/Tree.cpp index 6ae1d1e..b844c39 100644 --- a/lib/NGT/Tree.cpp +++ b/lib/NGT/Tree.cpp @@ -369,6 +369,7 @@ void DVPTree::removeEmptyNodes(InternalNode &inode) { LeafNode *ln = new LeafNode; #endif ln->parent = target->parent; + ln->pivot = PersistentObject::allocate(*objectSpace); insertNode(ln); InternalNode &in = *(InternalNode *)getNode(ln->parent); diff --git a/lib/NGT/Tree.h b/lib/NGT/Tree.h index f32867a..bef4a23 100644 --- a/lib/NGT/Tree.h +++ b/lib/NGT/Tree.h @@ -446,7 +446,10 @@ class DVPTree { auto objs = ln.getObjectIDs(); #endif for (size_t idx = 0; idx < ln.objectSize; ++idx) { - ids.insert(objs[idx].id); + auto ret = ids.insert(objs[idx].id); + if (ret.second == false) { + std::cerr << "Warning! Duplicated ID in the tree. ID=" << objs[idx].id << std::endl; + } } } }