/// <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; } }
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); }