void GiST::InsertHelper(const GiSTentry &entry, int level, // level of tree at which to insert int *splitvec) // a vector to trigger Split instead of forced reinsert { GiSTnode *leaf; int overflow=0; leaf=ChooseSubtree(GiSTRootPage, entry, level); leaf->Insert(entry); if (leaf->IsOverFull(*store)) { if(ForcedReinsert()&&!leaf->Path().IsRoot()&&(!splitvec||!splitvec[level])) { int split[GIST_MAX_LEVELS]; // R*-tree-style forced reinsert for(int i=0; i<GIST_MAX_LEVELS; i++) split[i]=0; OverflowTreatment(leaf, entry, split); overflow=1; } else Split(&leaf, entry); if(leaf->IsOverFull(*store)) { // we only should get here if we reinserted, and the node re-filled assert(overflow); leaf->DeleteEntry(entry.Position()); Split(&leaf, entry); } } else WriteNode(leaf); if(!overflow) AdjustKeys(leaf, NULL); delete leaf; }
void GiST::AdjustKeys (GiSTnode *node, GiSTnode **parent) { if (node->Path().IsRoot()) { return; } GiSTnode *P; // Read in node's parent if (parent == NULL) { GiSTpath parent_path = node->Path(); parent_path.MakeParent (); P = ReadNode (parent_path); parent = &P; } else { P = *parent; } // Get the old entry pointing to node GiSTentry *entry = P->SearchPtr(node->Path().Page()); assert (entry != NULL); // Get union of node GiSTentry *actual = node->Union(); WriteNode(node); // added by myself for the splitted = false; actual->SetPtr(node->Path().Page()); if (!entry->IsEqual(*actual)) { int pos = entry->Position(); P->DeleteEntry(pos); P->InsertBefore(*actual, pos); // A split may be necessary. // XXX: should we do Forced Reinsert here too? if (P->IsOverFull(*store)) { Split (parent, *actual); GiSTpage page = node->Path().Page(); node->Path() = P->Path(); node->Path().MakeChild(page); } else { WriteNode (P); AdjustKeys (P, NULL); } } if (parent == &P) { delete P; } delete actual; delete entry; }
void GiST::OverflowTreatment (GiSTnode *node, const GiSTentry& entry, int *splitvec) { // remove the "top" p entries from the node GiSTlist<GiSTentry*> deleted = RemoveTop (node); WriteNode (node); AdjustKeys (node, NULL); // note that we've seen this level already splitvec[node->Level()] = 1; // for each of the deleted entries, call InsertHelper at this level while (!deleted.IsEmpty()) { GiSTentry *tmpentry = deleted.RemoveFront (); InsertHelper (*tmpentry, node->Level(), splitvec); delete tmpentry; } }
// handle underfull leaf nodes int GiST::CondenseTree(GiSTnode *node) { GiSTlist<GiSTentry*> Q; int deleted=0; // Must be condensing a leaf assert(node->IsLeaf()); while(!node->Path().IsRoot()) { GiSTpath parent_path=node->Path(); parent_path.MakeParent(); GiSTnode *P=ReadNode(parent_path); GiSTentry *En=P->SearchPtr(node->Path().Page()); assert(En!=NULL); // Handle under-full node if(node->IsUnderFull(*store)) { if(!IsOrdered()) { TruePredicate truePredicate; GiSTlist<GiSTentry*> list=node->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 // Have to look at left sibling??? GiSTpage neighbor_page=P->SearchNeighbors(node->Path().Page()); GiSTpath neighbor_path=node->Path(); neighbor_path.MakeSibling(neighbor_page); if(neighbor_page!=0) { GiSTnode *neighbor; // If neighbor is RIGHT sibling... if(node->Sibling()==neighbor_page) neighbor=ReadNode(neighbor_path); else { neighbor=node; node=ReadNode(neighbor_path); } GiSTentry *e=P->SearchPtr(node->Path().Page()); node->Coalesce(*neighbor, *e); delete e; // If not overfull, coalesce, kill right node if(!node->IsOverFull(*store)) { node->SetSibling(neighbor->Sibling()); WriteNode(node); // 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; } // If overfull, split (same as borrowing) else { GiSTnode *node2=node->PickSplit(); node2->Path()=neighbor->Path(); node2->SetSibling(neighbor->Sibling()); WriteNode(node); WriteNode(node2); AdjustKeys(node2, &P); delete node2; deleted=1; } delete neighbor; } } } // Adjust covering predicate if(!deleted) AdjustKeys(node, &P); parent_path=node->Path(); parent_path.MakeParent(); delete node; // Propagate deletes if(!deleted) break; node=P; } // Re-insert orphaned entries while(!Q.IsEmpty()) { GiSTentry *e=Q.RemoveFront(); InsertHelper(*e, e->Level()); delete e; } return(deleted); }