public static void WriteBlock(this FileStream fileStream, Block block) { if (fileStream.Length < block.ThisPos) { fileStream.SetLength(block.ThisPos); } fileStream.Seek(block.ThisPos, SeekOrigin.Begin); Consts.formatter.Serialize(fileStream, block); BlockCache.TryRemoveFloatingBlock(block); // 如果是new Block(),需要在此时从floating列表移除 BlockCache.AddSunkBlock(block); // 如果是new Block(),需要在此时加入sunk字典 }
/// <summary> /// 创建初始状态的数据库文件。 /// </summary> /// <param name="fullname">数据库文件据对路径。</param> /// <param name="config">数据库配置信息。</param> private void CreateDB(string fullname, DBConfig config) { FileInfo fileInfo = new FileInfo(fullname); Directory.CreateDirectory(fileInfo.DirectoryName); using (FileStream fs = new FileStream(fullname, FileMode.CreateNew, FileAccess.Write, FileShare.None, Consts.pageSize)) { PageHeaderBlock page = new PageHeaderBlock() { OccupiedBytes = Consts.pageSize, AvailableBytes = 0, }; fs.WriteBlock(page); DBHeaderBlock dbHeader = new DBHeaderBlock() { MaxLevelOfSkipList = config.MaxLevelOfSkipList, ProbabilityOfSkipList = config.ProbabilityOfSkipList, MaxSunkCountInMemory = config.MaxSunkCountInMemory, LockTimeout = config.LockTimeout, ThisPos = fs.Position }; fs.WriteBlock(dbHeader); TableBlock tableHead = new TableBlock() { ThisPos = fs.Position, }; fs.WriteBlock(tableHead); byte[] leftSpace = new byte[Consts.pageSize - fs.Length]; fs.Write(leftSpace, 0, leftSpace.Length); BlockCache.TryRemoveFloatingBlock(page); BlockCache.TryRemoveFloatingBlock(dbHeader); BlockCache.TryRemoveFloatingBlock(tableHead); BlockCache.TryRemoveSunkBlock(page); BlockCache.TryRemoveSunkBlock(dbHeader); BlockCache.TryRemoveSunkBlock(tableHead); } }
/// <summary> /// 系统启动时初始化各项常量。 /// </summary> static Consts() { { PropertyInfo[] properties = typeof(Table).GetProperties(); foreach (var property in properties) { TableIndexAttribute attr = property.GetCustomAttribute <TableIndexAttribute>(); if (attr != null && property.PropertyType == typeof(ObjectId)) { Consts.TableIdString = property.Name; break; } } } { PageHeaderBlock page = new PageHeaderBlock(); using (MemoryStream ms = new MemoryStream()) { formatter.Serialize(ms, page); if (ms.Length > Consts.pageSize / 10) { throw new Exception("Page header block takes too much space!"); } Consts.pageHeaderBlockLength = (Int16)ms.Length; Consts.maxAvailableSpaceInPage = (Int16)(Consts.pageSize - ms.Length); Consts.minOccupiedBytes = (Int16)(Consts.pageSize - Consts.maxAvailableSpaceInPage); } BlockCache.TryRemoveFloatingBlock(page); } { PageHeaderBlock page = new PageHeaderBlock(); DBHeaderBlock dbHeader = new DBHeaderBlock(); TableBlock tableHead = new TableBlock(); Int16 usedSpaceInFirstPage; using (MemoryStream ms = new MemoryStream()) { formatter.Serialize(ms, page); dbHeader.ThisPos = ms.Length; formatter.Serialize(ms, dbHeader); tableHead.ThisPos = ms.Length; Consts.dbHeaderBlockLength = (Int16)(ms.Length - Consts.pageHeaderBlockLength); formatter.Serialize(ms, tableHead); Consts.tableBlockLength = (Int16)(ms.Length - tableHead.ThisPos); usedSpaceInFirstPage = (Int16)ms.Length; } if (usedSpaceInFirstPage > Consts.pageSize) { throw new Exception("First page is full!"); } BlockCache.TryRemoveFloatingBlock(page); BlockCache.TryRemoveFloatingBlock(dbHeader); BlockCache.TryRemoveFloatingBlock(tableHead); } { IndexBlock block = new IndexBlock(); int length = block.ToBytes().Length; if (length > Consts.pageSize / 10) { throw new Exception("index block takes too much space!"); } Consts.indexBlockLength = (Int16)length; BlockCache.TryRemoveFloatingBlock(block); } { SkipListNodeBlock block = new SkipListNodeBlock(); int length = block.ToBytes().Length; if (length > Consts.pageSize / 10) { throw new Exception("index block takes too much space!"); } Consts.skipListNodeBlockLength = (Int16)length; BlockCache.TryRemoveFloatingBlock(block); } { PageHeaderBlock page = new PageHeaderBlock(); DataBlock dataBlock = new DataBlock(); dataBlock.Data = new byte[0]; Int16 minValue; using (MemoryStream ms = new MemoryStream()) { formatter.Serialize(ms, page); long pos = ms.Length; formatter.Serialize(ms, dataBlock); Consts.dataBlockLength = (Int16)(ms.Length - pos); if (ms.Length > Consts.pageSize / 10) { throw new Exception("data block's metadata takes too much space!"); } minValue = (Int16)ms.Length; } Consts.maxDataBytes = (Int16)(Consts.pageSize - minValue); BlockCache.TryRemoveFloatingBlock(page); BlockCache.TryRemoveFloatingBlock(dataBlock); } }