/// <returns>Insert index</returns> public int InsertSorted(BlockBTreeEntry entryToInsert) { int insertIndex = GetSortedInsertIndex(entryToInsert); BlockEntryList.Insert(insertIndex, entryToInsert); return(insertIndex); }
/// <summary> /// The caller must update its reference to point to the new root /// </summary> public virtual void SaveChanges() { foreach (ulong blockID in m_blocksToWrite) { Block block = m_blockBuffer[blockID]; long offset = AllocationHelper.AllocateSpaceForBlock(m_file, block.TotalLength); block.WriteToStream(m_file.BaseStream, offset); m_file.BlockBTree.InsertBlockEntry(block.BlockID, offset, block.DataLength); } foreach (ulong blockID in m_blocksToFree) { BlockBTreeEntry entry = m_file.FindBlockEntryByBlockID(blockID); entry.cRef--; // Any leaf BBT entry that points to a BID holds a reference count to it. if (entry.cRef == 1) { // we can mark the allocation to be freed and delete the entry, // We should not free the allocation until the BBT is committed. m_file.MarkAllocationToBeFreed(entry.BREF.ib, Block.GetTotalBlockLength(entry.cb)); m_file.BlockBTree.DeleteBlockEntry(entry.BREF.bid); } else { m_file.BlockBTree.UpdateBlockEntry(entry.BREF.bid, entry.cRef); } } m_blocksToWrite.Clear(); m_blocksToFree.Clear(); }
public override void PopulateEntries(byte[] buffer, byte numberOfEntries) { for (int index = 0; index < numberOfEntries; index++) { int offset = index * cbEnt; BlockBTreeEntry entry = new BlockBTreeEntry(buffer, offset); BlockEntryList.Add(entry); } }
public void InsertBlockEntry(BlockID blockID, long offset, int dataLength) { BlockBTreeEntry entryToInsert = new BlockBTreeEntry(); entryToInsert.BREF.bid = blockID; entryToInsert.BREF.ib = (ulong)offset; entryToInsert.cb = (ushort)dataLength; entryToInsert.cRef = 2; // Any leaf BBT entry that points to a BID holds a reference count to it InsertBlockEntry(entryToInsert); }
private int GetSortedInsertIndex(BlockBTreeEntry entryToInsert) { ulong key = entryToInsert.BREF.bid.Value; int insertIndex = 0; while (insertIndex < BlockEntryList.Count && key > BlockEntryList[insertIndex].BREF.bid.Value) { insertIndex++; } return(insertIndex); }
public Block FindBlockByBlockID(ulong blockID) { BlockBTreeEntry entry = FindBlockEntryByBlockID(blockID); if (entry != null) { return(Block.ReadFromStream(m_stream, entry.BREF, entry.cb, Header.bCryptMethod)); } else { return(null); } }
public void InsertBlockEntry(BlockBTreeEntry entryToInsert) { ulong key = entryToInsert.BREF.bid.Value; BlockBTreeLeafPage page = (BlockBTreeLeafPage)FindLeafBTreePage(key); if (page.BlockEntryList.Count < BlockBTreeLeafPage.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 BlockBTreeLeafPage 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.PageKey, newPage.BlockID); } }
public void IncrementBlockEntryReferenceCount(BlockID blockID) { BlockBTreeEntry entry = FindBlockEntryByBlockID(blockID.LookupValue); UpdateBlockEntry(blockID, (ushort)(entry.cRef + 1)); }