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; } }
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; } }
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); }
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); }
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}; }