/// <summary>
        /// Splits this node into two internal nodes, creating a new node for the right-hand (upper) half of the keys
        /// </summary>
        /// <param name="txnId"></param>
        /// <param name="rightNodePage">The new page reserved to receive the newly created internal node</param>
        /// <param name="splitKey">Receives the value of the key used for the split</param>
        /// <returns>The new right-hand node</returns>
        public IInternalNode Split(ulong txnId, IPage rightNodePage, out byte[] splitKey)
        {
#if DEBUG_BTREE
            _config.BTreeDebug("InternalNode.Split. Id={0}. Structure Before: {1}", PageId, Dump());
#endif
            EnsureWriteable(txnId);
            var splitIndex = _config.InternalSplitIndex;
            splitKey = GetKey(splitIndex);
            rightNodePage.SetData(_page.Data, KeyOffset(splitIndex + 1),
                                  KeyOffset(0),
                                  (KeyCount - (splitIndex + 1)) * _config.KeySize);
            var pointerCopyStart  = PointerOffset(splitIndex + 1);
            var pointerCopyLength = (KeyCount - splitIndex) * 8;
            rightNodePage.SetData(_page.Data, pointerCopyStart,
                                  PointerOffset(0),
                                  pointerCopyLength);
            var rightNodeKeyCount = KeyCount - (splitIndex + 1);
            rightNodePage.SetData(BitConverter.GetBytes(~rightNodeKeyCount), 0, 0, 4);
            var rightNode = new InternalNode(rightNodePage, rightNodeKeyCount, _config);
            KeyCount = splitIndex;
#if DEBUG_BTREE
            _config.BTreeDebug("InternalNode.Split. Structure After: Id={0} {1}\nRight Node After: Id={2} {3}",
                               PageId, Dump(), rightNode.PageId, rightNode.Dump());
#endif
            return(rightNode);
        }
        /// <summary>
        /// Splits this node into two internal nodes, creating a new node for the right-hand (upper) half of the keys
        /// </summary>
        /// <param name="txnId"></param>
        /// <param name="rightNodePage">The new page reserved to receive the newly created internal node</param>
        /// <param name="splitKey">Receives the value of the key used for the split</param>
        /// <returns>The new right-hand node</returns>
        public IInternalNode Split(ulong txnId, IPage rightNodePage, out byte[] splitKey)
        {
#if DEBUG_BTREE
            _config.BTreeDebug("InternalNode.Split. Id={0}. Structure Before: {1}", PageId, Dump());
#endif
            EnsureWriteable(txnId);
            var splitIndex = _config.InternalSplitIndex;
            splitKey = GetKey(splitIndex);
            rightNodePage.SetData(_page.Data, KeyOffset(splitIndex + 1),
                                  KeyOffset(0),
                                  (KeyCount - (splitIndex + 1))*_config.KeySize);
            var pointerCopyStart = PointerOffset(splitIndex + 1);
            var pointerCopyLength = (KeyCount - splitIndex)*8;
            rightNodePage.SetData(_page.Data, pointerCopyStart,
                                  PointerOffset(0),
                                  pointerCopyLength);
            var rightNodeKeyCount = KeyCount - (splitIndex + 1);
            rightNodePage.SetData(BitConverter.GetBytes(~rightNodeKeyCount), 0, 0, 4);
            var rightNode = new InternalNode(rightNodePage, rightNodeKeyCount, _config);
            KeyCount = splitIndex;
#if DEBUG_BTREE
            _config.BTreeDebug("InternalNode.Split. Structure After: Id={0} {1}\nRight Node After: Id={2} {3}",
                PageId, Dump(), rightNode.PageId, rightNode.Dump());
#endif
            return rightNode;
        }