Beispiel #1
0
// adjust the keys of node, which is used during the final phase of the BulkLoad algorithm
void
MT::AdjKeys (GiSTnode *node)
{
	if (node->Path().IsRoot()) {
		return;
	}

	GiSTpath parentPath = node->Path();
	parentPath.MakeParent ();
	GiSTnode *parentNode = ReadNode (parentPath);
	GiSTentry *parentEntry = parentNode->SearchPtr(node->Path().Page());  // parent entry
	assert (parentEntry != NULL);
	GiSTentry *unionEntry = node->Union();
	unionEntry->SetPtr(node->Path().Page());
	((MTkey *) unionEntry->Key())->distance = ((MTkey *) parentEntry->Key())->distance;  // necessary to keep track of the distance from the parent
	if (!parentEntry->IsEqual(*unionEntry)) {  // replace this entry
		parentNode->DeleteEntry(parentEntry->Position());
		parentNode->Insert(*unionEntry);
		WriteNode (parentNode);
		AdjKeys (parentNode);
	}
	delete unionEntry;
	delete parentEntry;
	delete parentNode;
}
Beispiel #2
0
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;
}
Beispiel #3
0
void 
GiST::Delete (const GiSTpredicate& pred)
{
	GiSTcursor *c = Search (pred);
	GiSTentry *e;

	do {
		if (c == NULL) {
			return;
		}
		e = c->Next();
		GiSTpath path = c->Path();
		delete c;
		if (e == NULL) {
			return;
		}
		// Read in the node that this belongs to
		GiSTnode *node = ReadNode (path);
		node->DeleteEntry(e->Position());
		WriteNode (node);

		int condensed = CondenseTree (node);
		delete node;
		if (condensed) {
			ShortenTree ();
			// because the tree changed, we need to search all over again!
			// XXX - this is inefficient!  users may want to avoid condensing.
			c = Search (pred);
		}
	} while (e != NULL);
}
Beispiel #4
0
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;
}
Beispiel #5
0
void MXTree::Split(GiSTnode **node, const GiSTentry& entry)
{
	double radii[2], dist, *dists = new double[(*node)->NumEntries()*2];
	int pageNums[2], cands[2];
	vector<vector<int>> vec(2);
	((MXTnode *)(*node))->TestPromotion(radii, &dist, pageNums, cands, dists, vec);
	if (Trade((*node)->Path().IsRoot(), radii, dist, pageNums, ((MXTnode *)(*node))->GetPageNum()+1, (*node)->NumEntries())) {
		// don't split now
		delete[] dists;
		GiSTpath oldPath = (*node)->Path();

		int startPage = ((*node)->Path().IsRoot() ? rootPage : (*node)->Path().Page());
		int pageNum = ((MXTnode *)(*node))->GetPageNum();
		((MXTfile *)store)->Deallocate(startPage, pageNum);
		startPage = ((MXTfile *)store)->Allocate(++pageNum);
		(*node)->Path().MakeSibling(startPage);
		rootPage = ((*node)->Path().IsRoot() ? startPage : rootPage);
		((MXTnode *)(*node))->SetPageNum(pageNum);
		WriteNode(*node);

		if (!(*node)->Path().IsRoot() && startPage != oldPath.Page()) {
			GiSTpath parentPath = oldPath;
			parentPath.MakeParent();
			GiSTnode *parentNode = ReadNode(parentPath);
			GiSTentry *e = parentNode->SearchPtr(oldPath.Page());
			assert(e != NULL);
			int pos = e->Position();
			e->SetPtr(startPage);
			parentNode->DeleteEntry(pos);
			parentNode->InsertBefore(*e, pos);
			WriteNode(parentNode);
			delete parentNode;
			delete e;
		}
	} else {
		// split now
		bool bLeft = false, bNewRoot = false;

		if ((*node)->Path().IsRoot()) {
			bNewRoot = true;
			(*node)->Path().MakeChild(rootPage);
			rootPage = store->Allocate();
		}

		int oldPageNum = ((MXTnode *)(*node))->GetPageNum();
		GiSTnode *node2 = ((MXTnode *)(*node))->PickSplit(cands, dists, vec);
		delete[] dists;
		int curPageNum = ((MXTnode *)(*node))->GetPageNum();
		assert(oldPageNum >= curPageNum);
		if (oldPageNum > curPageNum) {
			((MXTfile *)store)->Deallocate((*node)->Path().Page()+curPageNum, oldPageNum-curPageNum);
		}
		node2->Path().MakeSibling(((MXTfile *)store)->Allocate(((MXTnode *)node2)->GetPageNum()));

		WriteNode(*node);
		WriteNode(node2);
	
		GiSTentry *e = (*node)->SearchPtr(entry.Ptr());
		if (e != NULL) {
			bLeft = true;
			delete e;
		}
	
		GiSTentry *e1 = (*node)->Union();
		GiSTentry *e2 = node2->Union();
	
		e1->SetPtr((*node)->Path().Page());
		e2->SetPtr(node2->Path().Page());
		// Create new root if root is being split
		if (bNewRoot) {
			GiSTnode *root = NewNode(this);
			root->SetLevel((*node)->Level() + 1);
			root->InsertBefore(*e1, 0);
			root->InsertBefore(*e2, 1);
			root->Path().MakeRoot();
			WriteNode(root);
			delete root;
		} else {
			// Insert entry for N' in parent
			GiSTpath parentPath = (*node)->Path();
			parentPath.MakeParent();
			GiSTnode *parent = ReadNode(parentPath);
			// Find the entry for N in parent
			GiSTentry *e = parent->SearchPtr((*node)->Path().Page());
			assert(e != NULL);
			// Insert the new entry right after it
			int pos = e->Position();
			parent->DeleteEntry(pos);
			parent->InsertBefore(*e1, pos);
			parent->InsertBefore(*e2, pos+1);
			delete e;
			if (!parent->IsOverFull(*store)) {
				WriteNode(parent);
			} else {
				Split(&parent, bLeft? *e1: *e2);  // parent is the node which contains the entry inserted
				GiSTpage page = (*node)->Path().Page();
				(*node)->Path() = parent->Path();  // parent's path may change
				(*node)->Path().MakeChild(page);
				page = node2->Path().Page();
				node2->Path() = (*node)->Path();
				node2->Path().MakeSibling(page);
			}
			delete parent;
		}
		if (!bLeft) {
			delete *node;
			*node = node2;  // return it
		} else {
			delete node2;
		}
		delete e1;
		delete e2;
	}
}
Beispiel #6
0
void 
GiST::Split (GiSTnode **node, const GiSTentry& entry)
{
	int went_left = 0, new_root = 0;

	if ((*node)->Path().IsRoot()) {
		new_root = 1;
		(*node)->Path().MakeChild(store->Allocate());
	}

	GiSTnode *node2 = (*node)->PickSplit();
	node2->Path().MakeSibling(store->Allocate());
	
	GiSTentry *e = (*node)->SearchPtr(entry.Ptr());
	if (e != NULL) {
		went_left = 1;
		delete e;
	}
	node2->SetSibling((*node)->Sibling());
	(*node)->SetSibling(node2->Path().Page());
	WriteNode (*node);
	WriteNode (node2);

	GiSTentry *e1 = (*node)->Union();
	GiSTentry *e2 = node2->Union();

	e1->SetPtr((*node)->Path().Page());
	e2->SetPtr(node2->Path().Page());
	// Create new root if root is being split
	if (new_root) {
		GiSTnode *root = NewNode (this);
		root->SetLevel((*node)->Level() + 1);
		root->InsertBefore(*e1, 0);
		root->InsertBefore(*e2, 1);
		root->Path().MakeRoot();
		WriteNode (root);
		delete root;
	} else {
		// Insert entry for N' in parent
		GiSTpath parent_path = (*node)->Path();
		parent_path.MakeParent ();
		GiSTnode *parent = ReadNode (parent_path);
		// Find the entry for N in parent
		GiSTentry *e = parent->SearchPtr((*node)->Path().Page());
		assert (e != NULL);
		// Insert the new entry right after it
		int pos = e->Position();
		parent->DeleteEntry(pos);
		parent->InsertBefore(*e1, pos);
		parent->InsertBefore(*e2, pos+1);
		delete e;
		if (!parent->IsOverFull(*store)) {
			WriteNode (parent);
		} else {
			Split (&parent, went_left? *e1: *e2);
			GiSTpage page = (*node)->Path().Page();
			(*node)->Path() = parent->Path();  // parent's path may changed
			(*node)->Path().MakeChild (page);
			page = node2->Path().Page();
			node2->Path() = (*node)->Path();
			node2->Path().MakeSibling (page);
		}
		delete parent;
	}
	if (!went_left) {
		delete *node;
		*node = node2;  // return it
	} else {
		delete node2;
	}
	delete e1;
	delete e2;
}
Beispiel #7
0
// 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);
}