Пример #1
0
 public BlockHeader(BinaryDeserializer Reader)
 {
     this.BytesUsed        = Reader.ReadUInt16();                // 0: Counts number of bytes used in block, excluding the node header, and the last block link (14 bytes in total).
     this.SizeSubtree      = Reader.ReadUInt32();                // 2: Order statistic tree, counting number of objects rooted at the current node.
     this.LastBlockIndex   = Reader.ReadBlockLink();             // 6: Last block link.
     this.ParentBlockIndex = Reader.ReadBlockLink();             // 10: Parent block link.
 }
        private async Task <ulong?> GoToObject(ulong ObjectIndex, uint BlockIndex)
        {
            if (ObjectIndex == 0)
            {
                if (await this.GoToFirst(BlockIndex))
                {
                    return(1);
                }
                else
                {
                    return(null);
                }
            }

            object ObjectId;
            int    Len;
            int    Pos;
            uint   BlockLink;
            bool   IsEmpty;

            byte[] Block = await this.LoadBlock(BlockIndex);

            BinaryDeserializer Reader = new BinaryDeserializer(this.file.CollectionName, this.file.Encoding, Block, this.file.BlockLimit);
            BlockHeader        Header = new BlockHeader(Reader);
            ulong Count = 0;
            ulong?SubtreeCount;

            if (ObjectIndex >= Header.SizeSubtree && Header.SizeSubtree < uint.MaxValue)
            {
                return(Header.SizeSubtree);
            }

            do
            {
                Pos = Reader.Position;

                BlockLink = Reader.ReadBlockLink();                                  // Block link.
                ObjectId  = this.recordHandler.GetKey(Reader);                       // Object ID of object.

                IsEmpty = (ObjectId == null);
                if (IsEmpty)
                {
                    break;
                }

                Len              = this.recordHandler.GetPayloadSize(Reader);        // Remaining length of object.
                Reader.Position += Len;

                if (BlockLink != 0)
                {
                    SubtreeCount = await this.GoToObject(ObjectIndex - Count, BlockLink);

                    if (SubtreeCount.HasValue)
                    {
                        Count += SubtreeCount.Value;
                        if (Count > ObjectIndex)
                        {
                            return(Count);
                        }
                    }
                    else
                    {
                        return(null);
                    }
                }

                if (Count++ == ObjectIndex)
                {
                    this.currentBlockIndex = BlockIndex;
                    this.currentBlock      = Block;
                    this.currentReader     = Reader;
                    this.currentHeader     = Header;

                    await this.LoadObject(ObjectId, Pos + 4);

                    return(Count);
                }
            }while (Reader.BytesLeft >= 4);

            if (Header.LastBlockIndex != 0)
            {
                SubtreeCount = await this.GoToObject(ObjectIndex - Count, Header.LastBlockIndex);

                if (SubtreeCount.HasValue)
                {
                    Count += SubtreeCount.Value;
                    if (Count == ObjectIndex)
                    {
                        return(Count);
                    }
                }
                else
                {
                    return(null);
                }
            }

            return(Count);
        }