Пример #1
0
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;
}
Пример #2
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);
}