Пример #1
0
        private bool RedistributeBranchElements(TreeBranch branch, int childIndex, TreeBranch child)
        {
            // We distribute the nodes in the child branch with the branch
            // immediately to the right.  If that's not possible, then we distribute
            // with the left.

            // If branch has only a single value, return immediately
            int branchSize = branch.ChildCount;

            if (branchSize == 1)
            {
                return(false);
            }

            int        leftI, rightI;
            TreeBranch left, right;

            if (childIndex < branchSize - 1)
            {
                // Distribute with the right
                leftI  = childIndex;
                rightI = childIndex + 1;
                left   = child;
                right  = (TreeBranch)UnfreezeNode(FetchNode(branch.GetChild(childIndex + 1)));
                branch.SetChild(right.Id, childIndex + 1);
            }
            else
            {
                // Distribute with the left
                leftI  = childIndex - 1;
                rightI = childIndex;
                left   = (TreeBranch)UnfreezeNode(FetchNode(branch.GetChild(childIndex - 1)));
                right  = child;
                branch.SetChild(left.Id, childIndex - 1);
            }

            // Get the mid value key reference
            Key midKey = branch.GetKey(rightI);

            // Perform the merge,
            Key newMidKey = left.Merge(right, midKey);

            // Reset the leaf element count
            branch.SetChildLeafElementCount(left.LeafElementCount, leftI);
            branch.SetChildLeafElementCount(right.LeafElementCount, rightI);

            // If after the merge the right branch is empty, we need to remove it
            if (right.IsEmpty)
            {
                // Delete the node
                DeleteNode(right.Id);
                // And remove it from the branch,
                branch.RemoveChild(rightI);
                return(true);
            }

            // Otherwise set the key reference
            branch.SetKeyToLeft(newMidKey, rightI);
            return(false);
        }
Пример #2
0
        public void DeleteLeaf(Key key)
        {
            // Set up the state
            StackFrame frame          = StackEnd(0);
            NodeId     thisRef        = frame.NodeId;
            TreeBranch branchNode     = null;
            int        deleteNodeSize = -1;
            Key        leftKey        = null;

            // Walk back through the rest of the stack
            int sz = FrameCount;

            for (int i = 1; i < sz; ++i)
            {
                // Find the child_i for the child
                // This is the child_i of the child in the current branch
                int childIndex = frame.ChildIndex;

                // Move the stack frame,
                frame = StackEnd(i);

                NodeId childId = thisRef;
                thisRef = frame.NodeId;
                TreeBranch childBranch = branchNode;
                branchNode = (TreeBranch)UnfreezeNode(FetchNode(thisRef));

                if (deleteNodeSize == -1)
                {
                    deleteNodeSize =
                        (int)branchNode.GetChildLeafElementCount(childIndex);
                }

                // If the child branch is empty,
                if (childBranch == null || childBranch.IsEmpty)
                {
                    // Delete the reference to it,
                    if (childIndex == 0 && branchNode.ChildCount > 1)
                    {
                        leftKey = branchNode.GetKey(1);
                    }
                    branchNode.RemoveChild(childIndex);
                    // Delete the child branch,
                    DeleteNode(childId);
                }
                // Not empty,
                else
                {
                    // Replace with the new child node reference
                    branchNode.SetChild(childBranch.Id, childIndex);
                    // Set the element count
                    long newChildSize =
                        branchNode.GetChildLeafElementCount(childIndex) -
                        deleteNodeSize;
                    branchNode.SetChildLeafElementCount(newChildSize, childIndex);
                    // Can we set the left key reference?
                    if (childIndex > 0 && leftKey != null)
                    {
                        branchNode.SetKeyToLeft(leftKey, childIndex);
                        leftKey = null;
                    }

                    // Has the size of the child reached the lower threshold?
                    if (childBranch.ChildCount <= 2)
                    {
                        // If it has, we need to redistribute the children,
                        RedistributeBranchElements(branchNode, childIndex, childBranch);
                    }
                }
            }

            // Finally, set the root node
            // If the branch node is a single element, we set the root as the child,
            if (branchNode.ChildCount == 1)
            {
                // This shrinks the height of the tree,
                RootNodeId = branchNode.GetChild(0);
                DeleteNode(branchNode.Id);
                if (TreeHeight != -1)
                {
                    TreeHeight = TreeHeight - 1;
                }
            }
            else
            {
                // Otherwise, we set the branch node.
                RootNodeId = branchNode.Id;
            }

            // Reset the object
            Reset();
        }
Пример #3
0
        public void SetupForPosition(Key key, long posit)
        {
            // If the current leaf is set
            if (currentLeaf != null)
            {
                StackFrame frame     = StackEnd(0);
                long       leafStart = frame.Offset;
                long       leafEnd   = leafStart + currentLeaf.Length;
                // If the position is at the leaf end, or if the keys aren't equal, we
                // need to reset the stack.  This ensures that we correctly place the
                // pointer.
                if (!key.Equals(Key.Tail) &&
                    (posit == leafEnd || !key.Equals(currentLeafKey)))
                {
                    StackClear();
                    currentLeaf    = null;
                    currentLeafKey = null;
                }
                else
                {
                    // Check whether the position is within the bounds of the current leaf
                    // If 'posit' is within this leaf
                    if (posit >= leafStart && posit < leafEnd)
                    {
                        // If the position is within the current leaf, set up the internal
                        // vars as necessary.
                        leafOffset = (int)(posit - leafStart);
                        return;
                    }

                    // If it's not, we reset the stack and start fresh,
                    StackClear();

                    currentLeaf    = null;
                    currentLeafKey = null;
                }
            }

            // ISSUE: It appears looking at the code above, the stack will always be
            //   empty and current_leaf will always be null if we get here.

            // If the stack is empty, push the root node,
            if (StackEmpty)
            {
                // Push the root node onto the top of the stack.
                StackPush(-1, 0, RootNodeId);
                // Set up the current_leaf_key to the default value
                currentLeafKey = Key.Head;
            }
            // Otherwise, we need to setup by querying the BTree.
            while (true)
            {
                if (StackEmpty)
                {
                    throw new ApplicationException("Position out of bounds.  p = " + posit);
                }

                // Pop the last stack frame,
                StackFrame frame          = StackPop();
                NodeId     nodePointer    = frame.NodeId;
                long       leftSideOffset = frame.Offset;
                int        nodeChildIndex = frame.ChildIndex;

                // Relative offset within this node
                long relativeOffset = posit - leftSideOffset;

                // If the node is not on the heap,
                if (!IsHeapNode(nodePointer))
                {
                    // The node is not on the heap. We optimize here.
                    // If we know the node is going to be a leaf node, we set up a
                    // temporary leaf node object with as much information as we know.

                    // Check if we know this is a leaf
                    int treeHeight = TreeHeight;
                    if (treeHeight != -1 &&
                        (stackSize / StackFrameSize) + 1 == treeHeight)
                    {
                        // Fetch the parent node,
                        frame = StackEnd(0);
                        NodeId     twigNodePointer = frame.NodeId;
                        TreeBranch twig            = (TreeBranch)FetchNode(twigNodePointer);
                        long       leafSize        =
                            twig.GetChildLeafElementCount(nodeChildIndex);

                        // This object holds off fetching the contents of the leaf node
                        // unless it's absolutely required.
                        TreeLeaf leaf =
                            new PlaceholderLeaf(ts, nodePointer, (int)leafSize);

                        currentLeaf = leaf;
                        StackPush(nodeChildIndex, leftSideOffset, nodePointer);
                        // Set up the leaf offset and return
                        leafOffset = (int)relativeOffset;

                        return;
                    }
                }

                // Fetch the node
                ITreeNode node = FetchNode(nodePointer);
                if (node is TreeLeaf)
                {
                    // Node is a leaf node
                    TreeLeaf leaf = (TreeLeaf)node;

                    currentLeaf = leaf;
                    StackPush(nodeChildIndex, leftSideOffset, nodePointer);
                    // Set up the leaf offset and return
                    leafOffset = (int)relativeOffset;

                    // Update the tree_height value,
                    TreeHeight = stackSize / StackFrameSize;
                    return;
                }

                // Node is a branch node
                TreeBranch branch     = (TreeBranch)node;
                int        childIndex = branch.IndexOfChild(key, relativeOffset);
                if (childIndex != -1)
                {
                    // Push the current details,
                    StackPush(nodeChildIndex, leftSideOffset, nodePointer);
                    // Found child so push the details
                    StackPush(childIndex,
                              branch.GetChildOffset(childIndex) + leftSideOffset,
                              branch.GetChild(childIndex));
                    // Set up the left key
                    if (childIndex > 0)
                    {
                        currentLeafKey = branch.GetKey(childIndex);
                    }
                }
            }             // while (true)
        }
Пример #4
0
        private TreeGraph CreateRootGraph(Key leftKey, long reference)
        {
            // The node being returned
            TreeGraph graph;

            // Open the area
            IArea area = store.GetArea(reference);
            // What type of node is this?
            short nodeType = area.ReadInt2();
            // The version
            short ver = area.ReadInt2();
            if (nodeType == LeafType) {
                // Read the reference count,
                long refCount = area.ReadInt4();
                // The number of bytes in the leaf
                int leafSize = area.ReadInt4();

                // Set up the leaf node object
                graph = new TreeGraph("leaf", reference);
                graph.SetProperty("ver", ver);
                graph.SetProperty("key", leftKey.ToString());
                graph.SetProperty("reference_count", refCount);
                graph.SetProperty("leaf_size", leafSize);

            } else if (nodeType == BranchType) {
                // The data size area containing the children information
                int childDataSize = area.ReadInt4();
                long[] data = new long[childDataSize];
                for (int i = 0; i < childDataSize; ++i) {
                    data[i] = area.ReadInt8();
                }
                // Create the TreeBranch object to query it
                TreeBranch branch = new TreeBranch(reference, data, childDataSize);
                // Set up the branch node object
                graph = new TreeGraph("branch", reference);
                graph.SetProperty("ver", ver);
                graph.SetProperty("key", leftKey.ToString());
                graph.SetProperty("branch_size", branch.ChildCount);
                // Recursively add each child into the tree
                for (int i = 0; i < branch.ChildCount; ++i) {
                    long child_ref = branch.GetChild(i);
                    // If the ref is a special node, skip it
                    if ((child_ref & 0x01000000000000000L) != 0) {
                        // Should we record special nodes?
                    } else {
                        Key newLeftKey = (i > 0) ? branch.GetKey(i) : leftKey;
                        TreeGraph bn = new TreeGraph("child_meta", reference);
                        bn.SetProperty("extent", branch.GetChildLeafElementCount(i));
                        graph.AddChild(bn);
                        graph.AddChild(CreateRootGraph(newLeftKey, child_ref));
                    }
                }
            } else {
                throw new IOException("Unknown node type: " + nodeType);
            }

            return graph;
        }
Пример #5
0
        private bool RedistributeBranchElements(TreeBranch branch, int childIndex, TreeBranch child)
        {
            // We distribute the nodes in the child branch with the branch
            // immediately to the right.  If that's not possible, then we distribute
            // with the left.

            // If branch has only a single value, return immediately
            int branchSize = branch.ChildCount;
            if (branchSize == 1) {
                return false;
            }

            int leftI, rightI;
            TreeBranch left, right;
            if (childIndex < branchSize - 1) {
                // Distribute with the right
                leftI = childIndex;
                rightI = childIndex + 1;
                left = child;
                right = (TreeBranch)UnfreezeNode(FetchNode(branch.GetChild(childIndex + 1)));
                branch.SetChild(right.Id, childIndex + 1);
            } else {
                // Distribute with the left
                leftI = childIndex - 1;
                rightI = childIndex;
                left = (TreeBranch)UnfreezeNode(FetchNode(branch.GetChild(childIndex - 1)));
                right = child;
                branch.SetChild(left.Id, childIndex - 1);
            }

            // Get the mid value key reference
            Key midKey = branch.GetKey(rightI);

            // Perform the merge,
            Key newMidKey = left.Merge(right, midKey);
            // Reset the leaf element count
            branch.SetChildLeafElementCount(left.LeafElementCount, leftI);
            branch.SetChildLeafElementCount(right.LeafElementCount, rightI);

            // If after the merge the right branch is empty, we need to remove it
            if (right.IsEmpty) {
                // Delete the node
                DeleteNode(right.Id);
                // And remove it from the branch,
                branch.RemoveChild(rightI);
                return true;
            }

            // Otherwise set the key reference
            branch.SetKeyToLeft(newMidKey, rightI);
            return false;
        }
Пример #6
0
        private TreeReportNode CreateDiagnosticRootGraph(Key leftKey, NodeId id)
        {
            // The node being returned
            TreeReportNode node;

            // Open the area
            IArea area = nodeStore.GetArea(ToInt64StoreAddress(id));
            // What type of node is this?
            short nodeType = area.ReadInt2();
            // The version
            short ver = area.ReadInt2();

            if (nodeType == StoreLeafType)
            {
                // Read the reference count,
                long refCount = area.ReadInt4();
                // The number of bytes in the leaf
                int leafSize = area.ReadInt4();

                // Set up the leaf node object
                node = new TreeReportNode("leaf", id);
                node.SetProperty("VER", ver);
                node.SetProperty("key", leftKey.ToString());
                node.SetProperty("reference_count", refCount);
                node.SetProperty("leaf_size", leafSize);
            }
            else if (nodeType == StoreBranchType)
            {
                // The data size area containing the children information
                int    childDataSize = area.ReadInt4();
                long[] dataArr       = new long[childDataSize];
                for (int i = 0; i < childDataSize; ++i)
                {
                    dataArr[i] = area.ReadInt8();
                }
                // Create the TreeBranch object to query it
                TreeBranch branch = new TreeBranch(id, dataArr, childDataSize);
                // Set up the branch node object
                node = new TreeReportNode("branch", id);
                node.SetProperty("VER", ver);
                node.SetProperty("key", leftKey.ToString());
                node.SetProperty("branch_size", branch.ChildCount);
                // Recursively add each child into the tree
                for (int i = 0; i < branch.ChildCount; ++i)
                {
                    NodeId childId = branch.GetChild(i);
                    // If the id is a special node, skip it
                    if (childId.IsSpecial)
                    {
                        // Should we record special nodes?
                    }
                    else
                    {
                        Key            newLeftKey = (i > 0) ? branch.GetKey(i) : leftKey;
                        TreeReportNode bn         = new TreeReportNode("child_meta", id);
                        bn.SetProperty("extent", branch.GetChildLeafElementCount(i));
                        node.ChildNodes.Add(bn);
                        node.ChildNodes.Add(CreateDiagnosticRootGraph(newLeftKey, childId));
                    }
                }
            }
            else
            {
                throw new IOException("Unknown node type: " + nodeType);
            }

            return(node);
        }
Пример #7
0
        private TreeReportNode CreateDiagnosticRootGraph(Key leftKey, NodeId id)
        {
            // The node being returned
            TreeReportNode node;

            // Open the area
            IArea area = nodeStore.GetArea(ToInt64StoreAddress(id));
            // What type of node is this?
            short nodeType = area.ReadInt2();
            // The version
            short ver = area.ReadInt2();
            if (nodeType == StoreLeafType) {
                // Read the reference count,
                long refCount = area.ReadInt4();
                // The number of bytes in the leaf
                int leafSize = area.ReadInt4();

                // Set up the leaf node object
                node = new TreeReportNode("leaf", id);
                node.SetProperty("VER", ver);
                node.SetProperty("key", leftKey.ToString());
                node.SetProperty("reference_count", refCount);
                node.SetProperty("leaf_size", leafSize);

            } else if (nodeType == StoreBranchType) {
                // The data size area containing the children information
                int childDataSize = area.ReadInt4();
                long[] dataArr = new long[childDataSize];
                for (int i = 0; i < childDataSize; ++i) {
                    dataArr[i] = area.ReadInt8();
                }
                // Create the TreeBranch object to query it
                TreeBranch branch = new TreeBranch(id, dataArr, childDataSize);
                // Set up the branch node object
                node = new TreeReportNode("branch", id);
                node.SetProperty("VER", ver);
                node.SetProperty("key", leftKey.ToString());
                node.SetProperty("branch_size", branch.ChildCount);
                // Recursively add each child into the tree
                for (int i = 0; i < branch.ChildCount; ++i) {
                    NodeId childId = branch.GetChild(i);
                    // If the id is a special node, skip it
                    if (childId.IsSpecial) {
                        // Should we record special nodes?
                    } else {
                        Key newLeftKey = (i > 0) ? branch.GetKey(i) : leftKey;
                        TreeReportNode bn = new TreeReportNode("child_meta", id);
                        bn.SetProperty("extent", branch.GetChildLeafElementCount(i));
                        node.ChildNodes.Add(bn);
                        node.ChildNodes.Add(CreateDiagnosticRootGraph(newLeftKey, childId));
                    }
                }

            } else {
                throw new IOException("Unknown node type: " + nodeType);
            }

            return node;
        }