GiSTentry* GiSTcursor::Next() { GiSTpage page; while (first || !stack.IsEmpty()) { if (first) { page = GiSTRootPage; first = 0; } else { assert(lastlevel >= 0); GiSTentry *entry = stack.RemoveFront(); if (entry->IsLeaf()) return entry; // Pop off the stack for (int i=0; i < entry->Level() - lastlevel; i++) path.MakeParent(); page = entry->Ptr(); delete entry; } // Entry was a pointer to another node path.MakeChild(page); GiSTnode *node = gist.ReadNode(path); lastlevel = node->Level(); GiSTlist<GiSTentry*> list = node->Search(*query); while (!list.IsEmpty()) { GiSTentry *entry = list.RemoveRear(); stack.Prepend(entry); } delete node; } // The search is over... return NULL; }
// handle underfull leaf nodes int GiST::CondenseTree (GiSTnode *leaf) { GiSTlist<GiSTentry*> Q; int deleted = 0; // Must be condensing a leaf assert (leaf->IsLeaf()); while (!leaf->Path().IsRoot()) { GiSTpath parent_path = leaf->Path(); parent_path.MakeParent (); GiSTnode *P = ReadNode (parent_path); GiSTentry *En = P->SearchPtr(leaf->Path().Page()); assert (En != NULL); // Handle under-full node if (leaf->IsUnderFull(*store)) { if (!IsOrdered()) { TruePredicate truePredicate; GiSTlist<GiSTentry*> list = leaf->Search(truePredicate); while (!list.IsEmpty()) { GiSTentry *e = list.RemoveFront(); Q.Append (e); } P->DeleteEntry(En->Position()); WriteNode (P); deleted = 1; AdjustKeys (P, NULL); } else { // Try to borrow entries, else coalesce with a neighbor GiSTpage neighbor_page = P->SearchNeighbors(leaf->Path().Page()); // right and then left if (neighbor_page != 0) { GiSTpath neighbor_path = leaf->Path(); neighbor_path.MakeSibling (neighbor_page); GiSTnode *neighbor; if (leaf->Sibling() == neighbor_page) { // RIGHT sibling... neighbor = ReadNode (neighbor_path); } else { // LEFT sibling neighbor = leaf; leaf = ReadNode (neighbor_path); } leaf->Coalesce(*neighbor); // If not overfull, coalesce, kill right node if (!leaf->IsOverFull(*store)) { leaf->SetSibling(neighbor->Sibling()); WriteNode (leaf); // Delete the neighbor from parent GiSTentry *e = P->SearchPtr(neighbor->Path().Page()); P->DeleteEntry(e->Position()); WriteNode (P); delete e; store->Deallocate(neighbor->Path().Page()); deleted = 1; } else { // If overfull, split (same as borrowing) GiSTnode *node2 = leaf->PickSplit(); node2->Path() = neighbor->Path(); node2->SetSibling(neighbor->Sibling()); WriteNode (leaf); WriteNode (node2); AdjustKeys (node2, &P); delete node2; deleted = 1; } delete neighbor; } } } // Adjust covering predicate if (!deleted) { AdjustKeys (leaf, &P); } parent_path = leaf->Path(); parent_path.MakeParent (); delete leaf; // Propagate deletes if (!deleted) { break; } leaf = P; } // Re-insert orphaned entries while (!Q.IsEmpty()) { GiSTentry *e = Q.RemoveFront (); InsertHelper (*e, e->Level()); delete e; } return (deleted); }