예제 #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
        public IList <NodeId> Persist(TreeWrite write)
        {
            try {
                nodeStore.LockForWrite();

                IList <ITreeNode> allBranches = write.BranchNodes;
                IList <ITreeNode> allLeafs    = write.LeafNodes;
                List <ITreeNode>  nodes       = new List <ITreeNode>(allBranches.Count + allLeafs.Count);
                nodes.AddRange(allBranches);
                nodes.AddRange(allLeafs);

                // The list of nodes to be allocated,
                int sz = nodes.Count;
                // The list of allocated referenced for the nodes,
                NodeId[] refs = new NodeId[sz];
                // The list of area writers,
                IAreaWriter[] writers = new IAreaWriter[sz];

                // Allocate the space first,
                for (int i = 0; i < sz; ++i)
                {
                    ITreeNode node = nodes[i];
                    // Is it a branch node?
                    if (node is TreeBranch)
                    {
                        TreeBranch branch = (TreeBranch)node;
                        int        ndsz   = branch.NodeDataSize;
                        writers[i] = nodeStore.CreateArea(4 + 4 + (ndsz * 8));
                    }
                    // Otherwise, it must be a leaf node,
                    else
                    {
                        TreeLeaf leaf = (TreeLeaf)node;
                        int      lfsz = leaf.Length;
                        writers[i] = nodeStore.CreateArea(12 + lfsz);
                    }
                    // Set the reference,
                    refs[i] = FromInt64StoreAddress(writers[i].Id);
                }

                // Now write out the data,
                for (int i = 0; i < sz; ++i)
                {
                    ITreeNode node = nodes[i];
                    // Is it a branch node?
                    if (node is TreeBranch)
                    {
                        TreeBranch branch = (TreeBranch)node;

                        // The number of children
                        int chsz = branch.ChildCount;
                        // For each child, if it's a heap node, look up the child id and
                        // reference map in the sequence and set the reference accordingly,
                        for (int o = 0; o < chsz; ++o)
                        {
                            NodeId childId = branch.GetChild(o);
                            if (childId.IsInMemory)
                            {
                                // The ref is currently on the heap, so adjust accordingly
                                int refId = write.LookupRef(i, o);
                                branch.SetChild(refs[refId], o);
                            }
                        }

                        // Write out the branch to the store
                        long[] nodeData = branch.NodeData;
                        int    ndsz     = branch.NodeDataSize;

                        IAreaWriter writer = writers[i];
                        writer.WriteInt2(StoreBranchType);
                        writer.WriteInt2(1);                         // version
                        writer.WriteInt4(ndsz);
                        for (int o = 0; o < ndsz; ++o)
                        {
                            writer.WriteInt8(nodeData[o]);
                        }
                        writer.Finish();

                        // Make this into a branch node and add to the cache,
                        branch = new TreeBranch(refs[i], nodeData, ndsz);
                        // Put this branch in the cache,
                        lock (branchCache) {
                            branchCache.Set(refs[i], branch);
                        }
                    }
                    // Otherwise, it must be a leaf node,
                    else
                    {
                        TreeLeaf    leaf   = (TreeLeaf)node;
                        IAreaWriter writer = writers[i];
                        writer.WriteInt2(StoreLeafType);
                        writer.WriteInt2(1);                         // version
                        writer.WriteInt4(1);                         // reference count
                        writer.WriteInt4(leaf.Length);
                        leaf.WriteTo(writer);
                        writer.Finish();
                    }
                }

                return(refs);
            } finally {
                nodeStore.UnlockForWrite();
            }
        }
예제 #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);
        }
예제 #8
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;
        }