public void DeleteNodeEntry(NodeID nodeID) { NodeBTreeLeafPage leaf = (NodeBTreeLeafPage)FindLeafBTreePage(nodeID.Value); // Remove the entry int index = leaf.RemoveEntry(nodeID.Value); if (index == 0) { // scanpst.exe report an error if page key does not match the first entry, // so we want to update the parent if (leaf.ParentPage != null) { if (leaf.NodeEntryList.Count > 0) { UpdateIndexEntry(leaf.ParentPage, leaf.BlockID, leaf.PageKey); } else { DeleteIndexEntry(leaf.ParentPage, leaf.BlockID); DeletePage(leaf); return; } } } // now we have to store the new leaf page, and cascade the changes up to the root page UpdatePageAndReferences(leaf); }
public static BTreePage ReadFromStream(Stream stream, BlockRef blockRef) { long offset = (long)blockRef.ib; stream.Seek(offset, SeekOrigin.Begin); byte[] buffer = new byte[Length]; stream.Read(buffer, 0, Length); PageTypeName ptype = (PageTypeName)buffer[PageTrailer.OffsetFromPageStart + 0]; BTreePage page; byte cLevel = buffer[491]; if (cLevel > 0) { // If cLevel is greater than 0, then each entry in the array is of type BTENTRY. page = new BTreeIndexPage(buffer); } else { // If cLevel is 0, then each entry is either of type BBTENTRY or NBTENTRY, depending on the ptype of the page. if (ptype == PageTypeName.ptypeBBT) { page = new BlockBTreeLeafPage(buffer); } else if (ptype == PageTypeName.ptypeNBT) { page = new NodeBTreeLeafPage(buffer); } else { throw new ArgumentException("BTreePage has incorrect ptype"); } } page.Offset = (ulong)blockRef.ib; if (blockRef.bid.Value != page.BlockID.Value) { throw new InvalidBlockIDException(); } uint crc = PSTCRCCalculation.ComputeCRC(buffer, PageTrailer.OffsetFromPageStart); if (page.pageTrailer.dwCRC != crc) { throw new InvalidChecksumException(); } uint signature = BlockTrailer.ComputeSignature(blockRef.ib, blockRef.bid.Value); if (page.pageTrailer.wSig != signature) { throw new InvalidChecksumException(); } return(page); }
public NodeBTreeEntry FindNodeEntryByNodeID(uint nodeID) { NodeBTreeLeafPage page = (NodeBTreeLeafPage)FindLeafBTreePage(nodeID); if (page != null) { // page.cLevel is now 0 List <NodeBTreeEntry> nodeEntryList = page.NodeEntryList; foreach (NodeBTreeEntry entry in nodeEntryList) { if (entry.nid.Value == nodeID) { return(entry); } } } return(null); }
public NodeBTreeLeafPage Split() { int newNodeStartIndex = NodeEntryList.Count / 2; NodeBTreeLeafPage newPage = new NodeBTreeLeafPage(); // BlockID will be given when the page will be added newPage.cEntMax = cEntMax; newPage.cbEnt = cbEnt; newPage.cLevel = cLevel; newPage.pageTrailer.ptype = pageTrailer.ptype; for (int index = newNodeStartIndex; index < NodeEntryList.Count; index++) { newPage.NodeEntryList.Add(NodeEntryList[index]); } NodeEntryList.RemoveRange(newNodeStartIndex, NodeEntryList.Count - newNodeStartIndex); return(newPage); }
public void InsertNodeEntry(NodeBTreeEntry entryToInsert) { ulong key = entryToInsert.nid.Value; NodeBTreeLeafPage page = (NodeBTreeLeafPage)FindLeafBTreePage(key); if (page.NodeEntryList.Count < NodeBTreeLeafPage.MaximumNumberOfEntries) { int insertIndex = page.InsertSorted(entryToInsert); UpdatePageAndReferences(page); if (insertIndex == 0 && page.ParentPage != null) { // page key has been modified, we must update the parent UpdateIndexEntry(page.ParentPage, page.BlockID, page.PageKey); } } else { // We have to split the tree node NodeBTreeLeafPage newPage = page.Split(); if (newPage.PageKey < key) { newPage.InsertSorted(entryToInsert); } else { int insertIndex = page.InsertSorted(entryToInsert); if (insertIndex == 0 && page.ParentPage != null) { // page key has been modified, we must update the parent UpdateIndexEntry(page.ParentPage, page.BlockID, page.PageKey); } } UpdatePageAndReferences(page); AddPage(newPage); if (page.ParentPage == null) { // this is a root page and it's full, we have to create a new root CreateNewRoot(); } InsertIndexEntry(page.ParentPage, newPage.NodeEntryList[0].nid.Value, newPage.BlockID); } }
public void UpdateNodeEntry(NodeID nodeID, DataTree dataTree, SubnodeBTree subnodeBTree) { NodeBTreeLeafPage leaf = (NodeBTreeLeafPage)FindLeafBTreePage(nodeID.Value); int index = leaf.GetIndexOfEntry(nodeID.Value); if (index >= 0) { leaf.NodeEntryList[index].bidData = new BlockID(0); if (dataTree != null && dataTree.RootBlock != null) { leaf.NodeEntryList[index].bidData = dataTree.RootBlock.BlockID; } leaf.NodeEntryList[index].bidSub = new BlockID(0); if (subnodeBTree != null && subnodeBTree.RootBlock != null) { leaf.NodeEntryList[index].bidSub = subnodeBTree.RootBlock.BlockID; } // now we have to store the new leaf page, and cascade the changes up to the root page UpdatePageAndReferences(leaf); } }