예제 #1
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);
        }
예제 #2
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);
        }