public static void Delete(this IndexBlock indexBlock, Table record, FileDBContext db)
        {
            Type                type     = record.GetType();
            PropertyInfo        property = type.GetProperty(indexBlock.BindMember);
            TableIndexAttribute attr     = property.GetCustomAttribute <TableIndexAttribute>();

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

            FileStream fs = db.fileStream;
            // 准备Key。
            var key = property.GetValue(record) as IComparable;

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

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

            // See if we actually found the node
            if ((rightNodes[0].RightObj != indexBlock.SkipListTailNode) && (rightKey.CompareTo(key) == 0))
            {
                for (int i = 0; i <= indexBlock.CurrentLevel; i++)
                {
                    // Since the node is consecutive levels, as soon as we don't find it on the next
                    // level, we can stop.
                    if (rightNodes[i].RightObj == indexBlock.SkipListTailNode)
                    {
                        break;
                    }
                    rightNodes[i].RightObj.TryLoadProperties(fs, SkipListNodeBlockLoadOptions.Key);
                    rightKey = rightNodes[i].RightObj.Key.GetObject <IComparable>(fs);
                    if (rightKey.CompareTo(key) != 0)
                    {
                        break;
                    }                                           // 要删除的结点的高度比CurrentLevel低,所以会走到这里。

                    rightNodes[i].RightObj.TryLoadProperties(fs, SkipListNodeBlockLoadOptions.RightObj);

                    db.transaction.Add(rightNodes[i]);
                    db.transaction.Delete(rightNodes[i].RightObj);

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

                //return true;
            }
            else
            {
                //return false;
            }

            //    //itemsCount++;// 有的在内存,有的在文件,因此itemsCount不好使了。
        }
        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不好使了。
        }
Exemple #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);
            }
        }