示例#1
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);
 }
示例#2
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);
        }
            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;
                        }
                    }
                }
            }
示例#4
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);
 }