Example #1
0
        /// <summary>
        /// 读取块存储头部
        /// </summary>
        private void ReadFileHeader()
        {
            byte[] header = new byte[this.FileHeaderSize];

            this.Stream.Seek(this.SeekStart, SeekOrigin.Begin);
            this.Stream.Read(header, 0, this.FileHeaderSize);

            int index = 0;

            // 魔数前缀
            foreach (byte b in FileHeaderPrefix)
            {
                if (header[index] != b)
                {
                    throw new LinkedFileException("invalid header prefix");
                }
                index++;
            }

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

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

            this.IsHeaderDirty = false;

            if (this.BlockSize < StoredConstants.MinBlockSize)
            {
                throw new LinkedFileException("linked file block size too small " + this.BlockSize);
            }
        }
Example #2
0
        /// <summary>
        /// 读取块存储头部
        /// </summary>
        private void ReadFileHeader()
        {
            // 魔数前缀长度 | 块的大小
            byte[] header = new byte[FileHeaderSize];
            this.Stream.Seek(this.SeekStart, SeekOrigin.Begin);
            this.Stream.Read(header, 0, FileHeaderSize);

            int index = 0;

            // 魔数前缀
            foreach (byte b in FileHeaderPrefix)
            {
                if (header[index] != b)
                {
                    throw new BlockFileException("Invalid block file header prefix.");
                }
                index++;
            }

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

            if (this.BlockSize < StoredConstants.MinBlockSize)
            {
                throw new BlockFileException("Block size is too small " + this.BlockSize + ".");
            }
        }
Example #3
0
        /// <summary>
        /// 获取指定头序号的大块数据
        /// </summary>
        /// <param name="headBlockNumber">指定头序号</param>
        /// <returns>大块数据</returns>
        public byte[] GetChunk(long headBlockNumber)
        {
            // get the head, interpret the length
            LinkedFileBlockFlag blockFlag;
            long nextBlockNumber;

            byte[] block = this.ReadBlock(headBlockNumber, out blockFlag, out nextBlockNumber);

            // 读取块长度
            int length = StoredHelper.RetrieveInt(block, 0);

            if (length < 0)
            {
                throw new LinkedFileException("negative length block? must be garbage: " + length);
            }

            if (blockFlag != LinkedFileBlockFlag.Head)
            {
                throw new LinkedFileException("first block not marked HEAD");
            }

            byte[] buffer = new byte[length];

            // 在第一个块中读取数据
            int firstLength = this.BlockSize - StoredConstants.IntegerLength;

            if (firstLength > length)
            {
                firstLength = length;
            }
            Array.Copy(block, StoredConstants.IntegerLength, buffer, 0, firstLength);

            // 在链接的其他块中读取数据
            int stored = firstLength;

            while (stored < length)
            {
                // get the next buffer
                long currentBlockNumber = nextBlockNumber;
                block = this.ReadBlock(currentBlockNumber, out blockFlag, out nextBlockNumber);

                int nextLength = this.BlockSize;
                if (length - stored < nextLength)
                {
                    nextLength = length - stored;
                }

                Array.Copy(block, 0, buffer, stored, nextLength);
                stored += nextLength;
            }

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

            this.Stream.Seek(this.SeekStart, SeekOrigin.Begin);
            this.Stream.Read(header, 0, HeaderSize);

            // 验证头前缀魔数
            int index = 0;

            foreach (byte b in StoredConstants.TreeFileHeaderPrefix)
            {
                if (header[index] != b)
                {
                    throw new BlockFileException("invalid header prefix");
                }
                index++;
            }

            // 版本
            this.Version = header[index];
            index       += 1;

            // 节点容量
            this.NodeCapacity = StoredHelper.RetrieveInt(header, index);
            index            += StoredConstants.IntegerLength;

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

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

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

            if (this.NodeCapacity < 2)
            {
                throw new BPlusTreeException("node size must be larger than 2");
            }
            if (this.KeyLength < 5)
            {
                throw new BPlusTreeException("Key length must be larger than 5");
            }
        }