/// <summary>
        /// Find the SubnodeLeafBlock where the entry with the given key should be located
        /// We use this method for search and insertion
        /// </summary>
        public SubnodeLeafBlock FindLeafBlock(uint subnodeID)
        {
            if (m_rootBlock == null)
            {
                return(null);
            }
            else if (m_rootBlock is SubnodeLeafBlock)
            {
                // We do not want to return the reference
                return((SubnodeLeafBlock)m_rootBlock.Clone());
            }
            else if (m_rootBlock is SubnodeIntermediateBlock)
            {
                SubnodeIntermediateBlock intermediateBlock = (SubnodeIntermediateBlock)m_rootBlock;

                int index = intermediateBlock.IndexOfIntermediateEntryWithMatchingRange(subnodeID);

                BlockID blockID = intermediateBlock.rgentries[index].bid;
                return((SubnodeLeafBlock)GetBlock(blockID.LookupValue));
            }
            else
            {
                throw new Exception("Invalid Subnode BTree root block");
            }
        }
        protected void InsertIntermediateEntry(SubnodeIntermediateBlock intermediateBlock, uint key, BlockID blockID)
        {
            SubnodeIntermediateEntry intermediateEntry = new SubnodeIntermediateEntry();

            intermediateEntry.nid = new NodeID(key);
            intermediateEntry.bid = blockID;
            InsertIntermediateEntry(intermediateBlock, intermediateEntry);
        }
        public override Block Clone()
        {
            SubnodeIntermediateBlock result = (SubnodeIntermediateBlock)MemberwiseClone();

            result.rgentries = new List <SubnodeIntermediateEntry>();
            foreach (SubnodeIntermediateEntry entry in rgentries)
            {
                result.rgentries.Add(entry.Clone());
            }
            return(result);
        }
 public void UpdateIntermediateEntry(SubnodeIntermediateBlock intermediateBlock, BlockID blockIDOfChild, uint newKeyOfChild)
 {
     for (int index = 0; index < intermediateBlock.rgentries.Count; index++)
     {
         SubnodeIntermediateEntry entry = intermediateBlock.rgentries[index];
         if (entry.bid.Value == blockIDOfChild.Value)
         {
             entry.nid = new NodeID(newKeyOfChild);
         }
     }
 }
 protected void InsertIntermediateEntry(SubnodeIntermediateBlock intermediateBlock, SubnodeIntermediateEntry entryToInsert)
 {
     if (intermediateBlock.rgentries.Count < SubnodeIntermediateBlock.MaximumNumberOfEntries)
     {
         intermediateBlock.InsertSorted(entryToInsert);
     }
     else
     {
         throw new Exception("Maximum number of entries has been reached for subnode intermediate block");
     }
 }
        public void CreateNewRoot()
        {
            SubnodeIntermediateBlock newRoot = new SubnodeIntermediateBlock();

            SubnodeIntermediateEntry rootIntermediateEntry = new SubnodeIntermediateEntry();

            // We make sure the old root page has been updated (to prevent the BlockID from changing during update)
            UpdateBlock(m_rootBlock);

            rootIntermediateEntry.nid = new NodeID(((SubnodeLeafBlock)m_rootBlock).BlockKey);
            rootIntermediateEntry.bid = m_rootBlock.BlockID;
            newRoot.rgentries.Add(rootIntermediateEntry);
            AddBlock(newRoot);
            m_rootBlock = newRoot;
        }
 public SubnodeLeafBlock GetLeafBlock(int blockIndex)
 {
     if (m_rootBlock is SubnodeLeafBlock)
     {
         if (blockIndex == 0)
         {
             return((SubnodeLeafBlock)m_rootBlock);
         }
         else
         {
             throw new ArgumentOutOfRangeException("blockIndex", "Invalid leaf block index");
         }
     }
     else
     {
         SubnodeIntermediateBlock intermediateBlock = (SubnodeIntermediateBlock)m_rootBlock;
         BlockID blockID = intermediateBlock.rgentries[blockIndex].bid;
         return((SubnodeLeafBlock)GetBlock(blockID.LookupValue));
     }
 }
        private void UpdateBlockAndReferences(SubnodeLeafBlock leafBlock)
        {
            ulong existingBlockID = leafBlock.BlockID.Value;

            UpdateBlock(leafBlock);
            if (m_rootBlock is SubnodeIntermediateBlock)
            {
                if (leafBlock.BlockID.Value != existingBlockID)
                {
                    // A new block has been written instead of the old one, update the root block
                    SubnodeIntermediateBlock rootBlock = (SubnodeIntermediateBlock)m_rootBlock;
                    int index = rootBlock.GetIndexOfBlockID(existingBlockID);
                    rootBlock.rgentries[index].bid = leafBlock.BlockID;
                    UpdateBlock(m_rootBlock);
                }
            }
            else if (m_rootBlock is SubnodeLeafBlock)
            {
                m_rootBlock = leafBlock;
            }
        }
示例#9
0
        public static Block ReadFromStream(Stream stream, BlockRef blockRef, int dataLength, bCryptMethodName bCryptMethod)
        {
            long offset      = (long)blockRef.ib;
            int  totalLength = GetTotalBlockLength(dataLength);

            stream.Seek(offset, SeekOrigin.Begin);
            byte[] buffer = new byte[totalLength];
            stream.Read(buffer, 0, totalLength);

            BlockTrailer trailer = BlockTrailer.ReadFromEndOfBuffer(buffer);
            Block        block;

            if (trailer.bid.Internal)
            {
                // XBlock or XXBlock
                byte btype  = buffer[0];
                byte cLevel = buffer[1];
                if (btype == (byte)BlockType.XBlock && cLevel == 0x01)
                {
                    // XBLOCK
                    block = new XBlock(buffer);
                }
                else if (btype == (byte)BlockType.XXBlock && cLevel == 0x02)
                {
                    // XXBLOCK
                    block = new XXBlock(buffer);
                }
                else if (btype == (byte)BlockType.SLBLOCK && cLevel == 0x00)
                {
                    // SLBLock
                    block = new SubnodeLeafBlock(buffer);
                }
                else if (btype == (byte)BlockType.SIBLOCK && cLevel == 0x01)
                {
                    // SIBLock
                    block = new SubnodeIntermediateBlock(buffer);
                }
                else
                {
                    throw new Exception("Internal block, but not XBLOCK, XXBlock, SLBLOCK or SIBLOCK");
                }
            }
            else
            {
                block = new DataBlock(buffer, bCryptMethod);
            }

            // See question 3 at:
            // http://social.msdn.microsoft.com/Forums/en-CA/os_binaryfile/thread/923f5964-4a89-4811-86c2-06a553c34510
            // However, so far all tests suggest that there should be no problem to use BlockID.Value for both arguments
            if (blockRef.bid.LookupValue != block.BlockID.LookupValue)
            {
                throw new InvalidBlockIDException();
            }

            if (dataLength != trailer.cb)
            {
                throw new Exception("Invalid block length");
            }

            uint crc = PSTCRCCalculation.ComputeCRC(buffer, dataLength);

            if (block.BlockTrailer.dwCRC != crc)
            {
                throw new InvalidChecksumException();
            }

            uint signature = BlockTrailer.ComputeSignature(blockRef.ib, blockRef.bid.Value);

            if (block.BlockTrailer.wSig != signature)
            {
                throw new InvalidChecksumException();
            }

            return(block);
        }