Пример #1
0
 private void EnsureCorrectBounds()
 {
     if (transaction.updateVersion > version)
     {
         // If version is -1, we force a key position lookup. Version is -1
         // when the range is created or it undergoes a large structural change.
         if (version == -1)
         {
             // Calculate absolute upper bound,
             end = transaction.AbsKeyEndPosition(upperKey);
             // Calculate the lower bound,
             start = transaction.AbsKeyEndPosition(lowerKey);
         }
         else
         {
             if (upperKey.CompareTo(transaction.lowestSizeChangedKey) >= 0)
             {
                 // Calculate absolute upper bound,
                 end = transaction.AbsKeyEndPosition(upperKey);
             }
             if (lowerKey.CompareTo(transaction.lowestSizeChangedKey) > 0)
             {
                 // Calculate the lower bound,
                 start = transaction.AbsKeyEndPosition(lowerKey);
             }
         }
         // Reset the stack and set the version to the most recent
         stack.Reset();
         version = transaction.updateVersion;
     }
 }
Пример #2
0
            public IDataFile GetFile(Key key, FileAccess access)
            {
                transaction.CheckErrorState();
                try {
                    // Check the key is within range,
                    if (key.CompareTo(lowerKey) < 0 ||
                        key.CompareTo(upperKey) > 0)
                    {
                        throw new IndexOutOfRangeException("Key out of bounds");
                    }

                    return(GetFile(key, access));
                } catch (OutOfMemoryException e) {
                    throw transaction.HandleMemoryException(e);
                }
            }
 private void EnsureCorrectBounds()
 {
     if (transaction.updateVersion > version)
     {
         // If version is -1, we force a key position lookup.  Version is -1
         // when the file is created or it undergoes a large structural change
         // such as a copy.
         if (version == -1 || key.CompareTo(transaction.lowestSizeChangedKey) >= 0)
         {
             long[] bounds = transaction.GetDataFileBounds(key);
             start = bounds[0];
             end   = bounds[1];
         }
         else
         {
             // If version doesn't equal -1, and this key is lower than the lowest
             // size changed key, then 'start' and 'end' should be correct.
         }
         // Reset the stack and set the version to the most recent
         stack.Reset();
         version = transaction.updateVersion;
     }
 }
Пример #4
0
        public int IndexOfChild(Key key, long offset)
        {
            if (offset >= 0)
            {
                int  sz         = ChildCount;
                long leftOffset = 0;
                for (int i = 0; i < sz; ++i)
                {
                    leftOffset += GetChildLeafElementCount(i);
                    // If the relative point must be within this child
                    if (offset < leftOffset)
                    {
                        return(i);
                    }

                    // This is a boundary condition, we need to use the key to work out
                    // which child to take
                    if (offset == leftOffset)
                    {
                        // If the end has been reached,
                        if (i == sz - 1)
                        {
                            return(i);
                        }

                        Key keyVal = GetKey(i + 1);
                        int n      = keyVal.CompareTo(key);
                        // If the key being inserted is less than the new leaf node,
                        if (n > 0)
                        {
                            // Go left,
                            return(i);
                        }

                        // Otherwise go right
                        return(i + 1);
                    }
                }
            }

            return(-1);
        }
Пример #5
0
        private long KeyEndPosition(Key key)
        {
            Key leftKey = Key.Head;
            int curHeight = 1;
            long leftOffset = 0;
            long nodeTotalSize = -1;
            ITreeNode node = FetchNode(RootNodeId);

            while (true) {
                // Is the node a leaf?
                if (node is TreeLeaf) {
                    treeHeight = curHeight;
                    break;
                }

                // Must be a branch,
                TreeBranch branch = (TreeBranch) node;
                // We ask the node for the child sub-tree that will contain this node
                int childIndex = branch.SearchLast(key);
                // Child will be in this subtree
                long childOffset = branch.GetChildOffset(childIndex);
                NodeId childNodeId = branch.GetChild(childIndex);
                nodeTotalSize = branch.GetChildLeafElementCount(childIndex);
                // Get the left key of the branch if we can
                if (childIndex > 0) {
                    leftKey = branch.GetKey(childIndex);
                }
                // Update left_offset
                leftOffset += childOffset;

                // Ok, if we know child_node_ref is a leaf,
                if (curHeight + 1 == treeHeight) {
                    break;
                }

                // Otherwise, descend to the child and repeat
                node = FetchNode(childNodeId);
                ++curHeight;
            }

            // Ok, we've reached the end of the tree,
            // 'left_key' will be the key of the node we are on,
            // 'node_total_size' will be the size of the node,

            // If the key matches,
            int c = key.CompareTo(leftKey);
            if (c == 0)
                return leftOffset + nodeTotalSize;

            // If the searched for key is less than this
            if (c < 0)
                return -(leftOffset + 1);

            // If this key is greater, relative offset is at the end of this node.

            //if (c > 0) {
            return -((leftOffset + nodeTotalSize) + 1);
        }
Пример #6
0
        private long[] GetDataFileBounds(Key key)
        {
            Key leftKey = Key.Head;
            int curHeight = 1;
            long leftOffset = 0;
            long nodeTotalSize = -1;
            ITreeNode node = FetchNode(RootNodeId);
            TreeBranch lastBranch = (TreeBranch) node;
            int childIndex = -1;

            while (true) {
                // Is the node a leaf?
                if (node is TreeLeaf) {
                    treeHeight = curHeight;
                    break;
                }

                // Must be a branch,
                TreeBranch branch = (TreeBranch) node;
                // We ask the node for the child sub-tree that will contain this node
                childIndex = branch.SearchLast(key);
                // Child will be in this subtree
                long childOffset = branch.GetChildOffset(childIndex);
                nodeTotalSize = branch.GetChildLeafElementCount(childIndex);
                // Get the left key of the branch if we can
                if (childIndex > 0) {
                    leftKey = branch.GetKey(childIndex);
                }
                // Update left_offset
                leftOffset += childOffset;
                lastBranch = branch;

                // Ok, if we know child_node_ref is a leaf,
                if (curHeight + 1 == treeHeight) {
                    break;
                }

                // Otherwise, descend to the child and repeat
                NodeId childNodeId = branch.GetChild(childIndex);
                node = FetchNode(childNodeId);
                ++curHeight;
            }

            // Ok, we've reached the leaf node on the search,
            // 'left_key' will be the key of the node we are on,
            // 'node_total_size' will be the size of the node,
            // 'last_branch' will be the branch immediately above the leaf
            // 'child_i' will be the offset into the last branch we searched

            long endPos;

            // If the key matches,
            int c = key.CompareTo(leftKey);
            if (c == 0) {
                endPos = leftOffset + nodeTotalSize;
            }
                // If the searched for key is less than this
            else if (c < 0) {
                endPos = -(leftOffset + 1);
            }
                // If this key is greater, relative offset is at the end of this node.
            else {
                //if (c > 0) {
                endPos = -((leftOffset + nodeTotalSize) + 1);
            }

            // If the key doesn't exist return the bounds as the position data is
            // entered.
            if (endPos < 0) {
                long p = -(endPos + 1);
                return new long[] {p, p};
            }

            // Now we have the end position of a key that definitely exists, we can
            // query the parent branch and see if we can easily find the record
            // start.

            // Search back through the keys until we find a key that is different,
            // which is the start bounds of the key,
            long predictedStartPos = endPos - nodeTotalSize;
            for (int i = childIndex - 1; i > 0; --i) {
                Key k = lastBranch.GetKey(i);
                if (key.CompareTo(k) == 0) {
                    // Equal,
                    predictedStartPos = predictedStartPos - lastBranch.GetChildLeafElementCount(i);
                } else {
                    // Not equal
                    if (predictedStartPos > endPos) {
                        throw new ApplicationException("Assertion failed: (1) start_pos > end_pos");
                    }
                    return new long[] {predictedStartPos, endPos};
                }
            }

            // Otherwise, find the end position of the previous key through a tree
            // search
            Key previousKey = PreviousKeyOrder(key);
            long startPos = AbsKeyEndPosition(previousKey);

            if (startPos > endPos) {
                throw new ApplicationException("Assertion failed: (2) start_pos > end_pos");
            }
            return new long[] {startPos, endPos};
        }