// delete removes a range from the range tree. // Since this tree is not stored in memory but persisted through the ranges, in // place deletion is not possible. Instead, we use the helper function // swapNodes above. func (tc *treeContext) delete(node *roachpb.RangeTreeNode) *roachpb.Error { key := node.Key if node.LeftKey != nil && node.RightKey != nil { left, pErr := tc.getNode(node.LeftKey) if pErr != nil { return pErr } predecessor, pErr := tc.getMaxNode(left) if pErr != nil { return pErr } node, _, pErr = tc.swapNodes(node, predecessor) if pErr != nil { return pErr } } // Node will always have at most one child. var child *roachpb.RangeTreeNode var pErr *roachpb.Error if node.LeftKey != nil { if child, pErr = tc.getNode(node.LeftKey); pErr != nil { return pErr } } else if node.RightKey != nil { if child, pErr = tc.getNode(node.RightKey); pErr != nil { return pErr } } if !isRed(node) { // Paint the node to the color of the child node. node.Black = !isRed(child) tc.setNode(node) if pErr := tc.deleteCase1(node); pErr != nil { return pErr } } if _, pErr := tc.replaceNode(node, child); pErr != nil { return pErr } // Always set the root back to black if node, pErr = tc.getNode(node.Key); pErr != nil { return pErr } if child != nil && node.ParentKey == nil { if child, pErr = tc.getNode(child.Key); pErr != nil { return pErr } child.Black = true tc.setNode(child) } tc.dropNode(key) return nil }
// replaceNode cuts a node away form its parent, substituting a new node or // nil. The updated new node is returned. Note that this does not in fact alter // the old node in any way, but only the old node's parent and the new node. func (tc *treeContext) replaceNode(oldNode, newNode *roachpb.RangeTreeNode) (*roachpb.RangeTreeNode, *roachpb.Error) { if oldNode.ParentKey == nil { if newNode == nil { return nil, roachpb.NewErrorf("cannot replace the root node with nil") } // Update the root key if this was the root. tc.setRootKey(newNode.Key) } else { oldParent, pErr := tc.getNode(oldNode.ParentKey) if pErr != nil { return nil, pErr } if oldParent.LeftKey != nil && oldNode.Key.Equal(oldParent.LeftKey) { if newNode == nil { oldParent.LeftKey = nil } else { oldParent.LeftKey = newNode.Key } } else { if newNode == nil { oldParent.RightKey = nil } else { oldParent.RightKey = newNode.Key } } tc.setNode(oldParent) } if newNode != nil { newNode.ParentKey = oldNode.ParentKey tc.setNode(newNode) } return newNode, nil }
// insertCase1 handles the case when the inserted node is the root node. func (tc *treeContext) insertCase1(node *roachpb.RangeTreeNode) *roachpb.Error { if node.ParentKey == nil { node.Black = true tc.setNode(node) return nil } return tc.insertCase2(node) }
// rotateRight performs a right rotation around the node. func (tc *treeContext) rotateRight(node *roachpb.RangeTreeNode) (*roachpb.RangeTreeNode, *roachpb.Error) { left, pErr := tc.getNode(node.LeftKey) if pErr != nil { return nil, pErr } left, pErr = tc.replaceNode(node, left) if pErr != nil { return nil, pErr } node.LeftKey = left.RightKey if left.RightKey != nil { leftRight, pErr := tc.getNode(left.RightKey) if pErr != nil { return nil, pErr } leftRight.ParentKey = node.Key tc.setNode(leftRight) } left.RightKey = node.Key node.ParentKey = left.Key tc.setNode(left) tc.setNode(node) return left, nil }
// rotateLeft performs a left rotation around the node. func (tc *treeContext) rotateLeft(node *roachpb.RangeTreeNode) (*roachpb.RangeTreeNode, *roachpb.Error) { right, pErr := tc.getNode(node.RightKey) if pErr != nil { return nil, pErr } right, pErr = tc.replaceNode(node, right) if pErr != nil { return nil, pErr } node.RightKey = right.LeftKey if right.LeftKey != nil { rightLeft, pErr := tc.getNode(right.LeftKey) if pErr != nil { return nil, pErr } rightLeft.ParentKey = node.Key tc.setNode(rightLeft) } right.LeftKey = node.Key node.ParentKey = right.Key tc.setNode(right) tc.setNode(node) return right, nil }
// insert performs the insertion of a new node into the tree. It walks the tree // until it finds the correct location. It will fail if the node already exists // as that case should not occur. After inserting the node, it checks all insert // cases to ensure the tree is balanced and adjusts it if needed. func (tc *treeContext) insert(node *roachpb.RangeTreeNode) *roachpb.Error { if tc.tree.RootKey == nil { tc.setRootKey(node.Key) } else { // Walk the tree to find the right place to insert the new node. currentKey := tc.tree.RootKey for { currentNode, pErr := tc.getNode(currentKey) if pErr != nil { return pErr } if node.Key.Equal(currentNode.Key) { return roachpb.NewErrorf("key %s already exists in the range tree", node.Key) } if node.Key.Less(currentNode.Key) { if currentNode.LeftKey == nil { currentNode.LeftKey = node.Key tc.setNode(currentNode) break } else { currentKey = currentNode.LeftKey } } else { if currentNode.RightKey == nil { currentNode.RightKey = node.Key tc.setNode(currentNode) break } else { currentKey = currentNode.RightKey } } } node.ParentKey = currentKey tc.setNode(node) } return tc.insertCase1(node) }