Example #1
0
        /// <summary>
        /// 构造B+树存储头
        /// </summary>
        /// <returns></returns>
        private byte[] MakeHeader()
        {
            // 魔数前缀 | 版本 | 节点容量 | 键大小 | 根节点块序号 | 空闲块头序号
            // prefix | version | node size | key size | block number of root | block number of free list head
            byte[] header = new byte[HeaderSize];

            // 魔数前缀
            StoredConstants.TreeFileHeaderPrefix.CopyTo(header, 0);

            // 版本 1 Byte
            header[StoredConstants.TreeFileHeaderPrefix.Length] = Version;

            // 节点容量 4 Bytes
            int index = StoredConstants.TreeFileHeaderPrefix.Length + 1;

            StoredHelper.Store(this.NodeCapacity, header, index);
            index += StoredConstants.IntegerLength;

            // 键大小 4 Bytes
            StoredHelper.Store(this.KeyLength, header, index);
            index += StoredConstants.IntegerLength;

            // 根节点块序号 8 Bytes
            StoredHelper.Store(this.RootNodeBlockNumber, header, index);
            index += StoredConstants.LongLength;

            // 空闲块头序号 8 Bytes
            StoredHelper.Store(this.FreeBlockHeadNumber, header, index);
            index += StoredConstants.LongLength;

            return(header);
        }
Example #2
0
        /// <summary>
        /// 构造存储头
        /// </summary>
        /// <returns></returns>
        public byte[] MakeFileHeader()
        {
            // 魔数前缀长度 | 块的大小
            byte[] header = new byte[FileHeaderSize];

            // 魔数前缀
            FileHeaderPrefix.CopyTo(header, 0);

            // 块的大小 4 Bytes
            StoredHelper.Store(this.BlockSize, header, FileHeaderPrefix.Length);

            return(header);
        }
Example #3
0
        /// <summary>
        /// 构造存储头
        /// </summary>
        /// <returns></returns>
        public byte[] MakeFileHeader()
        {
            // 魔数前缀长度 | 块的大小 | 空闲列表头序号
            byte[] header = new byte[this.FileHeaderSize];

            // 魔数前缀
            FileHeaderPrefix.CopyTo(header, 0);
            int index = FileHeaderPrefix.Length;

            // 块的大小
            StoredHelper.Store(this.BlockSize, header, index);
            index += StoredConstants.IntegerLength;

            // 空闲列表头序号
            StoredHelper.Store(this.FreeBlockHead, header, index);
            index += StoredConstants.LongLength;

            return(header);
        }
Example #4
0
        /// <summary>
        /// 回收再利用指定序号的块
        /// </summary>
        /// <param name="blockNumber">指定序号</param>
        public void ReclaimBlock(long blockNumber)
        {
            int freeSize = 1 + StoredConstants.LongLength;

            byte[] block = new byte[freeSize];

            // it better not already be marked free
            this.BlockFile.ReadBlock(blockNumber, block, 0, 1);
            if (block[0] == (byte)BPlusTreeNodeIndicator.Free)
            {
                throw new BPlusTreeException("attempt to re-free free block not allowed");
            }
            block[0] = (byte)BPlusTreeNodeIndicator.Free;

            // 将指定序号的块置为空闲
            StoredHelper.Store(this.FreeBlockHeadNumber, block, 1);
            this.BlockFile.WriteBlock(blockNumber, block, 0, freeSize);
            this.FreeBlockHeadNumber = blockNumber;
        }
Example #5
0
        /// <summary>
        /// 写入块
        /// </summary>
        /// <param name="blockNumber">块序号</param>
        /// <param name="blockFlag">块标记</param>
        /// <param name="fromArray">读取至此数组</param>
        /// <param name="startAt">读取起始点</param>
        /// <param name="length">读取长度</param>
        /// <param name="nextBlockNumber">链接的下一个块</param>
        private void WriteBlock(long blockNumber, LinkedFileBlockFlag blockFlag, byte[] fromArray, int startAt, int length, long nextBlockNumber)
        {
            if (this.BlockSize < length)
            {
                throw new LinkedFileException("block size too small " + this.BlockSize + "<" + length);
            }

            byte[] buffer = new byte[LinkedBlockOverhead + length];

            // 写入块标记
            buffer[0] = (byte)blockFlag; // 1 Byte

            // 写入链接的下一个块的序号
            StoredHelper.Store(nextBlockNumber, buffer, 1); // 8 Bytes

            // 写入数据
            if (fromArray != null)
            {
                Array.Copy(fromArray, startAt, buffer, LinkedBlockOverhead, length);
            }

            this.BlockFile.WriteBlock(blockNumber, buffer, 0, buffer.Length);
        }
Example #6
0
        /// <summary>
        /// 存储新的大块数据,返回头序号。
        /// </summary>
        /// <param name="chunk">读取至此数组</param>
        /// <param name="startAt">读取起始点</param>
        /// <param name="length">读取长度</param>
        /// <returns>存储数据的头序号</returns>
        public long StoreChunk(byte[] chunk, int startAt, int length)
        {
            if (length < 0 || startAt < 0)
            {
                throw new LinkedFileException("cannot store negative length chunk (" + startAt + "," + length + ")");
            }

            // 分配用于存储的块 并标记为头块
            long currentBlockNumber = this.AllocateBlock();
            LinkedFileBlockFlag currentBlockFlag = LinkedFileBlockFlag.Head;

            // 存储数据的头序号
            long headBlockNumber = currentBlockNumber;

            int endAt = startAt + length;

            // special case: zero length chunk
            if (endAt > chunk.Length)
            {
                throw new LinkedFileException("array doesn't have this much data: " + endAt);
            }

            // store header with length information
            byte[] block = new byte[this.BlockSize];

            // 存储块长度
            StoredHelper.Store(length, block, 0);

            int fromIndex        = startAt;
            int firstBlockLength = this.BlockSize - StoredConstants.IntegerLength;
            int storedLength     = 0;

            if (firstBlockLength > length)
            {
                firstBlockLength = length;
            }

            // 存储数据
            Array.Copy(chunk, fromIndex, block, StoredConstants.IntegerLength, firstBlockLength);

            storedLength += firstBlockLength;
            fromIndex    += firstBlockLength;

            // 存储剩余数据
            while (storedLength < length)
            {
                // 获取下一个块序号
                long nextBlockNumber = this.AllocateBlock();

                // 存储当前数据
                this.WriteBlock(currentBlockNumber, currentBlockFlag, block, 0, block.Length, nextBlockNumber);

                currentBlockNumber = nextBlockNumber;
                currentBlockFlag   = LinkedFileBlockFlag.Body; // 下一个块则为Body

                int nextLength = this.BlockSize;
                if (storedLength + nextLength > length)
                {
                    nextLength = length - storedLength;
                }

                Array.Copy(chunk, fromIndex, block, 0, nextLength);

                storedLength += nextLength;
                fromIndex    += nextLength;
            }

            // 存储最终块
            this.WriteBlock(currentBlockNumber, currentBlockFlag, block, 0, block.Length, StoredConstants.NullBlockNumber);

            return(headBlockNumber);
        }