예제 #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 MoveLastHalfInto(TreeBranch dest)
        {
            int midpoint = children.Length / 2;

            // Check mutable
            CheckReadOnly();
            dest.CheckReadOnly();

            // Check this is full
            if (!IsFull)
            {
                throw new InvalidOperationException("Branch node is not full.");
            }

            // Check destination is empty
            if (!dest.IsEmpty)
            {
                throw new ArgumentException("Destination branch node is not empty.");
            }

            // Copy,
            Array.Copy(children, midpoint + 1, dest.children, 0, midpoint - 1);

            // New child count in each branch node.
            int newChildCount = MaxChildCount / 2;

            // Set the size of this and the destination node
            childrenCount      = newChildCount;
            dest.childrenCount = newChildCount;
        }
예제 #3
0
        private void UpdateStackProperties(int sizeDiff)
        {
            StackFrame frame = StackEnd(0);
            int        sz    = FrameCount;

            // Walk the stack from the end
            for (int i = 1; i < sz; ++i)
            {
                int childIndex = frame.ChildIndex;
                frame = StackEnd(i);

                NodeId     nodeId = frame.NodeId;
                TreeBranch branch = (TreeBranch)FetchNode(nodeId);
                branch.SetChildLeafElementCount(branch.GetChildLeafElementCount(childIndex) + sizeDiff, childIndex);
            }
        }
예제 #4
0
        public Key MergeLeft(TreeBranch right, Key midValue, int count)
        {
            // Check mutable
            CheckReadOnly();

            // If we moving all from right,
            if (count == right.ChildCount)
            {
                // Move all the elements into this node,
                int destP    = childrenCount * 5;
                int rightLen = (right.childrenCount * 5) - 2;
                Array.Copy(right.children, 0, children, destP, rightLen);
                children[destP - 2] = midValue.GetEncoded(1);
                children[destP - 1] = midValue.GetEncoded(2);
                // Update children_count
                childrenCount += right.childrenCount;
                return(null);
            }
            if (count < right.ChildCount)
            {
                right.CheckReadOnly();

                // Shift elements from right to left
                // The amount to move that will leave the right node at min threshold
                int destP    = ChildCount * 5;
                int rightLen = (count * 5) - 2;
                Array.Copy(right.children, 0, children, destP, rightLen);
                // Redistribute the right elements
                int rightRedist = (count * 5);
                // The midpoint value becomes the extent shifted off the end
                long newMidpointValue1 = right.children[rightRedist - 2];
                long newMidpointValue2 = right.children[rightRedist - 1];
                // Shift the right child
                Array.Copy(right.children, rightRedist, right.children, 0,
                           right.children.Length - rightRedist);
                children[destP - 2]  = midValue.GetEncoded(1);
                children[destP - 1]  = midValue.GetEncoded(2);
                childrenCount       += count;
                right.childrenCount -= count;

                // Return the new midpoint value
                return(new Key(newMidpointValue1, newMidpointValue2));
            }

            throw new ApplicationException("count > right.size()");
        }
예제 #5
0
        private void UnfreezeStack()
        {
            StackFrame frame = StackEnd(0);

            NodeId oldChildNodeId = frame.NodeId;

            // If the leaf ref isn't frozen then we exit early
            if (!IsFrozen(oldChildNodeId))
            {
                return;
            }

            TreeLeaf leaf           = (TreeLeaf)UnfreezeNode(FetchNode(oldChildNodeId));
            NodeId   newChildNodeId = leaf.Id;

            frame.NodeId = newChildNodeId;
            currentLeaf  = leaf;
            // NOTE: Setting current_leaf here does not change the key of the node
            //   so we don't need to update current_leaf_key.

            // Walk the rest of the stack from the end
            int sz = FrameCount;

            for (int i = 1; i < sz; ++i)
            {
                int changedChildIndex = frame.ChildIndex;
                frame = StackEnd(i);
                NodeId     oldBranchId = frame.NodeId;
                TreeBranch branch      = (TreeBranch)UnfreezeNode(FetchNode(oldBranchId));
                // Get the child_i from the stack,
                branch.SetChild(newChildNodeId, changedChildIndex);

                // Change the stack entry
                frame.NodeId = branch.Id;

                newChildNodeId = branch.Id;
            }

            // Set the new root node ref
            RootNodeId = newChildNodeId;
        }
예제 #6
0
        public void WriteLeafOnly(Key key)
        {
            // Get the stack frame for the last entry.
            StackFrame frame = StackEnd(0);
            // The leaf
            NodeId leafId = frame.NodeId;
            // Write it out
            NodeId newId = WriteNode(leafId);

            // If new_ref = leaf_ref, then we didn't write a new node
            if (newId.Equals(leafId))
            {
                return;
            }

            // Otherwise, update the references,
            frame.NodeId = newId;
            currentLeaf  = (TreeLeaf)FetchNode(newId);
            // Walk back up the stack and update the ref as necessary
            int sz = FrameCount;

            for (int i = 1; i < sz; ++i)
            {
                // Get the child_i from the stack,
                int changedChildIndex = frame.ChildIndex;

                frame = StackEnd(i);

                NodeId     oldBranchId = frame.NodeId;
                TreeBranch branch      = (TreeBranch)UnfreezeNode(FetchNode(oldBranchId));
                branch.SetChild(newId, changedChildIndex);

                // Change the stack entry
                newId        = branch.Id;
                frame.NodeId = newId;
            }

            // Set the new root node ref
            RootNodeId = newId;
        }
예제 #7
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;
        }
예제 #8
0
        private ITreeNode FetchNode(long nodeId)
        {
            // Is it a special static node?
            if ((nodeId & 0x01000000000000000L) != 0)
                return SparseLeafNode.Create(nodeId);

            // Is this a branch node in the cache?
            TreeBranch branch;
            lock (branchCache) {
                branch = (TreeBranch)branchCache.Get(nodeId);
                if (branch != null)
                    return branch;
            }

            // Not found in the cache, so fetch the area from the backing store and
            // create the node type.

            // Get the area for the node
            IArea nodeArea = store.GetArea(nodeId);
            // Wrap around a BinaryReader for reading values from the store.
            BinaryReader reader = new BinaryReader(new AreaInputStream(nodeArea, 256));

            short nodeType = reader.ReadInt16();

            if (nodeType == LeafType) {
                // Read the key
                reader.ReadInt16();  // version
                reader.ReadInt32();   // reference count
                int leafSize = reader.ReadInt32();

                // Return a leaf that's mapped to the data in the store
                nodeArea.Position = 0;
                return new AreaTreeLeaf(nodeId, leafSize, nodeArea);
            } else if (nodeType == BranchType) {
                // Note that the entire branch is loaded into memory now,
                reader.ReadInt16();  // version
                int childDataSize = reader.ReadInt32();
                long[] data = new long[childDataSize];
                for (int i = 0; i < childDataSize; ++i) {
                    data[i] = reader.ReadInt64();
                }

                branch = new TreeBranch(nodeId, data, childDataSize);
                // Put this branch in the cache,
                lock (branchCache) {
                    branchCache.Set(nodeId, branch);
                    // And return the branch
                    return branch;
                }
            }

            throw new ApplicationException("Unknown node type: " + nodeType);
        }
예제 #9
0
파일: TreeBranch.cs 프로젝트: ikvm/cloudb
        public void MoveLastHalfInto(TreeBranch dest)
        {
            int midpoint = children.Length / 2;

            CheckReadOnly();
            dest.CheckReadOnly();

            // Check this is full
            if (!IsFull)
                throw new ApplicationException("Branch node is not full.");

            // Check destination is empty
            if (dest.ChildCount != 0)
                throw new ApplicationException("Destination branch node is not empty.");

            // Copy,
            Array.Copy(children, midpoint + 1, dest.children, 0, midpoint - 1);

            // New child count in each branch node.
            int new_child_count = MaxSize / 2;
            // Set the size of this and the destination node
            childCount = new_child_count;
            dest.childCount = new_child_count;
        }
예제 #10
0
        public IList<long> Persist(TreeWrite write)
        {
            try {
                store.LockForWrite();

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

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

                // Allocate the space first,
                for (int i = 0; i < sz; ++i) {
                    ITreeNode node = nodes[i];
                    if (node is TreeBranch) {
                        TreeBranch branch = (TreeBranch)node;
                        int ndsz = branch.DataSize;
                        areas[i] = store.CreateArea(4 + 4 + (ndsz * 8));
                    } else {
                        TreeLeaf leaf = (TreeLeaf)node;
                        int lfsz = leaf.Length;
                        areas[i] = store.CreateArea(12 + lfsz);
                    }
                    // Set the reference,
                    refs[i] = areas[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) {
                            long childId = branch.GetChild(o);
                            if (childId < 0) {
                                // The ref is currently on the heap, so adjust accordingly
                                int refId = write.LookupRef(i, o);
                                branch.SetChild(o, refs[refId]);
                            }
                        }

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

                        IAreaWriter writer = areas[i];
                        writer.WriteInt2(BranchType);
                        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);
                        }
                    } else {
                        // Otherwise, it must be a leaf node,
                        TreeLeaf leaf = (TreeLeaf)node;

                        IAreaWriter area = areas[i];
                        area.WriteInt2(LeafType);
                        area.WriteInt2(1);  // version
                        area.WriteInt4(1);            // reference count
                        area.WriteInt4(leaf.Length);
                        leaf.WriteTo(area);
                        area.Finish();
                    }
                }

                return refs;
            } finally {
                store.UnlockForWrite();
            }
        }
예제 #11
0
파일: TreeBranch.cs 프로젝트: ikvm/cloudb
        public Key MergeLeft(TreeBranch right, Key mid_value, int count)
        {
            // Check mutable
            CheckReadOnly();

            // If we moving all from right,
            if (count == right.ChildCount) {
                // Move all the elements into this node,
                int dest_p = childCount * 4;
                int right_len = (right.childCount * 4) - 2;
                Array.Copy(right.children, 0, children, dest_p, right_len);
                children[dest_p - 2] = mid_value.GetEncoded(1);
                children[dest_p - 1] = mid_value.GetEncoded(2);
                // Update children_count
                childCount += right.childCount;

                return null;
            }
            if (count < right.ChildCount) {
                right.CheckReadOnly();

                // Shift elements from right to left
                // The amount to move that will leave the right node at min threshold
                int dest_p = ChildCount * 4;
                int right_len = (count * 4) - 2;
                Array.Copy(right.children, 0, children, dest_p, right_len);
                // Redistribute the right elements
                int right_redist = (count * 4);
                // The midpoint value becomes the extent shifted off the end
                long new_midpoint_value1 = right.children[right_redist - 2];
                long new_midpoint_value2 = right.children[right_redist - 1];
                // Shift the right child
                Array.Copy(right.children, right_redist, right.children, 0,
                                 right.children.Length - right_redist);
                children[dest_p - 2] = mid_value.GetEncoded(1);
                children[dest_p - 1] = mid_value.GetEncoded(2);
                childCount += count;
                right.childCount -= count;

                // Return the new midpoint value
                return new Key(new_midpoint_value1, new_midpoint_value2);
            }

            throw new ArgumentException("count > right.size()");
        }
예제 #12
0
파일: TreeBranch.cs 프로젝트: ikvm/cloudb
 public TreeBranch(long id, TreeBranch branch, int maxChildCount)
     : this(id, maxChildCount)
 {
     Array.Copy(branch.children, 0, children, 0, Math.Min(branch.children.Length, children.Length));
     childCount = branch.childCount;
 }
예제 #13
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();
        }
예제 #14
0
        private ITreeNode FetchNode(NodeId nodeId)
        {
            // Is it a special static node?
            if (nodeId.IsSpecial)
            {
                return(SpecialStaticNode(nodeId));
            }

            // Is this a branch node in the cache?
            NodeId     cacheKey = nodeId;
            TreeBranch branch;

            lock (branchCache) {
                branch = (TreeBranch)branchCache.Get(cacheKey);
                if (branch != null)
                {
                    return(branch);
                }
            }

            // Not found in the cache, so fetch the area from the backing store and
            // create the node type.

            // Get the area for the node
            IArea nodeArea = nodeStore.GetArea(ToInt64StoreAddress(nodeId));
            // Wrap around a buffered BinaryRader for reading values from the store.
            BinaryReader input = new BinaryReader(new AreaInputStream(nodeArea, 256));

            short nodeType = input.ReadInt16();

            // Is the node type a leaf node?
            if (nodeType == StoreLeafType)
            {
                // Read the key
                input.ReadInt16();                 // version
                input.ReadInt32();                 // reference count
                int leafSize = input.ReadInt32();

                // Return a leaf that's mapped to the data in the store
                nodeArea.Position = 0;
                return(new AreaTreeLeaf(nodeId, leafSize, nodeArea));
            }
            // Is the node type a branch node?
            if (nodeType == StoreBranchType)
            {
                // Note that the entire branch is loaded into memory now,
                input.ReadInt16();                 // version
                int    childDataSize = input.ReadInt32();
                long[] dataArr       = new long[childDataSize];
                for (int i = 0; i < childDataSize; ++i)
                {
                    dataArr[i] = input.ReadInt64();
                }
                branch = new TreeBranch(nodeId, dataArr, childDataSize);
                // Put this branch in the cache,
                lock (branchCache) {
                    branchCache.Set(cacheKey, branch);
                    // And return the branch
                    return(branch);
                }
            }

            throw new ApplicationException("Unknown node type: " + nodeType);
        }
예제 #15
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;
        }
예제 #16
0
파일: TreeNodeHeap.cs 프로젝트: ikvm/cloudb
 internal HeapTreeBranch(ITransaction tran, long nodeId, TreeBranch branch, int maxChildren)
     : base(nodeId, branch, maxChildren)
 {
     this.tran = tran;
 }
예제 #17
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();
            }
        }
예제 #18
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);
        }
예제 #19
0
        public long Create()
        {
            if (initialized)
            {
                throw new InvalidOperationException("This tree store is already initialized.");
            }

            // Temporary node heap for creating a starting database
            TreeNodeHeap nodeHeap = new TreeNodeHeap(17, 4 * 1024 * 1024);

            // Write a root node to the store,
            // Create an empty head node
            TreeLeaf headLeaf = nodeHeap.CreateLeaf(null, Key.Head, 256);

            // Insert a tree identification pattern
            headLeaf.Write(0, new byte[] { 1, 1, 1, 1 }, 0, 4);
            // Create an empty tail node
            TreeLeaf tailLeaf = nodeHeap.CreateLeaf(null, Key.Tail, 256);

            // Insert a tree identification pattern
            tailLeaf.Write(0, new byte[] { 1, 1, 1, 1 }, 0, 4);

            // The write sequence,
            TreeWrite seq = new TreeWrite();

            seq.NodeWrite(headLeaf);
            seq.NodeWrite(tailLeaf);
            IList <NodeId> refs = Persist(seq);

            // Create a branch,
            TreeBranch rootBranch = nodeHeap.CreateBranch(null, MaxBranchSize);

            rootBranch.Set(refs[0], 4, Key.Tail, refs[1], 4);

            seq = new TreeWrite();
            seq.NodeWrite(rootBranch);
            refs = Persist(seq);

            // The written root node reference,
            NodeId rootId = refs[0];

            // Delete the head and tail leaf, and the root branch
            nodeHeap.Delete(headLeaf.Id);
            nodeHeap.Delete(tailLeaf.Id);
            nodeHeap.Delete(rootBranch.Id);

            // Write this version info to the store,
            long versionId = WriteSingleVersionInfo(1, rootId, new List <NodeId>(0));

            // Make a first version
            VersionInfo versionInfo = new VersionInfo(1, rootId, versionId);

            versions.Add(versionInfo);

            // Flush this to the version list
            IAreaWriter versionList = nodeStore.CreateArea(64);

            versionList.WriteInt4(0x01433);
            versionList.WriteInt4(1);
            versionList.WriteInt8(versionId);
            versionList.Finish();

            // Get the versions id
            long versionListId = versionList.Id;

            // The final header
            IAreaWriter header = nodeStore.CreateArea(64);

            header.WriteInt4(0x09391);       // The magic value,
            header.WriteInt4(1);             // The version
            header.WriteInt8(versionListId);
            header.Finish();

            // Set up the internal variables,
            headerId = header.Id;

            initialized = true;
            // And return the header reference
            return(headerId);
        }
예제 #20
0
        public Key Merge(TreeBranch right, Key midValue)
        {
            // Check mutable
            CheckReadOnly();
            right.CheckReadOnly();

            // How many elements in total?
            int totalElements = ChildCount + right.ChildCount;

            // If total elements is smaller than max size,
            if (totalElements <= MaxChildCount)
            {
                // Move all the elements into this node,
                int destP    = childrenCount * 5;
                int rightLen = (right.childrenCount * 5) - 2;
                Array.Copy(right.children, 0, children, destP, rightLen);
                children[destP - 2] = midValue.GetEncoded(1);
                children[destP - 1] = midValue.GetEncoded(2);
                // Update children_count
                childrenCount      += right.childrenCount;
                right.childrenCount = 0;

                return(null);
            }
            else
            {
                long newMidpointValue1, newMidpointValue2;

                // Otherwise distribute between the nodes,
                int maxShift = (MaxChildCount + right.MaxChildCount) - totalElements;
                if (maxShift <= 2)
                {
                    return(midValue);
                }

                int minThreshold = MaxChildCount / 2;
                if (ChildCount < right.ChildCount)
                {
                    // Shift elements from right to left
                    // The amount to move that will leave the right node at min threshold
                    int count    = Math.Min(right.ChildCount - minThreshold, maxShift);
                    int destP    = ChildCount * 5;
                    int rightLen = (count * 5) - 2;

                    Array.Copy(right.children, 0, children, destP, rightLen);
                    // Redistribute the right elements
                    int rightRedist = (count * 5);
                    // The midpoint value becomes the extent shifted off the end
                    newMidpointValue1 = right.children[rightRedist - 2];
                    newMidpointValue2 = right.children[rightRedist - 1];
                    // Shift the right child
                    Array.Copy(right.children, rightRedist, right.children, 0,
                               right.children.Length - rightRedist);
                    children[destP - 2]  = midValue.GetEncoded(1);
                    children[destP - 1]  = midValue.GetEncoded(2);
                    childrenCount       += count;
                    right.childrenCount -= count;
                }
                else
                {
                    // Shift elements from left to right
                    // The amount to move that will leave the left node at min threshold
                    int count = Math.Min(ChildCount - minThreshold, maxShift);

                    // Make room for these elements
                    int rightRedist = (count * 5);
                    Array.Copy(right.children, 0, right.children, rightRedist,
                               right.children.Length - rightRedist);
                    int srcP    = (ChildCount - count) * 5;
                    int leftLen = (count * 5) - 2;
                    Array.Copy(children, srcP, right.children, 0, leftLen);
                    right.children[rightRedist - 2] = midValue.GetEncoded(1);
                    right.children[rightRedist - 1] = midValue.GetEncoded(2);
                    // The midpoint value becomes the extent shifted off the end
                    newMidpointValue1 = children[srcP - 2];
                    newMidpointValue2 = children[srcP - 1];
                    // Update children counts
                    childrenCount       -= count;
                    right.childrenCount += count;
                }

                return(new Key(newMidpointValue1, newMidpointValue2));
            }
        }
예제 #21
0
 public TreeBranch(NodeId nodeId, TreeBranch branch, int maxChildrenCount)
     : this(nodeId, maxChildrenCount)
 {
     Array.Copy(branch.children, 0, children, 0, Math.Min(branch.children.Length, children.Length));
     childrenCount = branch.ChildCount;
 }
예제 #22
0
        public Key Merge(TreeBranch right, Key midValue)
        {
            // Check mutable
            CheckReadOnly();
            right.CheckReadOnly();

            // How many elements in total?
            int totalElements = ChildCount + right.ChildCount;
            // If total elements is smaller than max size,
            if (totalElements <= MaxChildCount) {
                // Move all the elements into this node,
                int destP = childrenCount*5;
                int rightLen = (right.childrenCount*5) - 2;
                Array.Copy(right.children, 0, children, destP, rightLen);
                children[destP - 2] = midValue.GetEncoded(1);
                children[destP - 1] = midValue.GetEncoded(2);
                // Update children_count
                childrenCount += right.childrenCount;
                right.childrenCount = 0;

                return null;
            } else {
                long newMidpointValue1, newMidpointValue2;

                // Otherwise distribute between the nodes,
                int maxShift = (MaxChildCount + right.MaxChildCount) - totalElements;
                if (maxShift <= 2)
                    return midValue;

                int minThreshold = MaxChildCount/2;
                if (ChildCount < right.ChildCount) {
                    // Shift elements from right to left
                    // The amount to move that will leave the right node at min threshold
                    int count = Math.Min(right.ChildCount - minThreshold, maxShift);
                    int destP = ChildCount*5;
                    int rightLen = (count*5) - 2;

                    Array.Copy(right.children, 0, children, destP, rightLen);
                    // Redistribute the right elements
                    int rightRedist = (count*5);
                    // The midpoint value becomes the extent shifted off the end
                    newMidpointValue1 = right.children[rightRedist - 2];
                    newMidpointValue2 = right.children[rightRedist - 1];
                    // Shift the right child
                    Array.Copy(right.children, rightRedist, right.children, 0,
                               right.children.Length - rightRedist);
                    children[destP - 2] = midValue.GetEncoded(1);
                    children[destP - 1] = midValue.GetEncoded(2);
                    childrenCount += count;
                    right.childrenCount -= count;

                } else {
                    // Shift elements from left to right
                    // The amount to move that will leave the left node at min threshold
                    int count = Math.Min(ChildCount - minThreshold, maxShift);

                    // Make room for these elements
                    int rightRedist = (count*5);
                    Array.Copy(right.children, 0, right.children, rightRedist,
                               right.children.Length - rightRedist);
                    int srcP = (ChildCount - count)*5;
                    int leftLen = (count*5) - 2;
                    Array.Copy(children, srcP, right.children, 0, leftLen);
                    right.children[rightRedist - 2] = midValue.GetEncoded(1);
                    right.children[rightRedist - 1] = midValue.GetEncoded(2);
                    // The midpoint value becomes the extent shifted off the end
                    newMidpointValue1 = children[srcP - 2];
                    newMidpointValue2 = children[srcP - 1];
                    // Update children counts
                    childrenCount -= count;
                    right.childrenCount += count;
                }

                return new Key(newMidpointValue1, newMidpointValue2);
            }
        }
예제 #23
0
        private ITreeNode FetchNode(NodeId nodeId)
        {
            // Is it a special static node?
            if (nodeId.IsSpecial) {
                return SpecialStaticNode(nodeId);
            }

            // Is this a branch node in the cache?
            NodeId cacheKey = nodeId;
            TreeBranch branch;
            lock (branchCache) {
                branch = (TreeBranch) branchCache.Get(cacheKey);
                if (branch != null) {
                    return branch;
                }
            }

            // Not found in the cache, so fetch the area from the backing store and
            // create the node type.

            // Get the area for the node
            IArea nodeArea = nodeStore.GetArea(ToInt64StoreAddress(nodeId));
            // Wrap around a buffered BinaryRader for reading values from the store.
            BinaryReader input = new BinaryReader(new AreaInputStream(nodeArea, 256));

            short nodeType = input.ReadInt16();
            // Is the node type a leaf node?
            if (nodeType == StoreLeafType) {
                // Read the key
                input.ReadInt16(); // version
                input.ReadInt32(); // reference count
                int leafSize = input.ReadInt32();

                // Return a leaf that's mapped to the data in the store
                nodeArea.Position = 0;
                return new AreaTreeLeaf(nodeId, leafSize, nodeArea);
            }
                // Is the node type a branch node?
            if (nodeType == StoreBranchType) {
                // Note that the entire branch is loaded into memory now,
                input.ReadInt16(); // version
                int childDataSize = input.ReadInt32();
                long[] dataArr = new long[childDataSize];
                for (int i = 0; i < childDataSize; ++i) {
                    dataArr[i] = input.ReadInt64();
                }
                branch = new TreeBranch(nodeId, dataArr, childDataSize);
                // Put this branch in the cache,
                lock (branchCache) {
                    branchCache.Set(cacheKey, branch);
                    // And return the branch
                    return branch;
                }
            }

            throw new ApplicationException("Unknown node type: " + nodeType);
        }
예제 #24
0
        public void InsertLeaf(Key newLeafKey, TreeLeaf newLeaf, bool before)
        {
            int leafSize = newLeaf.Length;

            if (leafSize <= 0)
            {
                throw new ArgumentException("size <= 0");
            }

            // The current absolute position and key
            Key newKey = newLeafKey;

            // The frame at the end of the stack,
            StackFrame frame = StackEnd(0);

            object[] info;
            object[] rInfo = new object[5];
            Key      leftKey;
            long     curAbsolutePos;

            // If we are inserting the new leaf after,
            if (!before)
            {
                info = new object[] {
                    currentLeaf.Id,
                    (long)currentLeaf.Length,
                    newLeafKey,
                    newLeaf.Id,
                    (long)newLeaf.Length
                };
                leftKey        = null;
                curAbsolutePos = frame.Offset + currentLeaf.Length;
            }
            // Otherwise we are inserting the new leaf before,
            else
            {
                // If before and current_leaf key is different than new_leaf key, we
                // generate an error
                if (!currentLeafKey.Equals(newLeafKey))
                {
                    throw new InvalidOperationException("Can't insert different new key before.");
                }

                info = new Object[] {
                    newLeaf.Id,
                    (long)newLeaf.Length,
                    currentLeafKey,
                    currentLeaf.Id,
                    (long)currentLeaf.Length
                };
                leftKey        = newLeafKey;
                curAbsolutePos = frame.Offset - 1;
            }

            bool insertTwoNodes = true;

            int sz = FrameCount;

            // Walk the stack from the end
            for (int i = 1; i < sz; ++i)
            {
                // child_i is the previous frame's child_i
                int childIndex = frame.ChildIndex;
                frame = StackEnd(i);
                // The child ref of this stack element
                NodeId childId = frame.NodeId;
                // Fetch it
                TreeBranch branch = (TreeBranch)UnfreezeNode(FetchNode(childId));

                // Do we have two nodes to insert into the branch?
                if (insertTwoNodes)
                {
                    TreeBranch insertBranch;
                    int        insertIndex = childIndex;
                    // If the branch is full,
                    if (branch.IsFull)
                    {
                        // Create a new node,
                        TreeBranch leftBranch  = branch;
                        TreeBranch rightBranch = CreateBranch();
                        // Split the branch,
                        Key midpointKey = leftBranch.MidPointKey;
                        // And move half of this branch into the new branch
                        leftBranch.MoveLastHalfInto(rightBranch);
                        // We split so we need to return a split flag,
                        rInfo[0] = leftBranch.Id;
                        rInfo[1] = leftBranch.LeafElementCount;
                        rInfo[2] = midpointKey;
                        rInfo[3] = rightBranch.Id;
                        rInfo[4] = rightBranch.LeafElementCount;
                        // Adjust insert_n and insert_branch
                        if (insertIndex >= leftBranch.ChildCount)
                        {
                            insertIndex -= leftBranch.ChildCount;
                            insertBranch = rightBranch;
                            rInfo[4]     = (long)rInfo[4] + newLeaf.Length;
                            // If insert_n == 0, we change the midpoint value to the left
                            // key value,
                            if (insertIndex == 0 && leftKey != null)
                            {
                                rInfo[2] = leftKey;
                                leftKey  = null;
                            }
                        }
                        else
                        {
                            insertBranch = leftBranch;
                            rInfo[1]     = (long)rInfo[1] + newLeaf.Length;
                        }
                    }
                    // If it's not full,
                    else
                    {
                        insertBranch   = branch;
                        rInfo[0]       = insertBranch.Id;
                        insertTwoNodes = false;
                    }
                    // Insert the two children nodes
                    insertBranch.Insert((NodeId)info[0], (long)info[1],
                                        (Key)info[2],
                                        (NodeId)info[3], (long)info[4],
                                        insertIndex);
                    // Copy r_nfo to nfo
                    for (int p = 0; p < rInfo.Length; ++p)
                    {
                        info[p] = rInfo[p];
                    }

                    // Adjust the left key reference if necessary
                    if (leftKey != null && insertIndex > 0)
                    {
                        insertBranch.SetKeyToLeft(leftKey, insertIndex);
                        leftKey = null;
                    }
                }
                else
                {
                    branch.SetChild((NodeId)info[0], childIndex);
                    info[0] = branch.Id;
                    branch.SetChildLeafElementCount(
                        branch.GetChildLeafElementCount(childIndex) + leafSize, childIndex);

                    // Adjust the left key reference if necessary
                    if (leftKey != null && childIndex > 0)
                    {
                        branch.SetKeyToLeft(leftKey, childIndex);
                        leftKey = null;
                    }
                }
            }             // For all elements in the stack,

            // At the end, if we still have a split then we make a new root and
            // adjust the stack accordingly
            if (insertTwoNodes)
            {
                TreeBranch newRoot = CreateBranch();
                newRoot.Set((NodeId)info[0], (long)info[1],
                            (Key)info[2],
                            (NodeId)info[3], (long)info[4]);
                RootNodeId = newRoot.Id;
                if (TreeHeight != -1)
                {
                    TreeHeight = TreeHeight + 1;
                }
            }
            else
            {
                RootNodeId = (NodeId)info[0];
            }

            // Now reset the position,
            Reset();
            SetupForPosition(newKey, curAbsolutePos);
        }
예제 #25
0
        public void MoveLastHalfInto(TreeBranch dest)
        {
            int midpoint = children.Length/2;

            // Check mutable
            CheckReadOnly();
            dest.CheckReadOnly();

            // Check this is full
            if (!IsFull)
                throw new InvalidOperationException("Branch node is not full.");

            // Check destination is empty
            if (!dest.IsEmpty)
                throw new ArgumentException("Destination branch node is not empty.");

            // Copy,
            Array.Copy(children, midpoint + 1, dest.children, 0, midpoint - 1);

            // New child count in each branch node.
            int newChildCount = MaxChildCount/2;

            // Set the size of this and the destination node
            childrenCount = newChildCount;
            dest.childrenCount = newChildCount;
        }
예제 #26
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)
        }
예제 #27
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;
        }
예제 #28
0
 public HeapTreeBranch(TreeSystemTransaction transaction, NodeId nodeId, TreeBranch branch, int maxChildrenCount)
     : base(nodeId, branch, maxChildrenCount)
 {
     this.transaction = transaction;
 }
예제 #29
0
파일: TreeBranch.cs 프로젝트: ikvm/cloudb
        public Key Merge(TreeBranch right, Key midValue)
        {
            CheckReadOnly();
            right.CheckReadOnly();

            // How many elements in total?
            int total_elements = ChildCount + right.ChildCount;
            // If total elements is smaller than max size,
            if (total_elements <= MaxSize) {
                // Move all the elements into this node,
                int dest_p = childCount * 4;
                int right_len = (right.childCount * 4) - 2;
                Array.Copy(right.children, 0, children, dest_p, right_len);
                children[dest_p - 2] = midValue.GetEncoded(1);
                children[dest_p - 1] = midValue.GetEncoded(2);
                // Update children_count
                childCount += right.childCount;
                right.childCount = 0;
                return null;
            } else {
                long new_midpoint_value1, new_midpoint_value2;

                // Otherwise distribute between the nodes,
                int max_shift = (MaxSize + right.MaxSize) - total_elements;
                if (max_shift <= 2) {
                    return midValue;
                }
                int min_threshold = MaxSize / 2;
                //      final int half_total_elements = total_elements / 2;
                if (ChildCount < right.ChildCount) {
                    // Shift elements from right to left
                    // The amount to move that will leave the right node at min threshold
                    int count = Math.Min(right.ChildCount - min_threshold, max_shift);
                    int dest_p = ChildCount * 4;
                    int right_len = (count * 4) - 2;
                    Array.Copy(right.children, 0, children, dest_p, right_len);
                    // Redistribute the right elements
                    int right_redist = (count * 4);
                    // The midpoint value becomes the extent shifted off the end
                    new_midpoint_value1 = right.children[right_redist - 2];
                    new_midpoint_value2 = right.children[right_redist - 1];
                    // Shift the right child
                    Array.Copy(right.children, right_redist, right.children, 0,
                                     right.children.Length - right_redist);
                    children[dest_p - 2] = midValue.GetEncoded(1);
                    children[dest_p - 1] = midValue.GetEncoded(2);
                    childCount += count;
                    right.childCount -= count;

                } else {
                    // Shift elements from left to right
                    // The amount to move that will leave the left node at min threshold
                    int count = Math.Min(MaxSize - min_threshold, max_shift);
                    //        int count = Math.min(half_total_elements - right.size(), max_shift);

                    // Make room for these elements
                    int right_redist = (count * 4);
                    Array.Copy(right.children, 0, right.children, right_redist,
                                     right.children.Length - right_redist);
                    int src_p = (ChildCount - count) * 4;
                    int left_len = (count * 4) - 2;
                    Array.Copy(children, src_p, right.children, 0, left_len);
                    right.children[right_redist - 2] = midValue.GetEncoded(1);
                    right.children[right_redist - 1] = midValue.GetEncoded(2);
                    // The midpoint value becomes the extent shifted off the end
                    new_midpoint_value1 = children[src_p - 2];
                    new_midpoint_value2 = children[src_p - 1];
                    // Update children counts
                    childCount -= count;
                    right.childCount += count;
                }

                return new Key(new_midpoint_value1, new_midpoint_value2);
            }
        }