예제 #1
0
 public TreeSystemStack(TreeSystemTransaction ts)
 {
     this.ts = ts;
     stackSize = 0;
     stack = new long[StackFrameSize*13];
     currentLeaf = null;
     currentLeafKey = null;
     leafOffset = 0;
 }
            internal DataFile(TreeSystemTransaction transaction, Key key, bool fileReadOnly)
            {
                stack = new TreeSystemStack(transaction);
                this.transaction = transaction;
                this.key = key;
                p = 0;

                version = -1;
                this.fileReadOnly = fileReadOnly;
                start = -1;
                end = -1;
            }
예제 #3
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};
        }
예제 #4
0
 private void CompactNodeKey(Key key)
 {
     Object[] mergeBuffer = new Object[5];
     // Compact the node,
     CompactNode(Key.Head, RootNodeId, mergeBuffer, key, key);
 }
예제 #5
0
 private long AbsKeyEndPosition(Key key)
 {
     long pos = KeyEndPosition(key);
     return (pos < 0) ? -(pos + 1) : pos;
 }
예제 #6
0
 protected IDataFile UnsafeGetDataFile(Key key, FileAccess mode)
 {
     // Check if the transaction disposed,
     if (disposed) {
         throw new InvalidOperationException("Transaction is disposed");
     }
     // Create and return the data file object for this key.
     return new DataFile(this, key, (mode == FileAccess.Read));
 }
예제 #7
0
 internal TreeLeaf CreateLeaf(Key key)
 {
     return NodeHeap.CreateLeaf(this, key, MaxLeafByteSize);
 }
예제 #8
0
        public IDataRange GetRange(Key minKey, Key maxKey)
        {
            CheckErrorState();
            try {

                // All key types greater than 0x07F80 are reserved for system data
                if (OutOfUserDataRange(minKey) ||
                    OutOfUserDataRange(maxKey)) {
                    throw new ArgumentException("Key is reserved for system data");
                }

                // Use the unsafe method after checks have been performed
                return UnsafeGetDataRange(minKey, maxKey);

            } catch (OutOfMemoryException e) {
                throw HandleMemoryException(e);
            }
        }
예제 #9
0
        public bool LinkLeaf(Key key, long reference)
        {
            // If the node is a special node, then we don't need to reference count it.
            if ((reference & 0x01000000000000000L) != 0)
                return true;

            try {
                store.LockForWrite();

                // Get the area as a MutableArea object
                IMutableArea leafArea = store.GetMutableArea(reference);

                // We synchronize over a reference count lock
                // (Pending: should we lock by area instead?  Not sure it will be
                //  worth the complexity of a more fine grained locking mechanism for the
                //  performance improvements - maybe we should implement a locking
                //  mechanism inside IMutableArea).
                lock (refCountLock) {
                    // Assert this is a leaf
                    leafArea.Position = 0;
                    short nodeType = leafArea.ReadInt2();
                    if (nodeType != LeafType)
                        throw new IOException("Can only link to a leaf node.");

                    leafArea.Position = 4;
                    int refCount = leafArea.ReadInt4();
                    // If reference counter is near overflowing, return false,
                    if (refCount > Int32.MaxValue - 8)
                        return false;

                    leafArea.Position = 4;
                    leafArea.WriteInt4(refCount + 1);
                }

                return true;
            } finally {
                store.UnlockForWrite();
            }
        }
예제 #10
0
파일: TreeBranch.cs 프로젝트: ikvm/cloudb
 internal void SetKeyValueToLeft(Key k, int child_i)
 {
     SetKeyValueToLeft(k.GetEncoded(1), k.GetEncoded(2), child_i);
 }
예제 #11
0
파일: TreeBranch.cs 프로젝트: ikvm/cloudb
        public int SearchLast(Key key)
        {
            int low = 1;
            int high = ChildCount - 1;

            while (true) {

                if (high - low <= 2) {
                    for (int i = high; i >= low; --i) {
                        int cmp1 = GetKey(i).CompareTo(key);
                        if (cmp1 <= 0)
                            return i;
                    }
                    return low - 1;
                }

                int mid = (low + high) / 2;
                int cmp = GetKey(mid).CompareTo(key);

                if (cmp < 0) {
                    low = mid + 1;
                } else if (cmp > 0) {
                    high = mid - 1;
                } else {
                    low = mid;
                }
            }
        }
예제 #12
0
파일: TreeBranch.cs 프로젝트: ikvm/cloudb
        public int SearchFirst(Key key)
        {
            int low = 1;
            int high = ChildCount - 1;

            while (true) {
                if (high - low <= 2) {
                    for (int i = low; i <= high; ++i) {
                        int cmp1 = GetKey(i).CompareTo(key);
                        if (cmp1 > 0)
                            // Value is less than extent so take the left route
                            return i - 1;
                        if (cmp1 == 0)
                            // Equal so need to search left and right of the extent
                            // This is (-(i + 1 - 1))
                            return -i;
                    }
                    // Value is greater than extent so take the right route
                    return high;
                }

                int mid = (low + high) / 2;
                int cmp = GetKey(mid).CompareTo(key);

                if (cmp < 0) {
                    low = mid + 1;
                } else if (cmp > 0) {
                    high = mid - 1;
                } else {
                    high = mid;
                }
            }
        }
예제 #13
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()");
        }
예제 #14
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);
            }
        }
예제 #15
0
파일: TreeBranch.cs 프로젝트: ikvm/cloudb
        public int IndexOfChild(Key key, long offset)
        {
            if (offset >= 0) {
                int sz = ChildCount;
                long left_offset = 0;
                for (int i = 0; i < sz; ++i) {
                    left_offset += GetChildLeafElementCount(i);
                    // If the relative point must be within this child
                    if (offset < left_offset)
                        return i;

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

                        Key key_val = GetKey(i + 1);
                        int n = key_val.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;
        }
예제 #16
0
        public bool DataFileExists(Key key)
        {
            CheckErrorState();

            try {

                // All key types above 0x07F80 are reserved for system data
                if (OutOfUserDataRange(key)) {
                    throw new ApplicationException("Key is reserved for system data.");
                }
                // If the key exists, the position will be >= 0
                return KeyEndPosition(key) >= 0;

            } catch (IOException e) {
                throw HandleIOException(e);
            } catch (OutOfMemoryException e) {
                throw HandleMemoryException(e);
            }
        }
예제 #17
0
        public IDataFile GetFile(Key key, FileAccess access)
        {
            CheckErrorState();
            try {

                // All key types greater than 0x07F80 are reserved for system data
                if (OutOfUserDataRange(key)) {
                    throw new ArgumentException("Key is reserved for system data", "key");
                }

                // Use the unsafe method after checks have been performed
                return UnsafeGetDataFile(key, access);

            } catch (OutOfMemoryException e) {
                throw HandleMemoryException(e);
            }
        }
예제 #18
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;
        }
예제 #19
0
        public void PreFetchKeys(Key[] keys)
        {
            CheckErrorState();

            try {
                foreach (Key k in keys) {
                    prefetchKeymap.Add(k, "");
                }
            } catch (OutOfMemoryException e) {
                throw HandleMemoryException(e);
            }
        }
예제 #20
0
        private NodeId LastUncachedNode(Key key)
        {
            int curHeight = 1;
            NodeId childNodeId = RootNodeId;
            TreeBranch lastBranch = null;
            int childIndex = -1;

            // How this works;
            // * Descend through the tree and try to find the last node of the
            //   previous key.
            // * If a node is encoutered that is not cached locally, return it.
            // * If a leaf is reached, return the next leaf entry from the previous
            //   branch (this should be the first node of key).

            // This does not perform completely accurately for tree edges but this
            // should not present too much of a problem.

            key = PreviousKeyOrder(key);

            // Try and fetch the node, if it's not available locally then return the
            // child node ref
            ITreeNode node = FetchNodeIfLocallyAvailable(childNodeId);
            if (node == null) {
                return childNodeId;
            }

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

                // Must be a branch,
                TreeBranch branch = (TreeBranch) node;
                lastBranch = branch;
                // We ask the node for the child sub-tree that will contain this node
                childIndex = branch.SearchLast(key);
                // Child will be in this subtree
                childNodeId = branch.GetChild(childIndex);

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

                // Try and fetch the node, if it's not available locally then return
                // the child node ref
                node = FetchNodeIfLocallyAvailable(childNodeId);
                if (node == null) {
                    return childNodeId;
                }
                // Otherwise, descend to the child and repeat
                ++curHeight;
            }

            // Ok, we've reached the end of the tree,

            // Fetch the next child_i if we are not at the end already,
            if (childIndex + 1 < lastBranch.ChildCount) {
                childNodeId = lastBranch.GetChild(childIndex);
            }

            // If the child node is not a heap node, and is not available locally then
            // return it.
            if (!IsHeapNode(childNodeId) &&
                !treeStore.IsNodeAvailable(childNodeId)) {
                return childNodeId;
            }

            // The key is available locally,
            return null;
        }
예제 #21
0
        internal TreeLeaf CreateSparseLeaf(Key key, byte value, long length)
        {
            // Make sure the sparse leaf doesn't exceed the maximum leaf size
            int sparseSize = (int)Math.Min(length, (long)MaxLeafByteSize);
            // Make sure the sparse leaf doesn't exceed the maximum size of the
            // sparse leaf object.
            sparseSize = Math.Min(65535, sparseSize);

            // Create node reference for a special sparse node,
            NodeId nodeId = NodeId.CreateSpecialSparseNode(value, length);

            return (TreeLeaf)FetchNode(nodeId);
        }
예제 #22
0
        private int MergeNodes(Key middleKeyValue, NodeId leftId, NodeId rightId, Key leftLeftKey, Key rightLeftKey, object[] mergeBuffer)
        {
            // Fetch the nodes,
            ITreeNode leftNode = FetchNode(leftId);
            ITreeNode rightNode = FetchNode(rightId);
            // Are we merging branches or leafs?
            if (leftNode is TreeLeaf) {
                TreeLeaf lleaf = (TreeLeaf) leftNode;
                TreeLeaf rleaf = (TreeLeaf) rightNode;
                // Check the keys are identical,
                if (leftLeftKey.Equals(rightLeftKey)) {
                    // 80% capacity on a leaf
                    int capacity80 = (int) (0.80*MaxLeafByteSize);
                    // True if it's possible to full merge left and right into a single
                    bool fullyMerge = lleaf.Length + rleaf.Length <= MaxLeafByteSize;
                    // Only proceed if the leafs can be fully merged or the left is less
                    // than 80% full,
                    if (fullyMerge || lleaf.Length < capacity80) {
                        // Move elements from the right leaf to the left leaf so that either
                        // the right node becomes completely empty or if that's not possible
                        // the left node is 80% full.
                        if (fullyMerge) {
                            // We can fit both nodes into a single node so merge into a single
                            // node,
                            TreeLeaf nleaf = (TreeLeaf) UnfreezeNode(lleaf);
                            byte[] copyBuf = new byte[rleaf.Length];
                            rleaf.Read(0, copyBuf, 0, copyBuf.Length);
                            nleaf.Write(nleaf.Length, copyBuf, 0, copyBuf.Length);

                            // Delete the right node,
                            DeleteNode(rleaf.Id);

                            // Setup the merge state
                            mergeBuffer[0] = nleaf.Id;
                            mergeBuffer[1] = (long) nleaf.Length;
                            return 1;
                        }

                        // Otherwise, we move bytes from the right leaf into the left
                        // leaf until it is 80% full,
                        int toCopy = capacity80 - lleaf.Length;
                        // Make sure we are copying at least 4 bytes and there are enough
                        // bytes available in the right leaf to make the copy,
                        if (toCopy > 4 && rleaf.Length > toCopy) {
                            // Unfreeze both the nodes,
                            TreeLeaf mlleaf = (TreeLeaf) UnfreezeNode(lleaf);
                            TreeLeaf mrleaf = (TreeLeaf) UnfreezeNode(rleaf);
                            // Copy,
                            byte[] copyBuf = new byte[toCopy];
                            mrleaf.Read(0, copyBuf, 0, toCopy);
                            mlleaf.Write(mlleaf.Length, copyBuf, 0, toCopy);
                            // Shift the data in the right leaf,
                            mrleaf.Shift(toCopy, -toCopy);

                            // Return the merge state
                            mergeBuffer[0] = mlleaf.Id;
                            mergeBuffer[1] = (long) mlleaf.Length;
                            mergeBuffer[2] = rightLeftKey;
                            mergeBuffer[3] = mrleaf.Id;
                            mergeBuffer[4] = (long) mrleaf.Length;
                            return 2;
                        }
                    }
                } // leaf keys unequal
            } else if (leftNode is TreeBranch) {
                // Merge branches,
                TreeBranch lbranch = (TreeBranch) leftNode;
                TreeBranch rbranch = (TreeBranch) rightNode;

                int capacity75 = (int) (0.75*MaxBranchSize);
                // True if it's possible to full merge left and right into a single
                bool fullyMerge = lbranch.ChildCount + rbranch.ChildCount <= MaxBranchSize;

                // Only proceed if left is less than 75% full,
                if (fullyMerge || lbranch.ChildCount < capacity75) {
                    // Move elements from the right branch to the left leaf only if the
                    // branches can be completely merged into a node
                    if (fullyMerge) {
                        // We can fit both nodes into a single node so merge into a single
                        // node,
                        TreeBranch nbranch = (TreeBranch) UnfreezeNode(lbranch);
                        // Merge,
                        nbranch.MergeLeft(rbranch, middleKeyValue, rbranch.ChildCount);

                        // Delete the right branch,
                        DeleteNode(rbranch.Id);

                        // Setup the merge state
                        mergeBuffer[0] = nbranch.Id;
                        mergeBuffer[1] = nbranch.LeafElementCount;
                        return 1;
                    }

                    // Otherwise, we move children from the right branch into the left
                    // branch until it is 75% full,
                    int toCopy = capacity75 - lbranch.ChildCount;
                    // Make sure we are copying at least 4 bytes and there are enough
                    // bytes available in the right leaf to make the copy,
                    if (toCopy > 2 && rbranch.ChildCount > toCopy + 3) {
                        // Unfreeze the nodes,
                        TreeBranch mlbranch = (TreeBranch) UnfreezeNode(lbranch);
                        TreeBranch mrbranch = (TreeBranch) UnfreezeNode(rbranch);
                        // And merge
                        Key newMiddleValue = mlbranch.MergeLeft(mrbranch, middleKeyValue, toCopy);

                        // Setup and return the merge state
                        mergeBuffer[0] = mlbranch.Id;
                        mergeBuffer[1] = mlbranch.LeafElementCount;
                        mergeBuffer[2] = newMiddleValue;
                        mergeBuffer[3] = mrbranch.Id;
                        mergeBuffer[4] = mrbranch.LeafElementCount;
                        return 2;
                    }
                }
            } else {
                throw new ApplicationException("Unknown node type.");
            }

            // Signifies no change to the branch,
            return 3;
        }
예제 #23
0
 protected IDataRange UnsafeGetDataRange(Key minKey, Key maxKey)
 {
     // Check if the transaction disposed,
     if (disposed) {
         throw new InvalidOperationException("Transaction is disposed");
     }
     // Create and return the data file object for this key.
     return new DataRange(this, minKey, maxKey);
 }
예제 #24
0
 private Key PreviousKeyOrder(Key key)
 {
     short type = key.Type;
     int secondary = key.Secondary;
     long primary = key.Primary;
     if (primary == Int64.MinValue) {
         // Should not use negative primary keys.
         throw new InvalidOperationException();
     }
     return new Key(type, secondary, primary - 1);
 }
예제 #25
0
        private void CompactNode(Key farLeft, NodeId id, object[] mergeBuffer, Key minBound, Key maxBound)
        {
            // If the ref is not on the heap, return the ref,
            if (!IsHeapNode(id))
                return;

            // Fetch the node,
            ITreeNode node = FetchNode(id);
            // If the node is a leaf, return the ref,
            if (node is TreeLeaf)
                return;

            // If the node is a branch,
            if (node is TreeBranch) {
                // Cast to a branch
                TreeBranch branch = (TreeBranch) node;

                // We ask the node for the child sub-tree that will contain the range
                // of this key
                int firstChildI = branch.SearchFirst(minBound);
                int lastChildI = branch.SearchLast(maxBound);

                // first_child_i may be negative which means a key reference is equal
                // to the key being searched, in which case we follow the left branch.
                if (firstChildI < 0) {
                    firstChildI = -(firstChildI + 1);
                }

                // Compact the children,
                for (int x = firstChildI; x <= lastChildI; ++x) {
                    // Change far left to represent the new far left node
                    Key newFarLeft = (x > 0) ? branch.GetKey(x) : farLeft;

                    // We don't change max_bound because it's not necessary.
                    CompactNode(newFarLeft, branch.GetChild(x), mergeBuffer, minBound, maxBound);
                }

                // The number of children in this branch,
                int sz = branch.ChildCount;

                // Now try and merge the compacted children,
                int i = firstChildI;
                // We must not let there be less than 3 children
                while (sz > 3 && i <= lastChildI - 1) {
                    // The left and right children nodes,
                    NodeId leftChildId = branch.GetChild(i);
                    NodeId rightChildId = branch.GetChild(i + 1);
                    // If at least one of them is a heap node we attempt to merge the
                    // nodes,
                    if (IsHeapNode(leftChildId) || IsHeapNode(rightChildId)) {
                        // Set the left left key and right left key of the references,
                        Key leftLeftKey = (i > 0) ? branch.GetKey(i) : farLeft;
                        Key rightLeftKey = branch.GetKey(i + 1);
                        // Attempt to merge the nodes,
                        int nodeResult = MergeNodes(branch.GetKey(i + 1),
                                                     leftChildId, rightChildId,
                                                     leftLeftKey, rightLeftKey,
                                                     mergeBuffer);
                        // If we merged into a single node then we update the left and
                        // delete the right
                        if (nodeResult == 1) {
                            branch.SetChild((NodeId) mergeBuffer[0], i);
                            branch.SetChildLeafElementCount((long) mergeBuffer[1], i);
                            branch.RemoveChild(i + 1);
                            // Reduce the size but don't increase i, because we may want to
                            // merge again.
                            --sz;
                            --lastChildI;
                        } else if (nodeResult == 2) {
                            // Two result but there was a change (the left was increased in
                            // size)
                            branch.SetChild((NodeId) mergeBuffer[0], i);
                            branch.SetChildLeafElementCount((long) mergeBuffer[1], i);
                            branch.SetKeyToLeft((Key) mergeBuffer[2], i + 1);
                            branch.SetChild((NodeId) mergeBuffer[3], i + 1);
                            branch.SetChildLeafElementCount((long) mergeBuffer[4], i + 1);
                            ++i;
                        } else {
                            // Otherwise, no change so skip to the next child,
                            ++i;
                        }
                    }
                        // left or right are not nodes on the heap so go to next,
                    else {
                        ++i;
                    }
                }
            }
        }
예제 #26
0
 public static bool OutOfUserDataRange(Key key)
 {
     // These types reserved for system use,
     if (key.Type >= (short) 0x07F80)
         return true;
     // Primary key has a reserved group of values at min value
     if (key.Primary <= Int64.MinValue + 16)
         return true;
     return false;
 }
예제 #27
0
        private Object[] DeleteFromLeaf(long leftOffset, NodeId leaf, long startPos, long endPos, Key inLeftKey)
        {
            Debug.Assert(startPos < endPos);

            TreeLeaf treeLeaf = (TreeLeaf) UnfreezeNode(FetchNode(leaf));
            const int leafStart = 0;
            int leafEnd = treeLeaf.Length;
            int delStart = (int) Math.Max(startPos - leftOffset, (long) leafStart);
            int delEnd = (int) Math.Min(endPos - leftOffset, (long) leafEnd);

            int removeAmount = delEnd - delStart;

            // Remove from the end point,
            treeLeaf.Shift(delEnd, -removeAmount);

            return new object[] {
                                    treeLeaf.Id,
                                    (long) removeAmount,
                                    inLeftKey, false
                                };
        }
예제 #28
0
        private TreeBranch RecurseRebalanceTree(long leftOffset, int height, NodeId nodeId, long absolutePosition, Key inLeftKey)
        {
            // Put the node in memory,
            TreeBranch branch = (TreeBranch) FetchNode(nodeId);

            int sz = branch.ChildCount;
            int i;
            long pos = leftOffset;
            // Find the first child i that contains the position.
            for (i = 0; i < sz; ++i) {
                long childElemCount = branch.GetChildLeafElementCount(i);
                // abs position falls within bounds,
                if (absolutePosition >= pos &&
                    absolutePosition < pos + childElemCount) {
                    break;
                }
                pos += childElemCount;
            }

            if (i > 0) {
                NodeId leftId = branch.GetChild(i - 1);
                NodeId rightId = branch.GetChild(i);

                // Only continue if both left and right are on the heap
                if (IsHeapNode(leftId) &&
                    IsHeapNode(rightId) &&
                    IsHeapNode(nodeId)) {

                    Key leftKey = (i - 1 == 0)
                                   	? inLeftKey
                                   	: branch.GetKey(i - 1);
                    Key rightKey = branch.GetKey(i);

                    // Perform the merge operation,
                    Key midKeyValue = rightKey;
                    object[] mergeBuffer = new Object[5];
                    int merge_result = MergeNodes(midKeyValue, leftId, rightId,
                                                  leftKey, rightKey, mergeBuffer);
                    if (merge_result == 1) {
                        branch.SetChild((NodeId) mergeBuffer[0], i - 1);
                        branch.SetChildLeafElementCount((long) mergeBuffer[1], i - 1);
                        branch.RemoveChild(i);
                    }
                        //
                    else if (merge_result == 2) {
                        branch.SetChild((NodeId) mergeBuffer[0], i - 1);
                        branch.SetChildLeafElementCount((long) mergeBuffer[1], i - 1);
                        branch.SetKeyToLeft((Key) mergeBuffer[2], i);
                        branch.SetChild((NodeId) mergeBuffer[3], i);
                        branch.SetChildLeafElementCount((long) mergeBuffer[4], i);
                    }
                }
            }

            // After merge, we don't know how the children will be placed, so we
            // do another search on the child to descend to,

            sz = branch.ChildCount;
            pos = leftOffset;
            // Find the first child i that contains the position.
            for (i = 0; i < sz; ++i) {
                long childElemCount = branch.GetChildLeafElementCount(i);
                // abs position falls within bounds,
                if (absolutePosition >= pos &&
                    absolutePosition < pos + childElemCount) {
                    break;
                }
                pos += childElemCount;
            }

            // Descend on 'i'
            ITreeNode descendChild = FetchNode(branch.GetChild(i));

            // Finish if we hit a leaf
            if (descendChild is TreeLeaf) {
                // End if we hit the leaf,
                return branch;
            }

            Key newLeftKey = (i == 0)
                               	? inLeftKey
                               	: branch.GetKey(i);

            // Otherwise recurse on the child,
            TreeBranch child_branch =
                RecurseRebalanceTree(pos, height + 1,
                                     descendChild.Id, absolutePosition,
                                     newLeftKey);

            // Make sure we unfreeze the branch
            branch = (TreeBranch) UnfreezeNode(branch);

            // Update the child,
            branch.SetChild(child_branch.Id, i);
            branch.SetChildLeafElementCount(child_branch.LeafElementCount, i);

            // And return this branch,
            return branch;
        }
예제 #29
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);
        }
예제 #30
0
        private Object[] RecurseRemoveBranches(long leftOffset, int height, NodeId node, long startPos, long endPos, Key inLeftKey)
        {
            // Do we know if this is a leaf node?
            if (treeHeight == height)
                return DeleteFromLeaf(leftOffset, node, startPos, endPos, inLeftKey);

            // Fetch the node,
            ITreeNode treeNode = FetchNode(node);
            if (treeNode is TreeLeaf) {
                // Leaf reach, so set the tree height and return
                treeHeight = height;
                return DeleteFromLeaf(leftOffset, node, startPos, endPos, inLeftKey);
            }

            // The amount removed,
            long removeCount = 0;

            // This is a branch,
            TreeBranch treeBranch = (TreeBranch) treeNode;
            treeBranch = (TreeBranch) UnfreezeNode(treeBranch);

            Key parentLeftKey = inLeftKey;

            // Find all the children branches between the bounds,
            int childCount = treeBranch.ChildCount;
            long pos = leftOffset;
            for (int i = 0; i < childCount && pos < endPos; ++i) {
                long childNodeSize = treeBranch.GetChildLeafElementCount(i);
                long nextPos = pos + childNodeSize;

                // Test if start_pos/end_pos bounds intersects with this child,
                if (startPos < nextPos && endPos > pos) {
                    // Yes, we intersect,

                    // Make sure the branch is on the heap,
                    NodeId childNode = treeBranch.GetChild(i);

                    // If we intersect entirely remove the child from the branch,
                    if (pos >= startPos && nextPos <= endPos) {
                        // Delete the child tree,
                        DeleteChildTree(height + 1, childNode);
                        removeCount += childNodeSize;

                        // If removing the first child, bubble up a new left_key
                        if (i == 0) {
                            parentLeftKey = treeBranch.GetKey(1);
                        }
                            // Otherwise parent left key doesn't change
                        else {
                            parentLeftKey = inLeftKey;
                        }

                        // Remove the child from the branch,
                        treeBranch.RemoveChild(i);
                        --i;
                        --childCount;
                    } else {
                        // We don't intersect entirely, so recurse on this,
                        // The left key
                        Key rLeftKey = (i == 0) ? inLeftKey : treeBranch.GetKey(i);

                        object[] rv = RecurseRemoveBranches(pos, height + 1, childNode, startPos, endPos, rLeftKey);
                        NodeId newChildRef = (NodeId) rv[0];
                        long removedInChild = (long) rv[1];
                        Key childLeftKey = (Key) rv[2];

                        removeCount += removedInChild;

                        // Update the child,
                        treeBranch.SetChild(newChildRef, i);
                        treeBranch.SetChildLeafElementCount(childNodeSize - removedInChild, i);
                        if (i == 0) {
                            parentLeftKey = childLeftKey;
                        } else {
                            treeBranch.SetKeyToLeft(childLeftKey, i);
                            parentLeftKey = inLeftKey;
                        }
                    }
                }

                // Next child in the branch,
                pos = nextPos;
            }

            // Return the reference and remove count,
            bool parentRebalance = (treeBranch.ChildCount <= 2);
            return new Object[] {
                                    treeBranch.Id, removeCount,
                                    parentLeftKey, parentRebalance
                                };
        }