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不好使了。 }
/// <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); } }