예제 #1
0
        private void CompensatePages(BTreePage left, BTreePage right, BTreePage parent, int childrenIndex)
        {
            int parentRecordIndex = 0, recordsToTransfer;

            if (left.GetPresentRecords() < right.GetPresentRecords())
            {
                for (var i = 0; i < parent.Childrens.Count; i++)
                {
                    if (parent.Childrens[i] == left.SelfIndex)
                    {
                        parentRecordIndex = i;
                    }
                }
                //parentRecordIndex = childrenIndex - 1;
                recordsToTransfer = (right.GetPresentRecords() - left.GetPresentRecords()) / 2;

                left.InsertRecord(parent.Records[parentRecordIndex]);
                for (var i = 0; i < recordsToTransfer - 1; i++)
                {
                    left.InsertRecord(right.PopRecordAt(0, false));
                }
                if (!right.IsLeaf)
                {
                    for (var i = 0; i < recordsToTransfer; i++)
                    {
                        left.Childrens.Add(right.PopChildrenAt(0));
                    }
                }

                parent.Records[parentRecordIndex] = right.PopRecordAt(0, false);
            }
            else
            {
                for (var i = 0; i < parent.Childrens.Count; i++)
                {
                    if (parent.Childrens[i] == left.SelfIndex)
                    {
                        parentRecordIndex = i;
                    }
                }
                //parentRecordIndex = childrenIndex;
                recordsToTransfer = (left.GetPresentRecords() - right.GetPresentRecords()) / 2;

                right.InsertRecord(parent.Records[parentRecordIndex]);

                for (var i = 0; i < recordsToTransfer - 1; i++)
                {
                    right.InsertRecord(left.PopRecordAt(left.Records.Count - 1, false));
                }
                if (!left.IsLeaf)
                {
                    for (var i = 0; i < recordsToTransfer; i++)
                    {
                        right.Childrens.Insert(0, left.PopChildrenAt(left.Childrens.Count - 1));
                    }
                }

                parent.Records[parentRecordIndex] = left.PopRecordAt(left.Records.Count - 1, false);
            }
        }
예제 #2
0
        private void Merge()
        {
            var       partPath = _path.Pop();
            var       parentPage = partPath.ParentPage;
            var       childrenIndex = partPath.ChildrenIndex;
            BTreePage leftBrother = null, rightBrother = null;

            if (childrenIndex == 0)                 //zrobic zapisy
            {
                rightBrother = new BTreePage(BtreeIO.ReadPage(parentPage.Childrens[childrenIndex + 1]));

                var recordsToTransfer = rightBrother.GetPresentRecords();
                for (var i = 0; i < recordsToTransfer; i++)
                {
                    _currentPage.InsertRecord(rightBrother.PopRecordAt(0, true));
                }
                if (!_currentPage.IsLeaf)
                {
                    for (var i = 0; i < recordsToTransfer + 1; i++)
                    {
                        _currentPage.Childrens.Add(rightBrother.PopChildrenAt(0));
                    }
                }

                parentPage.PopChildrenAt(childrenIndex + 1);

                _currentPage.InsertRecord(parentPage.Records[childrenIndex]);

                BTreeFreeSpaceMap.FreePage(rightBrother.SelfIndex);
                BtreeIO.WritePage(_currentPage.GetBTreePage(), _currentPage.SelfIndex);
            }
            else
            {
                leftBrother = new BTreePage(BtreeIO.ReadPage(parentPage.Childrens[childrenIndex - 1]));

                var recordsToTransfer = _currentPage.GetPresentRecords();
                for (var i = 0; i < recordsToTransfer; i++)
                {
                    leftBrother.InsertRecord(_currentPage.PopRecordAt(0, true));
                }
                if (!_currentPage.IsLeaf)
                {
                    for (var i = 0; i < recordsToTransfer + 1; i++)
                    {
                        leftBrother.Childrens.Add(_currentPage.PopChildrenAt(0));
                    }
                }

                parentPage.PopChildrenAt(childrenIndex);

                leftBrother.InsertRecord(parentPage.Records[childrenIndex - 1]);

                BTreeFreeSpaceMap.FreePage(_currentPage.SelfIndex);
                BtreeIO.WritePage(leftBrother.GetBTreePage(), leftBrother.SelfIndex);
            }

            try {
                if (childrenIndex == 0)
                {
                    parentPage.PopRecordAt(childrenIndex, false);
                }
                else
                {
                    parentPage.PopRecordAt(childrenIndex - 1, false);
                }
                BtreeIO.WritePage(parentPage.GetBTreePage(), parentPage.SelfIndex);
            } catch (PageDeficitException ex) {
                _currentPage = parentPage;
                if (!Compensate())
                {
                    Merge();
                }
            } catch (RootPageDeficitException ex) {
                BTreeFreeSpaceMap.FreePage(RootPage.SelfIndex);
                if (childrenIndex == 0)
                {
                    RootPage = _currentPage;
                    BTreeHeaderPage.RootIndex = _currentPage.SelfIndex;
                }
                else
                {
                    RootPage = leftBrother;
                    BTreeHeaderPage.RootIndex = leftBrother.SelfIndex;
                }
            }
        }
예제 #3
0
        public void RemoveRecordByKey(long key)
        {
            var record = FindByKey(key);

            if (record == null)
            {
                throw new KeyDoesNotExistException();
            }


            var       recordIndex = 0;
            BTreePage leafPage;

            try {
                if (_currentPage.IsLeaf)
                {
                    _currentPage.RemoveRecord(key);
                    BtreeIO.WritePage(_currentPage.GetBTreePage(), _currentPage.SelfIndex);
                    return;
                }
            } catch (PageDeficitException) {
                if (!Compensate())
                {
                    Merge();
                }
                return;
            } finally {
                DataFreeSpaceMap.FreePage(record.RecordIndex);
            }

            for (var i = 0; i < _currentPage.GetPresentRecords(); i++)
            {
                if (_currentPage.Records[i].Key == record.Key)
                {
                    recordIndex = i;
                }
            }
            if (recordIndex == 0)
            {
                leafPage = GetPageFromSubTreeWithLowestKey(
                    new BTreePage(BtreeIO.ReadPage(_currentPage.Childrens[recordIndex + 1]))
                    );

                var input = leafPage.Records[0];

                _currentPage.SwapRecord(input, record);
                leafPage.SwapRecord(record, input);
            }
            else
            {
                leafPage = GetPageFromSubTreeWithHighestKey(
                    new BTreePage(BtreeIO.ReadPage(_currentPage.Childrens[recordIndex]))
                    );
                var input = leafPage.Records[leafPage.GetPresentRecords() - 1];

                _currentPage.SwapRecord(input, record);
                leafPage.SwapRecord(record, input);
            }


            BtreeIO.WritePage(_currentPage.GetBTreePage(), _currentPage.SelfIndex);
            try {
                FindByKey(leafPage.Records[1].Key);                 //dla odswiezenia sciezki _path
                leafPage.RemoveRecord(key);
            } catch (PageDeficitException) {
                _currentPage = leafPage;

                if (!Compensate())
                {
                    Merge();
                }
                return;
            }

            BtreeIO.WritePage(leafPage.GetBTreePage(), leafPage.SelfIndex);
        }