Пример #1
0
 public TreeSystemStack(TreeSystemTransaction ts)
 {
     this.ts = ts;
     stackSize = 0;
     stack = new long[StackFrameSize*13];
     currentLeaf = null;
     currentLeafKey = null;
     leafOffset = 0;
 }
Пример #2
0
 public TreeSystemStack(TreeSystemTransaction ts)
 {
     this.ts        = ts;
     stackSize      = 0;
     stack          = new long[StackFrameSize * 13];
     currentLeaf    = null;
     currentLeafKey = null;
     leafOffset     = 0;
 }
Пример #3
0
 public HeapTreeLeaf(TreeSystemTransaction transaction, NodeId nodeId, TreeLeaf toCopy, int capacity)
 {
     this.nodeId      = nodeId;
     size             = toCopy.Length;
     this.transaction = transaction;
     // Copy the data into an array in this leaf.
     data = new byte[capacity];
     toCopy.Read(0, data, 0, size);
 }
Пример #4
0
 public void AddSpaceAfter(Key key, long spaceToAdd)
 {
     while (spaceToAdd > 0)
     {
         // Create an empty sparse node
         TreeLeaf emptyLeaf = CreateSparseLeaf(key, 0, spaceToAdd);
         InsertLeaf(key, emptyLeaf, false);
         spaceToAdd -= emptyLeaf.Length;
     }
 }
Пример #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
        public void SplitLeaf(Key key, long position)
        {
            UnfreezeStack();
            TreeLeaf sourceLeaf = CurrentLeaf;
            int      splitPoint = LeafOffset;
            // The amount of data we are copying from the current key.
            int amount = sourceLeaf.Length - splitPoint;
            // Create a new empty node
            TreeLeaf emptyLeaf = CreateLeaf(key);

            emptyLeaf.SetLength(amount);
            // Copy the data at the end of the leaf into a buffer
            byte[] buf = new byte[amount];
            sourceLeaf.Read(splitPoint, buf, 0, amount);
            // And write it out to the new leaf
            emptyLeaf.Write(0, buf, 0, amount);
            // Set the new size of the node
            sourceLeaf.SetLength(splitPoint);
            // Update the stack properties
            UpdateStackProperties(-amount);
            // And insert the new leaf after
            InsertLeaf(key, emptyLeaf, false);
        }
Пример #8
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;
        }
Пример #9
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);
        }
Пример #10
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)
        }
Пример #11
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();
            }
        }
Пример #12
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);
        }
Пример #13
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);
        }
Пример #14
0
 public void Reset()
 {
     StackClear();
     currentLeaf    = null;
     currentLeafKey = null;
 }
            private void CopyDataTo(long position, DataFile targetDataFile, long targetPosition, long size)
            {
                // If transactions are the same (data is being copied within the same
                // transaction context).
                TreeSystemStack targetStack;
                TreeSystemStack sourceStack;
                // Keys
                Key targetKey = targetDataFile.key;
                Key sourceKey = key;

                bool modifyPosOnShift = false;

                if (targetDataFile.Transaction == Transaction)
                {
                    // We set the source and target stack to the same
                    sourceStack = targetDataFile.stack;
                    targetStack = sourceStack;
                    // If same transaction and target_position is before the position we
                    // set the modify_pos_on_shift boolean.  This will update the absolute
                    // position when data is copied.
                    modifyPosOnShift = (targetPosition <= position);
                }
                else
                {
                    // Otherwise, set the target stack to the target file's stack
                    sourceStack = stack;
                    targetStack = targetDataFile.stack;
                }


                // Compact the key we are copying from, and in the destination,
                transaction.CompactNodeKey(sourceKey);
                targetDataFile.CompactNodeKey(targetKey);


                // The process works as follows;
                // 1. If we are not positioned at the start of a leaf, copy all data up
                //    to the next leaf to the target.
                // 2. Split the target leaf at the new position if the leaf can be
                //    split into 2 leaf nodes.
                // 3. Copy every full leaf to the target as a new leaf element.
                // 4. If there is any remaining data to copy, insert it into the target.

                // Set up for the position
                sourceStack.SetupForPosition(sourceKey, position);
                // If we aren't at the start of the leaf, then copy the data to the
                // target.
                int leafOff = sourceStack.LeafOffset;

                if (leafOff > 0)
                {
                    // We copy the remaining data in the leaf to the target
                    // The amount of data to copy from the leaf to the target
                    int to_copy = (int)Math.Min(size, sourceStack.LeafSize - leafOff);
                    if (to_copy > 0)
                    {
                        // Read into a buffer
                        byte[] buf = new byte[to_copy];
                        sourceStack.CurrentLeaf.Read(leafOff, buf, 0, to_copy);
                        // Make enough room to insert this data in the target
                        targetStack.ShiftData(targetKey, targetPosition, to_copy);
                        // Update the position if necessary
                        if (modifyPosOnShift)
                        {
                            position += to_copy;
                        }
                        // Write the data to the target stack
                        targetStack.WriteFrom(targetKey, targetPosition, buf, 0, to_copy);
                        // Increment the pointers
                        position       += to_copy;
                        targetPosition += to_copy;
                        size           -= to_copy;
                    }
                }

                // If this is true, the next iteration will use the byte buffer leaf copy
                // routine.  Set if a link to a node failed for whatever reason.
                bool useByteBufferCopyForNext = false;

                // The loop
                while (size > 0)
                {
                    // We now know we are at the start of a leaf with data left to copy.
                    sourceStack.SetupForPosition(sourceKey, position);
                    // Lets assert that
                    if (sourceStack.LeafOffset != 0)
                    {
                        throw new ApplicationException("Expected to be at the start of a leaf.");
                    }

                    // If the source is a heap node or we are copying less than the data
                    // that's in the leaf then we use the standard shift and write.
                    TreeLeaf currentLeaf = sourceStack.CurrentLeaf;
                    // Check the leaf size isn't 0
                    if (currentLeaf.Length <= 0)
                    {
                        throw new ApplicationException("Leaf is empty.");
                    }
                    // If the remaining copy is less than the size of the leaf we are
                    // copying from, we just do a byte array copy
                    if (useByteBufferCopyForNext || size < currentLeaf.Length)
                    {
                        // Standard copy through a byte[] buf,
                        useByteBufferCopyForNext = false;
                        int toCopy = (int)Math.Min(size, currentLeaf.Length);
                        // Read into a buffer
                        byte[] buf = new byte[toCopy];
                        currentLeaf.Read(0, buf, 0, toCopy);
                        // Make enough room in the target
                        targetStack.ShiftData(targetKey, targetPosition, toCopy);
                        if (modifyPosOnShift)
                        {
                            position += toCopy;
                        }
                        // Write the data and finish
                        targetStack.WriteFrom(targetKey, targetPosition, buf, 0, toCopy);
                        // Update pointers
                        position       += toCopy;
                        targetPosition += toCopy;
                        size           -= toCopy;
                    }
                    else
                    {
                        // We need to copy a complete leaf node,
                        // If the leaf is on the heap, write it out
                        if (transaction.IsHeapNode(currentLeaf.Id))
                        {
                            sourceStack.WriteLeafOnly(sourceKey);
                            // And update any vars
                            currentLeaf = sourceStack.CurrentLeaf;
                        }

                        // Ok, source current leaf isn't on the heap, and we are copying a
                        // complete leaf node, so we are elegible to play with pointers to
                        // copy the data.
                        targetStack.SetupForPosition(targetKey, targetPosition);
                        bool insertNextBefore = false;
                        // Does the target key exist?
                        bool targetKeyExists = targetStack.CurrentLeafKey.Equals(targetKey);
                        if (targetKeyExists)
                        {
                            // If the key exists, is target_position at the end of the span?
                            insertNextBefore = targetStack.LeafOffset < targetStack.CurrentLeaf.Length;
                        }

                        // If target isn't currently on a boundary
                        if (!targetStack.IsAtEndOfKeyData &&
                            targetStack.LeafOffset != 0)
                        {
                            // If we aren't on a boundary we need to split the target leaf
                            targetStack.SplitLeaf(targetKey, targetPosition);
                        }
                        // If the key exists we set up the position to the previous left
                        // to insert the new leaf, otherwise we set it up to the default
                        // position to insert.

                        // Copy the leaf,
                        // Try to link to this leaf
                        bool linkSuccessful = TreeSystem.LinkLeaf(targetKey, currentLeaf.Id);
                        // If the link was successful,
                        if (linkSuccessful)
                        {
                            // Insert the leaf into the tree
                            targetStack.InsertLeaf(targetKey, currentLeaf, insertNextBefore);
                            // Update the pointers
                            int copiedSize = currentLeaf.Length;
                            // Update if we inserting stuff before
                            if (modifyPosOnShift)
                            {
                                position += copiedSize;
                            }
                            position       += copiedSize;
                            targetPosition += copiedSize;
                            size           -= copiedSize;
                        }
                        // If the link was not successful,
                        else
                        {
                            // We loop back and use the byte buffer copy,
                            useByteBufferCopyForNext = true;
                        }
                    }
                }
            }
Пример #16
0
 public void Reset()
 {
     StackClear();
     currentLeaf = null;
     currentLeafKey = null;
 }
Пример #17
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)
        }
Пример #18
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;
        }
Пример #19
0
 internal HeapTreeLeaf(ITransaction tran, long nodeId, TreeLeaf toCopy, int maxCapacity)
     : base()
 {
     this.nodeId = nodeId;
     this.size = toCopy.Length;
     this.tran = tran;
     // Copy the data into an array in this leaf.
     data = new byte[maxCapacity];
     toCopy.Read(0, data, 0, size);
 }