public BTreeOnHeapLeaf <T> GetLeaf(HeapID leafHeapID, BTreeOnHeapIndexRecord leafIndexRecord) { BTreeOnHeapLeaf <T> result; if (!m_leavesCache.ContainsKey(leafHeapID.Value)) { BTreeOnHeapLeaf <T> leaf = GetLeafFromHeap(leafHeapID); if (leaf != null) { m_leavesCache.Add(leafHeapID.Value, leaf); } result = leaf; } else { result = m_leavesCache[leafHeapID.Value]; } if (result != null && leafIndexRecord != null) { // The BTH index node might have changed since the leaf was stored, // We must not use the index node stored in the cache. result.Index = leafIndexRecord.Index; } return(result); }
public BTreeOnHeapLeaf <T> GetLeafFromHeap(HeapID leafHeapID) { // The hid is set to zero if the BTH is empty if (leafHeapID.Value == 0) { return(null); } else { byte[] leafBytes = GetHeapItem(leafHeapID); BTreeOnHeapLeaf <T> result = new BTreeOnHeapLeaf <T>(leafBytes); result.HeapID = leafHeapID; return(result); } }
public BTreeOnHeapLeaf <T> Split() { int newNodeStartIndex = Records.Count / 2; BTreeOnHeapLeaf <T> newNode = new BTreeOnHeapLeaf <T>(); newNode.Index = Index; // Heap ID will be given when the item will be added for (int index = newNodeStartIndex; index < Records.Count; index++) { newNode.Records.Add(Records[index]); } Records.RemoveRange(newNodeStartIndex, Records.Count - newNodeStartIndex); return(newNode); }
// the PC is simply a BTH with cbKey set to 2 and cbEnt set to 6 public T FindRecord(byte[] key) { BTreeOnHeapLeaf <T> leaf = FindLeaf(key); if (leaf != null) { foreach (T record in leaf.Records) { // All the entries in the child have key values greater than or equal to this key value. if (record.IsKeyEquals(key)) { return(record); } } } return(default(T)); }
public void RemoveRecord(byte[] key) { BTreeOnHeapLeaf <T> leaf = FindLeaf(key); if (leaf != null) { int index = leaf.RemoveRecord(key); if (leaf.Records.Count == 0) { RemoveItemFromHeap(leaf.HeapID); // leaf with 0 entries is invalid and must be deleted if (leaf.Index == null) { // this is the root node BTreeHeader.hidRoot = HeapID.EmptyHeapID; BTreeHeader.bIdxLevels = 0; UpdateBTreeHeader(); } else { DeleteFromIndexRecord(leaf.Index, leaf.HeapID); } } else { // will always replace in place (the new leaf is smaller than the old one) ReplaceHeapItem(leaf.HeapID, leaf.GetBytes()); m_leavesCache[leaf.HeapID.Value] = leaf; // scanpst.exe report an error if page key does not match the first entry, // so we want to update the parent if (index == 0 && leaf.Index != null) { UpdateIndexRecord(leaf.Index, leaf.HeapID, leaf.HeapID, leaf.NodeKey); } } } }
public void AddRecord(T record) { BTreeOnHeapLeaf <T> leaf = FindLeaf(record.Key); if (leaf == null) // BTH is empty { leaf = new BTreeOnHeapLeaf <T>(); leaf.InsertSorted(record); HeapID rootHeapID = AddItemToHeap(leaf.GetBytes()); UpdateRootHeapID(rootHeapID); } else if (leaf.Records.Count < leaf.MaximumNumberOfRecords) { int insertIndex = leaf.InsertSorted(record); HeapID existingHeapID = leaf.HeapID; leaf.HeapID = ReplaceHeapItem(leaf.HeapID, leaf.GetBytes()); m_leavesCache[leaf.HeapID.Value] = leaf; if (leaf.HeapID.Value != existingHeapID.Value) { if (leaf.Index == null) { // this is the root node UpdateRootHeapID(leaf.HeapID); } else { // update the parent UpdateIndexRecord(leaf.Index, existingHeapID, leaf.HeapID, leaf.NodeKey); } m_leavesCache.Remove(existingHeapID.Value); } else if (insertIndex == 0 && leaf.Index != null) { // Node key has been modified, we must update the parent UpdateIndexRecord(leaf.Index, leaf.HeapID, leaf.HeapID, leaf.NodeKey); } } else { // The node is full, we have to split it BTreeOnHeapLeaf <T> newNode = leaf.Split(); if (record.CompareTo(newNode.NodeKey) > 0) { newNode.InsertSorted(record); } else { int insertIndex = leaf.InsertSorted(record); if (insertIndex == 0 && leaf.Index != null) { // Node key has been modified, we must update the parent UpdateIndexRecord(leaf.Index, leaf.HeapID, leaf.HeapID, leaf.NodeKey); } } if (leaf.Index == null) { // this is a root page and it's full, we have to create a new root leaf.Index = CreateNewRoot(leaf.NodeKey); } // Item will be replaced in place, because it has less items than before ReplaceHeapItem(leaf.HeapID, leaf.GetBytes()); m_leavesCache[leaf.HeapID.Value] = leaf; HeapID newNodeHeapID = AddItemToHeap(newNode.GetBytes()); // We made sure we have a parent to add our new page to InsertIndexRecord(leaf.Index, newNode.NodeKey, newNodeHeapID); } }