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);
            }
        }
Beispiel #3
0
        /// <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);
            }
        }