private Dictionary <string, IndexBlock> GetIndexDict(FileStream fileStream, TableBlock tableBlock)
        {
            Dictionary <string, IndexBlock> indexDict = new Dictionary <string, IndexBlock>();

            long       indexBlockHeadPos = tableBlock.IndexBlockHeadPos;
            IndexBlock currentIndexBlock = fileStream.ReadBlock <IndexBlock>(indexBlockHeadPos);

            tableBlock.IndexBlockHead = currentIndexBlock;

            currentIndexBlock.TryLoadNextObj(fileStream);// 此时的currentIndexBlock是索引块的头结点。
            while (currentIndexBlock.NextObj != null)
            {
                SkipListNodeBlock[] headNodes = GetHeadNodesOfSkipListNodeBlock(fileStream, currentIndexBlock.NextObj);
                currentIndexBlock.NextObj.SkipListHeadNodes = headNodes;
                SkipListNodeBlock tailNode = GetTailNodeOfSkipListNodeBlock(fileStream, currentIndexBlock.NextObj);
                currentIndexBlock.NextObj.SkipListTailNode = tailNode;
                foreach (SkipListNodeBlock headNode in currentIndexBlock.NextObj.SkipListHeadNodes)
                {
                    if (headNode.RightPos == tailNode.ThisPos)
                    {
                        headNode.RightObj = tailNode;
                    }
                }

                currentIndexBlock.NextObj.TryLoadNextObj(fileStream);

                indexDict.Add(currentIndexBlock.NextObj.BindMember, currentIndexBlock.NextObj);

                currentIndexBlock = currentIndexBlock.NextObj;
            }
            return(indexDict);
        }
Example #2
0
 /// <summary>
 /// 为指定的索引生成头结点和尾结点。
 /// </summary>
 /// <param name="indexBlock"></param>
 /// <param name="maxLevel"></param>
 private void InitHeadTailNodes(IndexBlock indexBlock, int maxLevel)
 {
     {
         // 初始化头结点列。
         indexBlock.SkipListHeadNodes = new SkipListNodeBlock[maxLevel];
         /*SkipListHeadNodes[maxLevel - 1]↓*/
         /*SkipListHeadNodes[.]↓*/
         /*SkipListHeadNodes[.]↓*/
         /*SkipListHeadNodes[2]↓*/
         /*SkipListHeadNodes[1]↓*/
         /*SkipListHeadNodes[0] */
         SkipListNodeBlock current = new SkipListNodeBlock();
         indexBlock.SkipListHeadNodes[0] = current;
         for (int i = 1; i < maxLevel; i++)
         {
             SkipListNodeBlock block = new SkipListNodeBlock();
             block.DownObj = current;
             indexBlock.SkipListHeadNodes[i] = block;
             current = block;
         }
     }
     {
         // 初始化尾结点。尾结点在序列化到数据库文件后,将永远不再变动,这给编码带来方便,也是我使用尾结点的原因。
         // 这样也是完全把外存(硬盘)与内存编程相对应的思想。
         indexBlock.SkipListTailNode = new SkipListNodeBlock();
     }
     {
         // 头结点指向对应的尾结点。
         for (int i = 0; i < maxLevel; i++)
         {
             indexBlock.SkipListHeadNodes[i].RightObj = indexBlock.SkipListTailNode;
         }
     }
 }
        private static SkipListNodeBlock[] FindRightMostNodes(IComparable key, IndexBlock indexBlock, FileDBContext db)
        {
            FileStream fs       = db.fileStream;
            int        maxLevel = db.headerBlock.MaxLevelOfSkipList;

            SkipListNodeBlock[] rightNodes = new SkipListNodeBlock[maxLevel];

            // Start at the top list header node
            SkipListNodeBlock currentNode = indexBlock.SkipListHeadNodes[indexBlock.CurrentLevel];

            for (int i = indexBlock.CurrentLevel; i >= 0; i--)
            {
                IComparable rightKey = db.GetRightObjKey(db.fileStream, indexBlock, currentNode);
                while ((currentNode.RightObj != indexBlock.SkipListTailNode) && (rightKey.CompareTo(key) < 0))
                {
                    currentNode = currentNode.RightObj;

                    rightKey = db.GetRightObjKey(db.fileStream, indexBlock, currentNode);
                }

                rightNodes[i] = currentNode;

                if (i > 0)
                {
                    currentNode.TryLoadProperties(fs, SkipListNodeBlockLoadOptions.DownObj);
                    currentNode = currentNode.DownObj;
                }
            }

            return(rightNodes);
        }
Example #4
0
        private static void DrawDataBlocks(FileDBContext db, FileStream fs, Bitmap[] bmps)
        {
            TableBlock tableBlockHead = db.GetTableBlockHeadNode();
            TableBlock previousTable  = tableBlockHead;

            while (previousTable.NextPos != 0)
            {
                TableBlock table = previousTable.NextObj;

                IndexBlock currentIndex = table.IndexBlockHead;
                while (currentIndex.NextObj != null)
                {
                    SkipListNodeBlock currentNode = currentIndex.NextObj.SkipListHeadNodes[0];
                    while (currentNode != null)
                    {
                        if (currentNode.KeyPos != 0)
                        {
                            currentNode.TryLoadProperties(fs, SkipListNodeBlockLoadOptions.Key | SkipListNodeBlockLoadOptions.Value);
                            {
                                long     index    = currentNode.Key.ThisPos.PagePos() / Consts.pageSize;
                                Bitmap   bmp      = bmps[index];
                                Graphics g        = Graphics.FromImage(bmp);
                                int      startPos = (int)(currentNode.Key.ThisPos - Consts.pageSize * index);
                                int      length   = currentNode.Key.ToBytes().Length;
                                Brush    brush    = new LinearGradientBrush(new Point(startPos, 0), new Point(startPos + length, 0), Color.DarkGoldenrod, Color.LightGoldenrodYellow);
                                g.FillRectangle(brush, startPos, 1, length, bmpHeight - 1);
                                g.DrawRectangle(boundPen, startPos, 1, length, bmpHeight - 1);
                                g.Dispose();
                            }
                            foreach (var dataBlock in currentNode.Value)
                            {
                                long     index    = dataBlock.ThisPos.PagePos() / Consts.pageSize;
                                Bitmap   bmp      = bmps[index];
                                Graphics g        = Graphics.FromImage(bmp);
                                int      startPos = (int)(dataBlock.ThisPos - Consts.pageSize * index);
                                int      length   = dataBlock.ToBytes().Length;
                                Brush    brush    = new LinearGradientBrush(new Point(startPos, 0), new Point(startPos + length, 0), Color.DarkGoldenrod, Color.LightGoldenrodYellow);
                                g.FillRectangle(brush, startPos, 1, length, bmpHeight - 1);
                                g.DrawRectangle(boundPen, startPos, 1, length, bmpHeight - 1);
                                g.Dispose();
                            }
                        }

                        currentNode.TryLoadProperties(fs, SkipListNodeBlockLoadOptions.RightObj);
                        currentNode = currentNode.RightObj;
                    }

                    currentIndex = currentIndex.NextObj;
                }

                previousTable = table;
            }
        }
        /// <summary>
        /// 删除数据库内的一条记录。
        /// </summary>
        /// <param name="record"></param>
        public bool Delete(Table record)
        {
            if (record.Id == null)
            {
                throw new Exception(string.Format("[{0}] is a new record!", record));
            }

            Type type = record.GetType();

            if (!this.tableBlockDict.ContainsKey(type))// 添加表和索引数据。
            {
                throw new Exception(string.Format("No Table for type [{0}] is set!", type));
            }

            Transaction ts = this.transaction;

            ts.Begin();

            try
            {
                // 删除record。
                IndexBlock        indexBlock = this.tableIndexBlockDict[type][Consts.TableIdString];
                SkipListNodeBlock downNode   = FindSkipListNode(fileStream, indexBlock, record.Id);

                if (downNode == null)// 此记录根本不存在或已经被删除过一次了。
                {
                    throw new Exception(string.Format("no data blocks for [{0}]", record));
                }

                foreach (KeyValuePair <string, IndexBlock> item in this.tableIndexBlockDict[type])
                {
                    item.Value.Delete(record, this);
                }

                downNode.TryLoadProperties(fileStream, SkipListNodeBlockLoadOptions.Key | SkipListNodeBlockLoadOptions.Value);

                for (int i = 0; i < downNode.Value.Length; i++)
                {
                    this.transaction.Delete(downNode.Value[i]);
                }                                      // 加入事务,准备写入数据库。
                this.transaction.Delete(downNode.Key); // 加入事务,准备写入数据库。

                this.transaction.Commit();

                return(true);
            }
            catch (Exception ex)
            {
                ts.Rollback();
                throw ex;
            }
        }
        private SkipListNodeBlock GetTailNodeOfSkipListNodeBlock(FileStream fileStream, IndexBlock indexBlock)
        {
            long currentSkipListNodeBlockPos = indexBlock.SkipListTailNodePos;

            if (currentSkipListNodeBlockPos == 0)
            {
                throw new Exception(string.Format("tail node not set for [{0}]", indexBlock));
            }

            SkipListNodeBlock tailNode = fileStream.ReadBlock <SkipListNodeBlock>(currentSkipListNodeBlockPos);

            return(tailNode);
        }
Example #7
0
        private static void GetSkipListInfo(IndexBlock indexBlock, FileDBContext db, out List <List <SkipListNodeBlock> > skipList, out Dictionary <long, DataBlock> keyDict, out Dictionary <long, DataBlock> valueDict, out Dictionary <long, SkipListNodeBlock> skipListNodeDict)
        {
            FileStream fs = db.GetFileStream();

            skipList         = new List <List <SkipListNodeBlock> >();
            keyDict          = new Dictionary <long, DataBlock>();
            valueDict        = new Dictionary <long, DataBlock>();
            skipListNodeDict = new Dictionary <long, SkipListNodeBlock>();

            long headNodePos        = indexBlock.SkipListHeadNodePos;
            long currentHeadNodePos = headNodePos;

            while (currentHeadNodePos != 0)
            {
                List <SkipListNodeBlock> line = new List <SkipListNodeBlock>();

                long currentNodePos = currentHeadNodePos;
                while (currentNodePos != 0)
                {
                    SkipListNodeBlock currentNode = fs.ReadBlock <SkipListNodeBlock>(currentNodePos);
                    line.Add(currentNode);

                    if (!skipListNodeDict.ContainsKey(currentNode.ThisPos))
                    {
                        skipListNodeDict.Add(currentNode.ThisPos, currentNode);
                    }
                    if (currentNode.KeyPos != 0)
                    {
                        if (!keyDict.ContainsKey(currentNode.KeyPos))
                        {
                            DataBlock keyBlock = fs.ReadBlock <DataBlock>(currentNode.KeyPos);
                            keyDict.Add(currentNode.KeyPos, keyBlock);
                        }
                    }
                    if (currentNode.ValuePos != 0)
                    {
                        if (!valueDict.ContainsKey(currentNode.ValuePos))
                        {
                            DataBlock valueBlock = fs.ReadBlock <DataBlock>(currentNode.ValuePos);
                            valueDict.Add(currentNode.ValuePos, valueBlock);
                        }
                    }

                    currentNodePos = currentNode.RightPos;
                }

                skipList.Add(line);

                currentHeadNodePos = skipListNodeDict[currentHeadNodePos].DownPos;
            }
        }
        private static void PrintSkipLists(FileDBContext db, StringBuilder builder, FileStream fs)
        {
            TableBlock tableHead         = db.GetTableBlockHeadNode();// fs.ReadBlock<TableBlock>(fs.Position);
            TableBlock currentTableBlock = tableHead;

            while (currentTableBlock.NextPos != 0)// 依次Print各个表
            {
                TableBlock tableBlock = fs.ReadBlock <TableBlock>(currentTableBlock.NextPos);
                builder.Append("Table:"); builder.AppendLine(tableBlock.TableType.ToString());
                IndexBlock indexBlockHead    = fs.ReadBlock <IndexBlock>(tableBlock.IndexBlockHeadPos);
                IndexBlock currentIndexBlock = indexBlockHead;
                IndexBlock indexBlock        = fs.ReadBlock <IndexBlock>(currentIndexBlock.NextPos);

                SkipListNodeBlock currentHeadNode = fs.ReadBlock <SkipListNodeBlock>(indexBlock.SkipListHeadNodePos);
                int level = db.GetDBHeaderBlock().MaxLevelOfSkipList - 1;
                SkipListNodeBlock current = currentHeadNode;
                while (current != null)// 依次Print表的PK Index
                {
                    StringBuilder levelBuilder = new StringBuilder();
                    levelBuilder.AppendLine(string.Format("level {0}", level--));
                    string str = Print(current);
                    levelBuilder.AppendLine(str);
                    int count = 1;
                    while (current.RightPos != 0)//依次Print PK Index的Level
                    {
                        current = fs.ReadBlock <SkipListNodeBlock>(current.RightPos);
                        str     = Print(current);
                        levelBuilder.AppendLine(str);
                        count++;
                    }

                    if (count > 2)
                    {
                        builder.AppendLine(levelBuilder.ToString());
                    }

                    if (currentHeadNode.DownPos != 0)
                    {
                        currentHeadNode = fs.ReadBlock <SkipListNodeBlock>(currentHeadNode.DownPos);
                    }
                    else
                    {
                        currentHeadNode = null;
                    }
                    current = currentHeadNode;
                }

                currentTableBlock = tableBlock;
            }
        }
        /// <summary>
        /// 标记要删除的skip list node块。
        /// </summary>
        /// <param name="currentIndex"></param>
        /// <param name="fs"></param>
        /// <param name="ts"></param>
        private void DeleteSkipListNodes(IndexBlock currentIndex, FileStream fs, Transaction ts)
        {
            foreach (SkipListNodeBlock levelHead in currentIndex.SkipListHeadNodes)
            {
                SkipListNodeBlock current = levelHead;
                while (current.ThisPos != currentIndex.SkipListTailNodePos)
                {
                    ts.Delete(levelHead);

                    current.TryLoadProperties(fs, SkipListNodeBlockLoadOptions.RightObj);
                    current = levelHead.RightObj;
                }
            }

            ts.Delete(currentIndex.SkipListTailNode);
        }
        /// <summary>
        /// 标记要删除的数据块。
        /// </summary>
        /// <param name="currentIndex"></param>
        /// <param name="fs"></param>
        /// <param name="ts"></param>
        private void DeleteDataBlocks(IndexBlock currentIndex, FileStream fs, Transaction ts)
        {
            SkipListNodeBlock current = currentIndex.SkipListHeadNodes[0];

            while (current.RightPos != currentIndex.SkipListTailNodePos)
            {
                current.TryLoadProperties(fs, SkipListNodeBlockLoadOptions.RightObj);
                current.RightObj.TryLoadProperties(fs, SkipListNodeBlockLoadOptions.Key | SkipListNodeBlockLoadOptions.Value);
                ts.Delete(current.RightObj.Key);
                foreach (var item in current.RightObj.Value)
                {
                    ts.Delete(item);
                }

                current = current.RightObj;
            }
        }
Example #11
0
        /// <summary>
        /// 查找具有指定的key值的结点列的最下方的结点。
        /// </summary>
        /// <param name="fileStream"></param>
        /// <param name="key"></param>
        /// <param name="indexBlock"></param>
        /// <returns></returns>
        //private SkipListNodeBlock FindSkipListNode(FileStream fileStream, IComparable key, IndexBlock indexBlock)
        private SkipListNodeBlock FindSkipListNode(FileStream fileStream, IndexBlock indexBlock, IComparable key)
        {
            // Start at the top list header node
            SkipListNodeBlock currentNode = indexBlock.SkipListHeadNodes[indexBlock.CurrentLevel];

            IComparable rightKey = null;

            while (true)
            {
                rightKey = GetRightObjKey(fileStream, indexBlock, currentNode);

                while ((currentNode.RightObj != indexBlock.SkipListTailNode) && (rightKey.CompareTo(key) < 0))
                {
                    currentNode = currentNode.RightObj;

                    rightKey = GetRightObjKey(fileStream, indexBlock, currentNode);
                }

                // Check if there is a next level, and if there is move down.
                if (currentNode.DownPos == 0)
                {
                    break;
                }
                else
                {
                    currentNode.TryLoadProperties(fileStream, SkipListNodeBlockLoadOptions.DownObj);
                    currentNode = currentNode.DownObj;
                }
            }

            // Do one final comparison to see if the key to the right equals this key.
            // If it doesn't match, it would be bigger than this key.
            if (rightKey.CompareTo(key) == 0)
            {
                return(currentNode.RightObj);
            }
            else
            {
                return(null);
            }
        }
        private SkipListNodeBlock[] GetHeadNodesOfSkipListNodeBlock(FileStream fileStream, IndexBlock indexBlock)
        {
            SkipListNodeBlock[] headNodes    = new SkipListNodeBlock[this.headerBlock.MaxLevelOfSkipList];
            long currentSkipListNodeBlockPos = indexBlock.SkipListHeadNodePos;

            for (int i = headNodes.Length - 1; i >= 0; i--)
            {
                if (currentSkipListNodeBlockPos == 0)
                {
                    throw new Exception(string.Format("max level [{0}] != real max level [{1}]", headNodes.Length, headNodes.Length - 1 - i));
                }
                SkipListNodeBlock skipListNodeBlock = fileStream.ReadBlock <SkipListNodeBlock>(currentSkipListNodeBlockPos);
                headNodes[i] = skipListNodeBlock;
                if (i != headNodes.Length - 1)
                {
                    headNodes[i + 1].DownObj = headNodes[i];
                }
                currentSkipListNodeBlockPos = skipListNodeBlock.DownPos;
            }
            return(headNodes);
        }
        public static void TryLoadProperties(this SkipListNodeBlock node, FileStream fileStream, SkipListNodeBlockLoadOptions options = SkipListNodeBlockLoadOptions.RightObj | SkipListNodeBlockLoadOptions.DownObj | SkipListNodeBlockLoadOptions.Key | SkipListNodeBlockLoadOptions.Value)// where T : SkipListNodeBlock//, ISkipListNode<T>
        {
            if (node.RightPos != 0 && node.RightObj == null && (options & SkipListNodeBlockLoadOptions.RightObj) == SkipListNodeBlockLoadOptions.RightObj)
            {
                node.RightObj = fileStream.ReadBlock <SkipListNodeBlock>(node.RightPos);
            }

            if (node.DownPos != 0 && node.DownObj == null && (options & SkipListNodeBlockLoadOptions.DownObj) == SkipListNodeBlockLoadOptions.DownObj)
            {
                node.DownObj = fileStream.ReadBlock <SkipListNodeBlock>(node.DownPos);
            }

            if (node.KeyPos != 0 && node.Key == null && (options & SkipListNodeBlockLoadOptions.Key) == SkipListNodeBlockLoadOptions.Key)
            {
                node.Key = fileStream.ReadBlock <DataBlock>(node.KeyPos);
            }

            if (node.ValuePos != 0 && node.Value == null && (options & SkipListNodeBlockLoadOptions.Value) == SkipListNodeBlockLoadOptions.Value)
            {
                node.Value = fileStream.ReadBlocks <DataBlock>(node.ValuePos);
            }
        }
        /// <summary>
        /// 查找数据库内所有指定类型的记录。
        /// </summary>
        /// <typeparam name="T">要查找的类型。</typeparam>
        /// <returns></returns>
        public IEnumerable <T> FindAll <T>() where T : Table, new()
        {
            Type type = typeof(T);

            if (this.tableBlockDict.ContainsKey(type))
            {
                TableBlock tableBlock = this.tableBlockDict[type];
                IndexBlock firstIndex = tableBlock.IndexBlockHead.NextObj;// 第一个索引应该是Table.Id的索引。
                FileStream fs         = this.fileStream;

                SkipListNodeBlock current = firstIndex.SkipListHeadNodes[0]; //currentHeadNode;

                while (current.RightPos != firstIndex.SkipListTailNodePos)
                {
                    current.TryLoadProperties(fs, SkipListNodeBlockLoadOptions.RightObj);
                    current.RightObj.TryLoadProperties(fs, SkipListNodeBlockLoadOptions.RightObj | SkipListNodeBlockLoadOptions.Value);
                    T item = current.RightObj.Value.GetObject <T>(this);

                    yield return(item);

                    current = current.RightObj;
                }
            }
        }
        /// <summary>
        /// 获取数据库的所有表和表里的所有数据对象。
        /// </summary>
        /// <param name="db"></param>
        /// <returns></returns>
        public static SharpFileDBInfo GetDBInfo(this FileDBContext db)
        {
            SharpFileDBInfo info = new SharpFileDBInfo();

            FileStream fs = db.GetFileStream();
            //fs.ReadBlock<PageHeaderBlock>(0);
            //fs.ReadBlock<DBHeaderBlock>(fs.Position);
            //TableBlock tableHead = fs.ReadBlock<TableBlock>(fs.Position);
            TableBlock currentTableBlock = db.GetTableBlockHeadNode();// tableHead;

            while (currentTableBlock.NextPos != 0)
            {
                TableBlock tableBlock = fs.ReadBlock <TableBlock>(currentTableBlock.NextPos);
                TableInfo  tableInfo  = new TableInfo(tableBlock);
                info.Add(tableInfo);
                IndexBlock indexBlockHead    = fs.ReadBlock <IndexBlock>(tableBlock.IndexBlockHeadPos);
                IndexBlock currentIndexBlock = indexBlockHead;
                bool       primaryKey        = true;
                while (currentIndexBlock.NextPos != 0)
                {
                    IndexBlock indexBlock = fs.ReadBlock <IndexBlock>(currentIndexBlock.NextPos);
                    tableInfo.Add(indexBlock);
                    if (primaryKey)
                    {
                        long currentHeadNodePos           = indexBlock.SkipListHeadNodePos;
                        SkipListNodeBlock currentHeadNode = fs.ReadBlock <SkipListNodeBlock>(currentHeadNodePos);
                        currentHeadNode.TryLoadProperties(fs, SkipListNodeBlockLoadOptions.DownObj);
                        while (currentHeadNode.DownObj != null)
                        {
                            currentHeadNode.DownObj.TryLoadProperties(fs, SkipListNodeBlockLoadOptions.DownObj);
                            currentHeadNode = currentHeadNode.DownObj;
                        }
                        SkipListNodeBlock current = currentHeadNode;
                        current.TryLoadProperties(fs, SkipListNodeBlockLoadOptions.RightObj);
                        while (current.RightObj != null && current.RightObj.ThisPos != indexBlock.SkipListTailNodePos)
                        {
                            current.RightObj.TryLoadProperties(fs, SkipListNodeBlockLoadOptions.Value);
                            Table item = current.RightObj.Value.GetObject <Table>(db);

                            tableInfo.Add(item);

                            current = current.RightObj;
                            current.TryLoadProperties(fs, SkipListNodeBlockLoadOptions.RightObj);
                        }
                        //while (current.RightObj.RightPos != 0)
                        //{
                        //    current.RightObj.TryLoadProperties(fs, SkipListNodeBlockLoadOptions.Value);
                        //    Table item = current.RightObj.Value.GetObject<Table>(db);

                        //    tableInfo.Add(item);

                        //    current = current.RightObj;
                        //}

                        primaryKey = false;
                    }

                    currentIndexBlock = indexBlock;
                }

                currentTableBlock = tableBlock;
            }

            return(info);
        }
 static string Print(SkipListNodeBlock skipListNodeBlock)
 {
     return(string.Format("Pos: {0}, K: {1}, V: {2}, Down: {3}, Right: {4}",
                          skipListNodeBlock.ThisPos, skipListNodeBlock.KeyPos, skipListNodeBlock.ValuePos,
                          skipListNodeBlock.DownPos, skipListNodeBlock.RightPos));
 }
Example #17
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);
            }
        }
Example #18
0
        private static void SaveToImage(TableBlock table, IndexBlock index, List <List <SkipListNodeBlock> > skipList, Dictionary <long, DataBlock> keyDict, Dictionary <long, DataBlock> valueDict, Dictionary <long, SkipListNodeBlock> skipListNodeDict, string dir, string prefix, FileDBContext db)
        {
            const int leftMargin     = 25;
            const int topMargin      = 13;
            const int nodeWidth      = 200;
            const int nodeHeight     = 30;
            const int arrowLength    = 30;
            const int keyValueHeight = 20;
            //const int keyValueInterval = 5;
            const int bottomLargin = 30;

            int      width    = skipList[skipList.Count - 1].Count * (nodeWidth + arrowLength) + leftMargin;
            int      height   = skipList.Count * (nodeHeight + arrowLength) + keyDict.Count * keyValueHeight * 2 + topMargin + bottomLargin;
            Bitmap   bmp      = new Bitmap(width, height);
            Graphics graphics = Graphics.FromImage(bmp);

            int maxLevel = db.GetDBHeaderBlock().MaxLevelOfSkipList;

            if (maxLevel != skipList.Count)
            {
                throw new Exception();
            }

            // 画 skip list node.
            List <SkipListNodeBlock> lastLine = skipList[skipList.Count - 1];

            for (int i = 0; i < skipList.Count; i++)
            {
                List <SkipListNodeBlock> line = skipList[i];
                graphics.DrawString(string.Format("{0}:", skipList.Count - i - 1), font, brush,
                                    2, (i) * (nodeHeight + arrowLength) + topMargin);
                for (int j = 0; j < line.Count; j++)
                {
                    int widthStep = 0;
                    if (j + 1 == line.Count)
                    {
                        widthStep = lastLine.Count - 1;
                    }
                    else
                    {
                        while (lastLine[widthStep].KeyPos != line[j].KeyPos)
                        {
                            widthStep++;
                        }
                    }
                    SkipListNodeBlock node = line[j];
                    graphics.DrawString(string.Format("[@[{0}]: {1}, {2}]", node.ThisPos, node.KeyPos, node.ValuePos), font, brush,
                                        leftMargin + widthStep * (nodeWidth + arrowLength),
                                        i * (nodeHeight + arrowLength) + topMargin);
                }
            }

            // 画RightPos箭头。
            for (int i = 0; i < skipList.Count; i++)
            {
                List <SkipListNodeBlock> line = skipList[i];
                for (int j = 0; j < line.Count - 1; j++)
                {
                    int leftWidthStep = 0, rightWidthStep = 0;
                    while (lastLine[leftWidthStep].KeyPos != line[j].KeyPos)
                    {
                        leftWidthStep++;
                    }
                    if (j + 1 + 1 == line.Count)
                    {
                        rightWidthStep = lastLine.Count - 1;
                    }
                    else
                    {
                        while (lastLine[rightWidthStep].KeyPos != line[j + 1].KeyPos)
                        {
                            rightWidthStep++;
                        }
                    }
                    graphics.DrawLine(rightPosPen,
                                      leftMargin + leftWidthStep * (nodeWidth + arrowLength) + nodeWidth / 2,
                                      topMargin + i * (nodeHeight + arrowLength),
                                      leftMargin + rightWidthStep * (nodeWidth + arrowLength),
                                      topMargin + i * (nodeHeight + arrowLength)
                                      );
                    graphics.DrawLine(rightPosPen,
                                      leftMargin + rightWidthStep * (nodeWidth + arrowLength) - 5,
                                      topMargin + i * (nodeHeight + arrowLength) - 5,
                                      leftMargin + rightWidthStep * (nodeWidth + arrowLength),
                                      topMargin + i * (nodeHeight + arrowLength));
                    graphics.DrawLine(rightPosPen,
                                      leftMargin + rightWidthStep * (nodeWidth + arrowLength) - 5,
                                      topMargin + i * (nodeHeight + arrowLength) + 5,
                                      leftMargin + rightWidthStep * (nodeWidth + arrowLength),
                                      topMargin + i * (nodeHeight + arrowLength));
                }
            }

            // 画DownPos箭头。
            for (int i = 0; i < skipList.Count; i++)
            {
                List <SkipListNodeBlock> line = skipList[i];
                for (int j = 0; j < line.Count; j++)
                {
                    SkipListNodeBlock node = line[j];
                    if (node.DownPos != 0)
                    {
                        SkipListNodeBlock downNode = skipListNodeDict[node.DownPos];
                        int topWidthStep = 0, topHeightStep = 0, downWidthStep = 0, downHeightStep = 0;
                        while (lastLine[topWidthStep].KeyPos != node.KeyPos)
                        {
                            topWidthStep++;
                        }
                        topHeightStep = i;
                        while (lastLine[downWidthStep].KeyPos != downNode.KeyPos)
                        {
                            downWidthStep++;
                        }
                        for (int k = 0; k < skipList.Count; k++)
                        {
                            if (skipList[k].Contains(downNode))
                            {
                                downHeightStep = k;
                                break;
                            }
                        }
                        graphics.DrawLine(downPosPen,
                                          leftMargin + topWidthStep * (nodeWidth + arrowLength) + nodeWidth / 2,
                                          topMargin + topHeightStep * (nodeHeight + arrowLength) + nodeHeight / 2,
                                          leftMargin + downWidthStep * (nodeWidth + arrowLength) + nodeWidth / 2,
                                          topMargin + downHeightStep * (nodeHeight + arrowLength) - 2
                                          );
                        graphics.DrawLine(downPosPen,
                                          leftMargin + downWidthStep * (nodeWidth + arrowLength) + nodeWidth / 2 + 5,
                                          topMargin + downHeightStep * (nodeHeight + arrowLength) - 2 - 5,
                                          leftMargin + downWidthStep * (nodeWidth + arrowLength) + nodeWidth / 2,
                                          topMargin + downHeightStep * (nodeHeight + arrowLength) - 2
                                          );
                        graphics.DrawLine(downPosPen,
                                          leftMargin + downWidthStep * (nodeWidth + arrowLength) + nodeWidth / 2 - 5,
                                          topMargin + downHeightStep * (nodeHeight + arrowLength) - 2 - 5,
                                          leftMargin + downWidthStep * (nodeWidth + arrowLength) + nodeWidth / 2,
                                          topMargin + downHeightStep * (nodeHeight + arrowLength) - 2
                                          );
                    }
                }
            }

            // 画Key和Value。
            for (int i = 0; i < lastLine.Count; i++)
            {
                SkipListNodeBlock node = lastLine[i];
                if ((node.KeyPos == 0 && node.ValuePos != 0) || (node.KeyPos != 0 && node.ValuePos == 0))
                {
                    throw new Exception();
                }
                if (node.KeyPos != 0)
                {
                    DataBlock   keyDataBlock = keyDict[node.KeyPos];
                    IComparable key          = keyDataBlock.GetObject <IComparable>(db.GetFileStream());
                    graphics.DrawString(string.Format("Key: @[{0}]: {{{1}}}", node.KeyPos, key),
                                        font, brush, leftMargin,
                                        (skipList.Count - 1) * (nodeHeight + arrowLength) + topMargin + (keyValueHeight) * i * 2);
                    DataBlock valueDataBlock = valueDict[node.ValuePos];
                    Table     value          = valueDataBlock.GetObject <Table>(db.GetFileStream());
                    graphics.DrawString(string.Format("Value: @[{0}]: {{{1}}}", node.ValuePos, value),
                                        font, brush, leftMargin,
                                        (skipList.Count - 1) * (nodeHeight + arrowLength) + topMargin + (keyValueHeight) * (i * 2 + 1));
                }
            }

            // 画边框。
            graphics.DrawRectangle(boundPen, 0, 0, width - 1, height - 1);

            string fullname = Path.Combine(dir, prefix + table.TableType.FullName + "-" + index.BindMember + ".bmp");

            bmp.Save(fullname);
            graphics.Dispose();
            bmp.Dispose();
        }
Example #19
0
        /// <summary>
        /// 更新数据库内的一条记录。
        /// </summary>
        /// <param name="record"></param>
        public bool Update(Table record)
        {
            if (record.Id == null)
            {
                throw new Exception(string.Format("[{0}] is a new record! Use Insert(Table) to create a new record in SharpFileDB.", record));
            }

            Type type = record.GetType();

            if (!this.tableBlockDict.ContainsKey(type))// 添加表和索引数据。
            {
                throw new Exception(string.Format("DBError: No Table for type [{0}] is set!", type));
            }

            Transaction ts = this.transaction;

            ts.Begin();

            try
            {
                // 更新record。
                IndexBlock        indexBlock = this.tableIndexBlockDict[type][Consts.TableIdString];
                SkipListNodeBlock downNode   = FindSkipListNode(fileStream, indexBlock, record.Id);
                downNode.TryLoadProperties(fileStream, SkipListNodeBlockLoadOptions.Value);
                DataBlock[] oldValue = downNode.Value;

                if (downNode == null)// 此记录根本不存在或已经被删除了。
                {
                    throw new Exception(string.Format("no data blocks for [{0}]", record));
                }

                DataBlock[] dataBlocksForValue = record.ToDataBlocks();

                foreach (KeyValuePair <string, IndexBlock> item in this.tableIndexBlockDict[type])
                {
                    item.Value.Update(record, dataBlocksForValue, this);
                }

                // 删除旧的record.ToDataBlocks()数据。
                for (int i = 0; i < oldValue.Length; i++)
                {
                    this.transaction.Delete(oldValue[i]);
                }                                        // 加入事务,准备写入数据库。
                //this.transaction.Delete(downNode.Key);// 加入事务,准备写入数据库。

                // 写入新的record.ToDataBlocks()数据。
                for (int i = 0; i < dataBlocksForValue.Length; i++)
                {
                    this.transaction.Add(dataBlocksForValue[i]);
                }                                               // 加入事务,准备写入数据库。

                ts.Commit();

                return(true);
            }
            catch (Exception ex)
            {
                ts.Rollback();
                throw ex;
            }
        }
        public static void Insert(this IndexBlock indexBlock, Table item, DataBlock[] dataBlocksForValue, FileDBContext db)
        {
            Type                type     = item.GetType();
            PropertyInfo        property = type.GetProperty(indexBlock.BindMember);
            TableIndexAttribute attr     = property.GetCustomAttribute <TableIndexAttribute>();

            if (attr == null)
            {
                throw new Exception(string.Format("No TableIndexAttribute binded!"));
            }

            // 准备Key。
            IComparable key = property.GetValue(item) as IComparable;

            byte[] keyBytes = key.ToBytes();
            if (keyBytes.Length > Consts.maxDataBytes)
            {
                throw new Exception(string.Format("Toooo long is the key [{0}]", key));
            }
            DataBlock dataBlockForKey = new DataBlock()
            {
                ObjectLength = keyBytes.Length, Data = keyBytes,
            };

            SkipListNodeBlock[] rightNodes = FindRightMostNodes(key, indexBlock, db);

            // Check if the item allready exists in the list.  If it does, throw an exception -
            // we will not allow duplicate items here.
            FileStream fs       = db.fileStream;
            int        maxLevel = db.headerBlock.MaxLevelOfSkipList;

            IComparable rightKey = db.GetRightObjKey(fs, indexBlock, rightNodes[0]);

            if ((rightNodes[0].RightObj != indexBlock.SkipListTailNode) &&
                (rightKey.CompareTo(key) == 0))   // key相等,说明Value相同。此处不再使用NGenerics的Comparer<TKey>.Default这种可指定外部比较工具的模式,是因为那会由于忘记编写合适的比较工具而带来隐藏地很深的bug。
            {
                throw new Exception("Item Already In List");
            }
            else
            {
                int newLevel = PickRandomLevel(db, indexBlock);

                if (newLevel > indexBlock.CurrentLevel)
                {
                    for (int i = indexBlock.CurrentLevel + 1; i <= newLevel; i++)
                    {
                        rightNodes[i] = indexBlock.SkipListHeadNodes[i];
                    }

                    indexBlock.CurrentLevel = newLevel;
                }

                List <SkipListNodeBlock> nodeList = new List <SkipListNodeBlock>();
                SkipListNodeBlock        newNode  = new SkipListNodeBlock()
                {
                    Key = dataBlockForKey, Value = dataBlocksForValue,
                };
                nodeList.Add(newNode);

                // Insert the item in the first level
                newNode.RightObj       = rightNodes[0].RightObj;
                rightNodes[0].RightObj = newNode;

                // And now insert the node in the rest of the levels, making sure
                // to update the the links
                SkipListNodeBlock previousNode = null;
                for (int i = 1; i <= indexBlock.CurrentLevel; i++)
                {
                    previousNode = newNode;
                    newNode      = new SkipListNodeBlock()
                    {
                        Key = dataBlockForKey, Value = dataBlocksForValue,
                    };
                    nodeList.Add(newNode);

                    newNode.RightObj       = rightNodes[i].RightObj;
                    rightNodes[i].RightObj = newNode;

                    newNode.DownObj = previousNode;
                }

                for (int i = nodeList.Count - 1; i >= 0; i--)
                {
                    db.transaction.Add(rightNodes[i]);
                }                                     // 加入事务,准备写入数据库。

                for (int i = nodeList.Count - 1; i >= 0; i--)
                {
                    db.transaction.Add(nodeList[i]);
                }                                    // 加入事务,准备写入数据库。

                db.transaction.Add(dataBlockForKey); // 加入事务,准备写入数据库。
            }

            //itemsCount++;// 有的在内存,有的在文件,因此itemsCount不好使了。
        }
Example #21
0
        internal IComparable GetRightObjKey(FileStream fileStream, IndexBlock indexBlock, SkipListNodeBlock currentNode)
        {
            IComparable rightKey = null;

            if (currentNode.RightPos == indexBlock.SkipListTailNodePos)
            {
                currentNode.RightObj = indexBlock.SkipListTailNode;
            }
            else
            {
                currentNode.TryLoadProperties(fileStream, SkipListNodeBlockLoadOptions.RightObj);
                currentNode.RightObj.TryLoadProperties(fileStream, SkipListNodeBlockLoadOptions.Key);
                rightKey = currentNode.RightObj.Key.GetObject <IComparable>(fileStream);
            }
            return(rightKey);
        }