Example #1
0
 void InternalBTreeParentEraseRange(ref Sector sector, ref BTreeParentIterator iter, int firstIndexToErase, int lastIndexToErase)
 {
     var originalLength = iter.TotalLength;
     Debug.Assert(iter.Count >= lastIndexToErase - firstIndexToErase);
     var eraseFromOfs = iter.OffsetOfIndex(firstIndexToErase);
     var eraseToOfs = lastIndexToErase - 1 == iter.Count
                          ? originalLength + KeyValueDB.PtrDownSize + 8
                          : iter.OffsetOfIndex(lastIndexToErase);
     sector = _owner.ResizeSectorNoUpdatePosition(sector,
                                                  originalLength - eraseToOfs + eraseFromOfs,
                                                  sector.Parent,
                                                  null);
     var newCount = iter.Count - (lastIndexToErase - firstIndexToErase);
     BTreeParentIterator.SetCountToSectorData(sector.Data, newCount);
     var ofs = BTreeParentIterator.HeaderSize + newCount * BTreeParentIterator.HeaderForEntry;
     if (firstIndexToErase == 0)
     {
         iter.MoveTo(lastIndexToErase - 1);
         Array.Copy(iter.Data, iter.ChildSectorPtrOffset, sector.Data, BTreeParentIterator.FirstChildSectorPtrOffset, KeyValueDB.PtrDownSize + 8);
         Array.Copy(iter.Data, eraseToOfs, sector.Data, ofs, originalLength - eraseToOfs);
     }
     else
     {
         Array.Copy(iter.Data, BTreeParentIterator.FirstChildSectorPtrOffset, sector.Data, BTreeParentIterator.FirstChildSectorPtrOffset, KeyValueDB.PtrDownSize + 8);
         iter.MoveTo(firstIndexToErase - 1);
         if (lastIndexToErase - 1 == iter.Count)
         {
             Array.Copy(iter.Data, iter.FirstOffset, sector.Data, ofs, iter.EntryOffset - iter.FirstOffset);
         }
         else
         {
             var ofs2 = ofs + iter.ChildSectorPtrOffset - iter.FirstOffset;
             iter.MoveTo(lastIndexToErase - 1);
             Array.Copy(iter.Data, iter.FirstOffset, sector.Data, ofs, eraseFromOfs - iter.FirstOffset);
             ofs += eraseFromOfs - iter.FirstOffset;
             Array.Copy(iter.Data, iter.ChildSectorPtrOffset, sector.Data, ofs2, KeyValueDB.PtrDownSize + 8);
             Array.Copy(iter.Data, eraseToOfs, sector.Data, ofs, originalLength - eraseToOfs);
         }
     }
     BTreeParentIterator.RecalculateHeader(sector.Data, newCount);
 }
Example #2
0
 void SimplifyBTree(ref Sector sector, int mergeAroundIndex)
 {
     var iter = new BTreeParentIterator(sector.Data);
     if (iter.Count == 0 || mergeAroundIndex > iter.Count)
         return;
     var lenCurrent = ApproximateLengthOfBTreeChild(iter.GetChildSectorPtr(mergeAroundIndex));
     var lenPrevious = -1;
     if (mergeAroundIndex > 0)
         lenPrevious = ApproximateLengthOfBTreeChild(iter.GetChildSectorPtr(mergeAroundIndex - 1));
     var lenNext = -1;
     if (mergeAroundIndex < iter.Count)
         lenNext = ApproximateLengthOfBTreeChild(iter.GetChildSectorPtr(mergeAroundIndex + 1));
     ShouldMergeResult result = KeyValueDB.ShouldMergeBTreeParent(lenPrevious, lenCurrent, lenNext);
     if (result == ShouldMergeResult.NoMerge)
         return;
     if (result == ShouldMergeResult.MergeWithPrevious)
         mergeAroundIndex--;
     long mergedPairs;
     var leftSectorPtr = iter.GetChildSectorPtrWithKeyCount(mergeAroundIndex, out mergedPairs);
     Sector mergedSector;
     var leftSector = GetBTreeSector(leftSectorPtr, sector);
     long tempPairs;
     var rightSectorPtr = iter.GetChildSectorPtrWithKeyCount(mergeAroundIndex + 1, out tempPairs);
     mergedPairs += tempPairs;
     var rightSector = GetBTreeSector(rightSectorPtr, sector);
     Debug.Assert(leftSector.Type == rightSector.Type);
     iter.MoveTo(mergeAroundIndex);
     if (leftSector.Type == SectorType.BTreeChild)
     {
         var leftIter = new BTreeChildIterator(leftSector.Data);
         var rightIter = new BTreeChildIterator(rightSector.Data);
         if (!KeyValueDB.ShouldMerge2BTreeChild(leftIter.Count, leftIter.TotalLength, rightIter.Count,
                                                   rightIter.TotalLength))
             return;
         mergedSector = _owner.NewSector();
         mergedSector.Type = SectorType.BTreeChild;
         mergedSector.Parent = sector;
         mergedSector.SetLengthWithRound(leftIter.TotalLength + rightIter.TotalLength - BTreeChildIterator.HeaderSize);
         var mergedCount = leftIter.Count + rightIter.Count;
         BTreeChildIterator.SetCountToSectorData(mergedSector.Data, mergedCount);
         var ofs = BTreeChildIterator.HeaderSize + BTreeChildIterator.HeaderForEntry * mergedCount;
         Array.Copy(leftIter.Data, leftIter.FirstOffset, mergedSector.Data, ofs, leftIter.TotalLength - leftIter.FirstOffset);
         ofs += leftIter.TotalLength - leftIter.FirstOffset;
         Array.Copy(rightIter.Data, rightIter.FirstOffset, mergedSector.Data, ofs, rightIter.TotalLength - rightIter.FirstOffset);
         BTreeChildIterator.RecalculateHeader(mergedSector.Data, mergedCount);
     }
     else
     {
         var keyStorageLen = 4 + iter.KeyLenInline + (iter.HasKeySectorPtr ? KeyValueDB.PtrDownSize : 0);
         var leftIter = new BTreeParentIterator(leftSector.Data);
         var rightIter = new BTreeParentIterator(rightSector.Data);
         if (!KeyValueDB.ShouldMerge2BTreeParent(leftIter.Count, leftIter.TotalLength, rightIter.Count,
                                                    rightIter.TotalLength, keyStorageLen))
             return;
         mergedSector = _owner.NewSector();
         mergedSector.Type = SectorType.BTreeParent;
         mergedSector.Parent = sector;
         mergedSector.SetLengthWithRound(leftIter.TotalLength + rightIter.TotalLength + keyStorageLen);
         var mergedCount = leftIter.Count + rightIter.Count + 1;
         BTreeParentIterator.SetCountToSectorData(mergedSector.Data, mergedCount);
         Array.Copy(leftIter.Data, BTreeParentIterator.FirstChildSectorPtrOffset, mergedSector.Data,
                    BTreeParentIterator.FirstChildSectorPtrOffset, KeyValueDB.PtrDownSize + 8);
         var ofs = BTreeParentIterator.HeaderSize + BTreeParentIterator.HeaderForEntry * mergedCount;
         Array.Copy(leftIter.Data, leftIter.FirstOffset, mergedSector.Data, ofs, leftIter.TotalLength - leftIter.FirstOffset);
         ofs += leftIter.TotalLength - leftIter.FirstOffset;
         PackUnpack.PackInt32LE(mergedSector.Data, ofs, iter.KeyLen);
         ofs += 4;
         Array.Copy(rightIter.Data, BTreeParentIterator.FirstChildSectorPtrOffset, mergedSector.Data, ofs, KeyValueDB.PtrDownSize + 8);
         ofs += KeyValueDB.PtrDownSize + 8;
         Array.Copy(iter.Data, iter.KeyOffset, mergedSector.Data, ofs, keyStorageLen - 4);
         ofs += keyStorageLen - 4;
         Array.Copy(rightIter.Data, rightIter.FirstOffset, mergedSector.Data, ofs, rightIter.TotalLength - rightIter.FirstOffset);
         BTreeParentIterator.RecalculateHeader(mergedSector.Data, mergedCount);
     }
     _owner.PublishSector(mergedSector, true);
     _owner.DeallocateSector(leftSector);
     _owner.DeallocateSector(rightSector);
     InternalBTreeParentEraseRange(ref sector, ref iter, mergeAroundIndex, mergeAroundIndex + 1);
     new BTreeParentIterator(sector.Data).SetChildSectorPtrWithKeyCount(mergeAroundIndex,
                                                                        mergedSector.ToSectorPtr(),
                                                                        mergedPairs);
     _owner.TruncateSectorCache(true, 0);
 }
Example #3
0
        void ErasePartiallyParent(ref Sector sector, long firstKeyIndex, long lastKeyIndex)
        {
            sector = _owner.DirtizeSector(sector, sector.Parent, null);
            var iter = new BTreeParentIterator(sector.Data);
            int? firstChildErasedCompletely = null;
            int? lastChildErasedCompletely = null;
            int? firstChildErasedPartialy = null;

            if (firstKeyIndex < iter.FirstChildKeyCount)
            {
                firstChildErasedPartialy = 0;
                var childSectorPtr = iter.FirstChildSectorPtr;
                Sector childSector = GetBTreeSector(childSectorPtr, sector);
                if (firstKeyIndex == 0 && lastKeyIndex + 1 >= iter.FirstChildKeyCount)
                {
                    EraseCompletely(ref childSector);
                    firstChildErasedCompletely = 0;
                    lastChildErasedCompletely = 1;
                    lastKeyIndex -= iter.FirstChildKeyCount;
                }
                else
                {
                    var removeCount = Math.Min(lastKeyIndex + 1, iter.FirstChildKeyCount) - firstKeyIndex;
                    ErasePartially(ref childSector, firstKeyIndex, firstKeyIndex + removeCount - 1);
                    firstKeyIndex = 0;
                    lastKeyIndex -= iter.FirstChildKeyCount;
                    iter.FirstChildSectorPtr = childSector.ToSectorPtr();
                    iter.FirstChildKeyCount -= removeCount;
                }
            }
            else
            {
                firstKeyIndex -= iter.FirstChildKeyCount;
                lastKeyIndex -= iter.FirstChildKeyCount;
            }
            iter.MoveFirst();
            for (int i = 1; i <= iter.Count; i++, iter.MoveNext())
            {
                if (lastKeyIndex < 0) break;
                var childKeyCount = iter.ChildKeyCount;
                if (firstKeyIndex >= childKeyCount)
                {
                    firstKeyIndex -= childKeyCount;
                    lastKeyIndex -= childKeyCount;
                    continue;
                }
                if (!firstChildErasedPartialy.HasValue) firstChildErasedPartialy = i;
                var childSectorPtr = iter.ChildSectorPtr;
                Sector childSector = GetBTreeSector(childSectorPtr, sector);
                if (firstKeyIndex == 0 && lastKeyIndex + 1 >= childKeyCount)
                {
                    EraseCompletely(ref childSector);
                    if (!firstChildErasedCompletely.HasValue) firstChildErasedCompletely = i;
                    lastChildErasedCompletely = i + 1;
                    lastKeyIndex -= childKeyCount;
                }
                else
                {
                    var removeCount = Math.Min(lastKeyIndex + 1, childKeyCount) - firstKeyIndex;
                    ErasePartially(ref childSector, firstKeyIndex, firstKeyIndex + removeCount - 1);
                    iter.ChildSectorPtr = childSector.ToSectorPtr();
                    iter.ChildKeyCount -= removeCount;
                    if (firstKeyIndex == 0)
                    {
                        // update key because current key was removed
                        UpdateKeyAfterRemoval(ref sector, ref iter, childSector);
                        iter.MoveTo(i - 1);
                    }
                    lastKeyIndex -= childKeyCount;
                    firstKeyIndex = 0;
                }
            }
            if (firstChildErasedCompletely.HasValue)
            {
                InternalBTreeParentEraseRange(ref sector, ref iter, firstChildErasedCompletely.Value, lastChildErasedCompletely.Value);
            }
            SimplifyBTree(ref sector, firstChildErasedPartialy ?? 0);
        }