예제 #1
0
        public void InsertRecord(DataRecord dataRecord)
        {
            var record = FindByKey(dataRecord.Key);

            if (record != null)
            {
                throw new KeyAlreadyExistsException();
            }



            var dataPointer = DataFreeSpaceMap.AllocatePage();

            DataIO.WriteRecord(dataRecord.Record, dataPointer);
            var nodeRecord = new NodeRecord(dataRecord.Key, dataPointer);


            try {
                _currentPage.InsertRecord(nodeRecord);
            } catch (PageOverflowException) {               //kompensacja lub rozszczepienie
                if (!Compensate())
                {
                    Split();
                }

                return;
            }
            BtreeIO.WritePage(_currentPage.GetBTreePage(), _currentPage.SelfIndex);
        }
예제 #2
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();
            }
        }
예제 #3
0
        public void Dispose()
        {
            BtreeIO.WritePage(RootPage.GetBTreePage(), RootPage.SelfIndex);
            BtreeIO.WritePage(BTreeHeader.GetHeaderPage(), 0);

            BTreeFreeSpaceMap.Dispose();
            DataFreeSpaceMap.Dispose();

            BtreeIO.Stream.Dispose();
            DataIO.Stream.Dispose();
        }
예제 #4
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;
        }
예제 #5
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;
                }
            }
        }