예제 #1
0
        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);
        }
예제 #2
0
 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);
     }
 }
예제 #3
0
        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);
        }
예제 #4
0
        // 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));
        }
예제 #5
0
        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);
                    }
                }
            }
        }
예제 #6
0
        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);
            }
        }