Пример #1
0
        public void DeleteFromIndexRecord(BTreeOnHeapIndex index, HeapID heapID)
        {
            int recordIndex = index.GetIndexOfRecord(heapID);

            index.Records.RemoveAt(recordIndex);
            if (index.Records.Count > 0)
            {
                // will always replace in place (smaller size)
                ReplaceHeapItem(index.HeapID, index.GetBytes());
            }
            else
            {
                if (index.ParentIndex == null)
                {
                    // this is the root node
                    BTreeHeader.hidRoot    = HeapID.EmptyHeapID;
                    BTreeHeader.bIdxLevels = 0;
                    UpdateBTreeHeader();
                }
                else
                {
                    DeleteFromIndexRecord(index.ParentIndex, index.HeapID);
                }
            }
        }
Пример #2
0
        public void InsertIndexRecord(BTreeOnHeapIndex index, BTreeOnHeapIndexRecord record)
        {
            HeapID existingHeapID = index.HeapID;

            if (index.Records.Count < index.MaximumNumberOfRecords)
            {
                int insertIndex = index.InsertSorted(record);
                index.HeapID = ReplaceHeapItem(existingHeapID, index.GetBytes());
                if (index.HeapID.Value != existingHeapID.Value)
                {
                    if (index.ParentIndex == null)
                    {
                        // this is the root node
                        UpdateRootHeapID(index.HeapID);
                    }
                    else
                    {
                        UpdateIndexRecord(index.ParentIndex, existingHeapID, index.HeapID, index.NodeKey);
                    }
                }
                else if (insertIndex == 0 && index.ParentIndex != null)
                {
                    // Node key has been modified, we must update the parent
                    UpdateIndexRecord(index.ParentIndex, existingHeapID, index.HeapID, index.NodeKey);
                }
            }
            else
            {
                // The node is full, we have to split it
                BTreeOnHeapIndex newNode = index.Split();
                if (record.CompareTo(newNode.NodeKey) > 0)
                {
                    newNode.InsertSorted(record);
                }
                else
                {
                    int insertIndex = index.InsertSorted(record);
                    if (insertIndex == 0 && index.ParentIndex != null)
                    {
                        // Node key has been modified, we must update the parent
                        UpdateIndexRecord(index.ParentIndex, index.HeapID, index.HeapID, index.NodeKey);
                    }
                }

                if (index.ParentIndex == null)
                {
                    // this is a root page and it's full, we have to create a new root
                    index.ParentIndex = CreateNewRoot(index.NodeKey);
                }

                // Item will be replaced in place, because it has less items than before
                ReplaceHeapItem(index.HeapID, index.GetBytes());

                HeapID newNodeHeapID = AddItemToHeap(newNode.GetBytes());

                // We made sure we have a parent to add our new page to
                InsertIndexRecord(index.ParentIndex, newNode.NodeKey, newNodeHeapID);
            }
        }
Пример #3
0
        public void InsertIndexRecord(BTreeOnHeapIndex index, byte[] key, HeapID hidNextLevel)
        {
            BTreeOnHeapIndexRecord indexRecord = new BTreeOnHeapIndexRecord();

            indexRecord.key          = key;
            indexRecord.hidNextLevel = hidNextLevel;
            InsertIndexRecord(index, indexRecord);
        }
Пример #4
0
        /// <summary>
        /// Find the leaf BTreePage where the entry with the given key should be located
        /// We use this method for search and insertion
        /// Note: you can use record.Index to find the BTreeOnHeapIndex of the record
        /// </summary>
        private BTreeOnHeapIndexRecord FindLeafIndexRecord(byte[] key)
        {
            int keyLength = BTreeHeader.cbKey;

            if (keyLength != key.Length)
            {
                throw new ArgumentException("Key length is not valid");
            }

            if (BTreeHeader.bIdxLevels > 0)
            {
                if (BTreeHeader.hidRoot.IsEmpty)
                {
                    throw new Exception("PST is corrupted, bIdxLevels > 0 and BTH root is empty");
                }
                byte             level      = BTreeHeader.bIdxLevels;
                byte[]           indexBytes = GetHeapItem(BTreeHeader.hidRoot);
                BTreeOnHeapIndex index      = new BTreeOnHeapIndex(indexBytes, keyLength);
                index.HeapID = BTreeHeader.hidRoot;

                while (level > 0)
                {
                    BTreeOnHeapIndexRecord lastToMatch = index.Records[0];

                    for (int recordIndex = 1; recordIndex < index.Records.Count; recordIndex++)
                    {
                        BTreeOnHeapIndexRecord record = index.Records[recordIndex];
                        // All the entries in the child have key values greater than or equal to this key value.
                        if (record.CompareTo(key) <= 0)
                        {
                            lastToMatch = record;
                        }
                        else
                        {
                            break;
                        }
                    }

                    level--;

                    if (level == 0)
                    {
                        lastToMatch.Index = index;
                        return(lastToMatch);
                    }
                    else
                    {
                        byte[]           bytes      = GetHeapItem(lastToMatch.hidNextLevel);
                        BTreeOnHeapIndex childIndex = new BTreeOnHeapIndex(bytes, keyLength);
                        childIndex.ParentIndex = index;
                        childIndex.HeapID      = lastToMatch.hidNextLevel;
                        index = childIndex;
                    }
                }
            }

            return(null);
        }
Пример #5
0
        public void UpdateIndexRecord(BTreeOnHeapIndex index, HeapID oldHeapID, HeapID newHeapID, byte[] newKey)
        {
            int recordIndex = index.GetIndexOfRecord(oldHeapID);

            index.Records[recordIndex].hidNextLevel = newHeapID;
            index.Records[recordIndex].key          = newKey;
            // will always replace in place (same size)
            ReplaceHeapItem(index.HeapID, index.GetBytes());

            if (recordIndex == 0 && index.ParentIndex != null)
            {
                UpdateIndexRecord(index.ParentIndex, index.HeapID, index.HeapID, index.NodeKey);
            }
        }
        public BTreeOnHeapIndex Split()
        {
            int newNodeStartIndex    = Records.Count / 2;
            BTreeOnHeapIndex newNode = new BTreeOnHeapIndex(this.KeyLength);

            newNode.ParentIndex = ParentIndex;
            // 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);
        }
Пример #7
0
        public BTreeOnHeapIndex CreateNewRoot(byte[] nextLevelKey)
        {
            BTreeOnHeapIndex       newRoot         = new BTreeOnHeapIndex(nextLevelKey.Length);
            BTreeOnHeapIndexRecord rootIndexRecord = new BTreeOnHeapIndexRecord();

            rootIndexRecord.key          = nextLevelKey;
            rootIndexRecord.hidNextLevel = BTreeHeader.hidRoot;
            newRoot.Records.Add(rootIndexRecord);
            newRoot.HeapID = AddItemToHeap(newRoot.GetBytes());

            BTreeHeader.hidRoot = newRoot.HeapID;
            BTreeHeader.bIdxLevels++;
            UpdateBTreeHeader();

            return(newRoot);
        }