/// <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); } }
/// <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"); } }
/// <summary> /// 在指定的块序号之后,查找新的空闲块头序号 /// </summary> /// <param name="blockNumber">指定的块序号</param> /// <returns>新的空闲块头序号</returns> private long ParseFreeBlock(long blockNumber) { int freeSize = 1 + StoredConstants.LongLength; byte[] block = new byte[freeSize]; this.BlockFile.ReadBlock(blockNumber, block, 0, freeSize); if (block[0] != (byte)BPlusTreeNodeIndicator.Free) { throw new BPlusTreeException("free block not marked free"); } long newHead = StoredHelper.RetrieveLong(block, 1); return(newHead); }
/// <summary> /// 读取块 /// </summary> /// <param name="blockNumber">块序号</param> /// <param name="blockFlag">块标记</param> /// <param name="nextBlockNumber">链接的下一个块</param> /// <returns>块数据</returns> private byte[] ReadBlock(long blockNumber, out LinkedFileBlockFlag blockFlag, out long nextBlockNumber) { byte[] fullBuffer = new byte[LinkedBlockOverhead + this.BlockSize]; this.BlockFile.ReadBlock(blockNumber, fullBuffer, 0, fullBuffer.Length); // 读取块标记 blockFlag = (LinkedFileBlockFlag)fullBuffer[0]; // 读取链接的下一个块的序号 nextBlockNumber = StoredHelper.RetrieveLong(fullBuffer, 1); // 读取数据 byte[] buffer = new byte[this.BlockSize]; Array.Copy(fullBuffer, LinkedBlockOverhead, buffer, 0, this.BlockSize); return(buffer); }