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