Пример #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
        public BTree(Stream bTreeStream, Stream dataStream, Stream bTreeMap, Stream dataMap, bool create)
        {
            BtreeIO = new BufferedIO(bTreeStream, (int)Static.PageSize);
            DataIO  = new BufferedIO(dataStream, Record.ByteSize);

            if (create)
            {
                bTreeStream.SetLength(0);
                dataStream.SetLength(0);
                bTreeMap.SetLength(0);
                dataMap.SetLength(0);

                BTreeHeader       = new BTreeHeaderPage(Static.FirstRootIndex);
                RootPage          = new BTreePage(0, Static.FirstRootIndex);
                BTreeFreeSpaceMap = new FreeSpaceMap(bTreeMap, 2);
                DataFreeSpaceMap  = new FreeSpaceMap(dataMap, 0);
            }
            else
            {
                BTreeHeader       = new BTreeHeaderPage(BtreeIO.ReadPage(0));
                RootPage          = new BTreePage(BtreeIO.ReadPage(BTreeHeaderPage.RootIndex));
                BTreeFreeSpaceMap = new FreeSpaceMap(bTreeMap, bTreeStream.Length / Static.PageSize);
                DataFreeSpaceMap  = new FreeSpaceMap(dataMap, dataStream.Length / Record.ByteSize);
            }
        }
Пример #3
0
        private void Split()
        {
            if (_currentPage.SelfIndex == BTreeHeaderPage.RootIndex)                    //root split

            {
                SplitRoot();
                return;
            }

            var pathPart      = _path.Pop();
            var parentPage    = pathPart.ParentPage;
            var childrenIndex = pathPart.ChildrenIndex;

            var newPage = new BTreePage(parentPage.SelfIndex, BTreeFreeSpaceMap.AllocatePage());

            if (!_currentPage.IsLeaf)
            {
                newPage.IsLeaf = false;
            }

            parentPage.Childrens.Insert(childrenIndex, newPage.SelfIndex);

            var recordsPerPage = _currentPage.GetPresentRecords() / 2;

            for (var i = 0; i < recordsPerPage; i++)
            {
                newPage.InsertRecord(_currentPage.PopRecordAt(0, false));
            }

            if (!_currentPage.IsLeaf)
            {
                for (var i = 0; i < recordsPerPage + 1; i++)
                {
                    newPage.Childrens.Add(_currentPage.PopChildrenAt(0));
                }
            }

            var forParent = _currentPage.PopRecordAt(0, false);

            BtreeIO.WritePage(_currentPage.GetBTreePage(), _currentPage.SelfIndex);
            BtreeIO.WritePage(newPage.GetBTreePage(), newPage.SelfIndex);

            try {
                parentPage.InsertRecord(forParent);

                BtreeIO.WritePage(parentPage.GetBTreePage(), parentPage.SelfIndex);
            } catch (PageOverflowException) {
                _currentPage = parentPage;

                if (Compensate())
                {
                    return;
                }

                Split();
            }
        }
Пример #4
0
        private BTreePage GetPageFromSubTreeWithHighestKey(BTreePage subTreeRootPage)
        {
            var currentPage = subTreeRootPage;

            while (currentPage.IsLeaf == false)
            {
                currentPage = new BTreePage(BtreeIO.ReadPage(currentPage.Childrens[currentPage.Childrens.Count - 1]));
            }

            return(currentPage);
        }
Пример #5
0
        private bool Compensate()
        {
            if (_currentPage.SelfIndex == BTreeHeaderPage.RootIndex)
            {
                return(false);
            }

            var partPath      = _path.Peek();
            var parentPage    = partPath.ParentPage;
            var childrenIndex = partPath.ChildrenIndex;

            BTreePage leftBrother, rightBrother;

            if (childrenIndex == 0)
            {
                leftBrother  = null;
                rightBrother = new BTreePage(BtreeIO.ReadPage(parentPage.Childrens[childrenIndex + 1]));
            }
            else if (childrenIndex == parentPage.GetPresentRecords())
            {
                leftBrother  = new BTreePage(BtreeIO.ReadPage(parentPage.Childrens[childrenIndex - 1]));
                rightBrother = null;
            }
            else
            {
                leftBrother  = new BTreePage(BtreeIO.ReadPage(parentPage.Childrens[childrenIndex - 1]));
                rightBrother = new BTreePage(BtreeIO.ReadPage(parentPage.Childrens[childrenIndex + 1]));
            }

            var sumWithLeft  = leftBrother?.GetPresentRecords() + _currentPage.GetPresentRecords();
            var sumWithRight = rightBrother?.GetPresentRecords() + _currentPage.GetPresentRecords();

            if (sumWithLeft >= 2 * Static.MemMin && sumWithLeft <= 2 * Static.MemMax)
            {
                CompensatePages(leftBrother, _currentPage, parentPage, childrenIndex);
                BtreeIO.WritePage(leftBrother.GetBTreePage(), leftBrother.SelfIndex);
            }
            else if (sumWithRight >= 2 * Static.MemMin && sumWithRight <= 2 * Static.MemMax)
            {
                CompensatePages(_currentPage, rightBrother, parentPage, childrenIndex);
                BtreeIO.WritePage(rightBrother.GetBTreePage(), rightBrother.SelfIndex);
            }
            else
            {
                return(false);
            }

            BtreeIO.WritePage(_currentPage.GetBTreePage(), _currentPage.SelfIndex);
            BtreeIO.WritePage(parentPage.GetBTreePage(), parentPage.SelfIndex);


            return(true);
        }
Пример #6
0
        private NodeRecord FindByKey(long key)
        {
            _currentPage = RootPage;
            _path        = new Stack <PathPart>();
            while (true)
            {
                var record = _currentPage.FindRecord(key);
                if (record != null)
                {
                    return(record);
                }

                if (_currentPage.IsLeaf)
                {
                    return(null);
                }

                _parentPage = _currentPage;
                if (key < _currentPage.Records[0].Key)
                {
                    _childrenIndex = 0;
                    _currentPage   = new BTreePage(BtreeIO.ReadPage(_currentPage.Childrens[_childrenIndex]));
                }
                else if (key > _currentPage.Records[_currentPage.Records.Count - 1].Key)
                {
                    _childrenIndex = _currentPage.Records.Count;
                    _currentPage   = new BTreePage(BtreeIO.ReadPage(_currentPage.Childrens[_childrenIndex]));
                }
                else
                {
                    for (var i = 0; i < _currentPage.Records.Count - 1; i++)
                    {
                        if (key > _currentPage.Records[i].Key && key < _currentPage.Records[i + 1].Key)
                        {
                            _childrenIndex = i + 1;
                            _currentPage   = new BTreePage(BtreeIO.ReadPage(_currentPage.Childrens[_childrenIndex]));
                            break;
                        }
                    }
                }

                _path.Push(new PathPart {
                    ParentPage    = _parentPage,
                    ChildrenIndex = _childrenIndex
                });
            }
        }
Пример #7
0
        private void SplitRoot()
        {
            var rootPage = new BTreePage(0, BTreeFreeSpaceMap.AllocatePage());

            rootPage.IsLeaf = false;

            _currentPage.ParentIndex = rootPage.SelfIndex;
            var newPage = new BTreePage(rootPage.SelfIndex, BTreeFreeSpaceMap.AllocatePage());

            if (!_currentPage.IsLeaf)
            {
                newPage.IsLeaf = false;
            }


            rootPage.Childrens.Add(newPage.SelfIndex);
            rootPage.Childrens.Add(_currentPage.SelfIndex);

            var recordsPerPage = _currentPage.GetPresentRecords() / 2;

            for (var i = 0; i < recordsPerPage; i++)
            {
                newPage.InsertRecord(_currentPage.PopRecordAt(0, false));
            }
            if (!_currentPage.IsLeaf)
            {
                for (var i = 0; i < recordsPerPage + 1; i++)
                {
                    newPage.Childrens.Add(_currentPage.PopChildrenAt(0));
                }
            }

            rootPage.InsertRecord(_currentPage.PopRecordAt(0, false));

            BtreeIO.WritePage(_currentPage.GetBTreePage(), _currentPage.SelfIndex);
            BtreeIO.WritePage(newPage.GetBTreePage(), newPage.SelfIndex);
            BtreeIO.WritePage(rootPage.GetBTreePage(), rootPage.SelfIndex);

            RootPage = rootPage;
            BTreeHeaderPage.RootIndex = RootPage.SelfIndex;
        }
Пример #8
0
        public void DisplayTree(BTreePage page, int tabs = 0)             //root
        {
            for (var i = 0; i < page.Records.Count; i++)
            {
                if (!page.IsLeaf)
                {
                    DisplayTree(new BTreePage(BtreeIO.ReadPage(page.Childrens[i])), tabs + 1);
                }

                var record    = DataIO.ReadRecord(page.Records[i].RecordIndex);
                var outString = new string(' ', 112);
                outString = outString.Insert(tabs * 4, page.Records[i].Key.ToString());
                outString = outString.Insert(80, record.Radius.ToString());
                outString = outString.Insert(100, record.Angle.ToString());
                outString = outString.Insert(110, tabs.ToString());
                Console.WriteLine(outString);
            }

            if (!page.IsLeaf)
            {
                DisplayTree(new BTreePage(BtreeIO.ReadPage(page.Childrens[page.Childrens.Count - 1])), tabs + 1);
            }
        }
Пример #9
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;
                }
            }
        }
Пример #10
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);
        }