// 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 *proto.RangeTreeNode) error { key := node.Key if node.LeftKey != nil && node.RightKey != nil { left, err := tc.getNode(node.LeftKey) if err != nil { return err } predecessor, err := tc.getMaxNode(left) if err != nil { return err } node, _, err = tc.swapNodes(node, predecessor) if err != nil { return err } } // Node will always have at most one child. var child *proto.RangeTreeNode var err error if node.LeftKey != nil { if child, err = tc.getNode(node.LeftKey); err != nil { return err } } else if node.RightKey != nil { if child, err = tc.getNode(node.RightKey); err != nil { return err } } if !isRed(node) { // Paint the node to the color of the child node. node.Black = !isRed(child) tc.setNode(node) if err := tc.deleteCase1(node); err != nil { return err } } if _, err := tc.replaceNode(node, child); err != nil { return err } // Always set the root back to black if node, err = tc.getNode(node.Key); err != nil { return err } if child != nil && node.ParentKey == nil { if child, err = tc.getNode(child.Key); err != nil { return err } 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 *proto.RangeTreeNode) (*proto.RangeTreeNode, error) { if oldNode.ParentKey == nil { if newNode == nil { return nil, util.Error("cannot replace the root node with nil") } // Update the root key if this was the root. tc.setRootKey(newNode.Key) } else { oldParent, err := tc.getNode(oldNode.ParentKey) if err != nil { return nil, err } 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 }
// rotateRight performs a right rotation around the node. func (tc *treeContext) rotateRight(node *proto.RangeTreeNode) (*proto.RangeTreeNode, error) { left, err := tc.getNode(node.LeftKey) if err != nil { return nil, err } if left.Black { return nil, util.Error("rotating a black node") } node.LeftKey = left.RightKey left.RightKey = &node.Key left.Black = node.Black node.Black = false tc.setNode(node) tc.setNode(left) return left, nil }
// rotateLeft performs a left rotation around the node. func (tc *treeContext) rotateLeft(node *proto.RangeTreeNode) (*proto.RangeTreeNode, error) { right, err := tc.getNode(node.RightKey) if err != nil { return nil, err } if right.Black { return nil, util.Error("rotating a black node") } node.RightKey = right.LeftKey right.LeftKey = &node.Key right.Black = node.Black node.Black = false tc.setNode(node) tc.setNode(right) return right, nil }
// insertCase1 handles the case when the inserted node is the root node. func (tc *treeContext) insertCase1(node *proto.RangeTreeNode) error { if node.ParentKey == nil { node.Black = true tc.setNode(node) return nil } return tc.insertCase2(node) }
// insert performs the insertion of a new range into the RangeTree. It will // recursively call insert until it finds the correct location. It will not // overwrite an already existing key, but that case should not occur. func (tc *treeContext) insert(node *proto.RangeTreeNode, key proto.Key) (*proto.RangeTreeNode, error) { if node == nil { // Insert the new node here. node = &proto.RangeTreeNode{ Key: key, } tc.setNode(node) } else if key.Less(node.Key) { // Walk down the tree to the left. left, err := tc.getNode(node.LeftKey) if err != nil { return nil, err } left, err = tc.insert(left, key) if err != nil { return nil, err } if node.LeftKey == nil || !(*node.LeftKey).Equal(left.Key) { node.LeftKey = &left.Key tc.setNode(node) } } else { // Walk down the tree to the right. right, err := tc.getNode(node.RightKey) if err != nil { return nil, err } right, err = tc.insert(right, key) if err != nil { return nil, err } if node.RightKey == nil || !(*node.RightKey).Equal(right.Key) { node.RightKey = &right.Key tc.setNode(node) } } return tc.walkUpRot23(node) }
// rotateRight performs a right rotation around the node. func (tc *treeContext) rotateRight(node *proto.RangeTreeNode) (*proto.RangeTreeNode, error) { left, err := tc.getNode(node.LeftKey) if err != nil { return nil, err } left, err = tc.replaceNode(node, left) if err != nil { return nil, err } node.LeftKey = left.RightKey if left.RightKey != nil { leftRight, err := tc.getNode(left.RightKey) if err != nil { return nil, err } 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 *proto.RangeTreeNode) (*proto.RangeTreeNode, error) { right, err := tc.getNode(node.RightKey) if err != nil { return nil, err } right, err = tc.replaceNode(node, right) if err != nil { return nil, err } node.RightKey = right.LeftKey if right.LeftKey != nil { rightLeft, err := tc.getNode(right.LeftKey) if err != nil { return nil, err } rightLeft.ParentKey = node.Key tc.setNode(rightLeft) } right.LeftKey = node.Key node.ParentKey = right.Key tc.setNode(right) tc.setNode(node) return right, nil }
// flip swaps the color of the node and both of its children. Both those // children must exist. func (tc *treeContext) flip(node *proto.RangeTreeNode) (*proto.RangeTreeNode, error) { left, err := tc.getNode(node.LeftKey) if err != nil { return nil, err } right, err := tc.getNode(node.RightKey) if err != nil { return nil, err } node.Black = !node.Black left.Black = !left.Black right.Black = !right.Black tc.setNode(node) tc.setNode(left) tc.setNode(right) return node, 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 *proto.RangeTreeNode) 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, err := tc.getNode(currentKey) if err != nil { return err } if node.Key.Equal(currentNode.Key) { return util.Errorf("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) }