Beispiel #1
0
        internal static void IncrementChildCount(byte[] parentData, long childPos)
        {
            var iterParent = new BTreeParentIterator(parentData);

            if ((iterParent.FirstChildSectorPos & KeyValueDB.MaskOfPosition) == childPos)
            {
                iterParent.IncrementFirstChildKeyCount();
                return;
            }
            if (iterParent.Count != 0)
            {
                iterParent.MoveFirst();
                do
                {
                    if ((iterParent.ChildSectorPos & KeyValueDB.MaskOfPosition) == childPos)
                    {
                        iterParent.IncrementChildKeyCount();
                        return;
                    }
                } while (iterParent.MoveNext());
            }
            throw new BTDBException("ModifyChildCount child not found");
        }
Beispiel #2
0
 static ulong CalcKeysInSector(Sector sector)
 {
     if (sector.Type == SectorType.BTreeChild)
     {
         return BTreeChildIterator.CountFromSectorData(sector.Data);
     }
     Debug.Assert(sector.Type == SectorType.BTreeParent);
     var iter = new BTreeParentIterator(sector.Data);
     var res = (ulong)iter.FirstChildKeyCount;
     if (iter.Count != 0)
     {
         iter.MoveFirst();
         do
         {
             res += (ulong)iter.ChildKeyCount;
         } while (iter.MoveNext());
     }
     return res;
 }
Beispiel #3
0
 public bool FindPreviousKey()
 {
     if (_currentKeyIndexInLeaf < 0) throw new BTDBException("Current Key is invalid");
     if (_currentKeyIndex == _prefixKeyStart) return false;
     try
     {
         if (_currentKeyIndexInLeaf > 0)
         {
             _currentKeyIndexInLeaf--;
             _currentKeyIndex--;
             _owner.UpdateLastAccess(_currentKeySector);
             return true;
         }
         var sector = _currentKeySector;
         var parent = PopCurrentKeyParent();
         while (parent != null)
         {
             var iter = new BTreeParentIterator(parent.Data);
             var childByPos = iter.FindChildByPos(sector.Position);
             if (childByPos == 0)
             {
                 sector = parent;
                 parent = PopCurrentKeyParent();
                 continue;
             }
             var childSectorPtr = iter.GetChildSectorPtr(childByPos - 1);
             while (true)
             {
                 sector = LoadBTreeSector(childSectorPtr);
                 if (sector.Type == SectorType.BTreeChild)
                 {
                     _currentKeyIndexInLeaf = (int)(BTreeChildIterator.CountFromSectorData(sector.Data) - 1);
                     _currentKeyIndex--;
                     return true;
                 }
                 iter = new BTreeParentIterator(sector.Data);
                 childSectorPtr = iter.GetChildSectorPtr(iter.Count);
             }
         }
         throw new BTDBException("Internal error");
     }
     catch
     {
         InvalidateCurrentKey();
         throw;
     }
 }
Beispiel #4
0
 void UpdateKeyAfterRemoval(ref Sector sector, ref BTreeParentIterator iter, Sector childSector)
 {
     var entryOffset = iter.EntryOffset;
     var nextEntryOffset = iter.NextEntryOffset;
     var originalEntryLength = nextEntryOffset - entryOffset;
     byte[] data;
     int ofs;
     int len;
     int keyLen;
     ExtractFirstKey(childSector, out data, out ofs, out len, out keyLen);
     var newEntryLength = BTreeParentIterator.CalcEntrySize(keyLen);
     // structure of data is inlinekey/var, [downptr/12]
     int originalLength = iter.TotalLength;
     sector = _owner.ResizeSectorNoUpdatePosition(sector,
                                                  originalLength - originalEntryLength + newEntryLength,
                                                  sector.Parent,
                                                  null);
     Array.Copy(iter.Data, 0, sector.Data, 0, iter.KeyOffset);
     Array.Copy(iter.Data, nextEntryOffset, sector.Data, entryOffset + newEntryLength, originalLength - nextEntryOffset);
     PackUnpack.PackInt32LE(sector.Data, entryOffset, keyLen);
     Array.Copy(data, ofs, sector.Data, iter.KeyOffset, len);
     BTreeParentIterator.RecalculateHeader(sector.Data, iter.Count);
     iter = new BTreeParentIterator(sector.Data);
 }
Beispiel #5
0
 void SimplifySingleSubChild(ref Sector sector)
 {
     while (sector.Type == SectorType.BTreeParent)
     {
         var iter = new BTreeParentIterator(sector.Data);
         if (iter.Count > 0) break;
         var sectorPtr = iter.FirstChildSectorPtr;
         _owner.DeallocateSector(sector);
         sector = GetBTreeSector(sectorPtr, null);
         _owner.NewState.RootBTreeLevels--;
     }
 }
Beispiel #6
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);
 }
Beispiel #7
0
 public bool FindNextKey()
 {
     if (_currentKeyIndexInLeaf < 0) throw new BTDBException("Current Key is invalid");
     if (_prefixKeyCount != -1 && _currentKeyIndex + 1 >= _prefixKeyStart + _prefixKeyCount) return false;
     try
     {
         if (_currentKeyIndexInLeaf + 1 < BTreeChildIterator.CountFromSectorData(_currentKeySector.Data))
         {
             _owner.UpdateLastAccess(_currentKeySector);
             _currentKeyIndexInLeaf++;
             if (CheckPrefix())
             {
                 _currentKeyIndex++;
                 return true;
             }
             _prefixKeyCount = _currentKeyIndex - _prefixKeyStart + 1;
             _currentKeyIndexInLeaf--;
             return false;
         }
         var sector = _currentKeySector;
         var parent = PopCurrentKeyParent();
         if (parent == null)
         {
             _prefixKeyCount = _currentKeyIndex - _prefixKeyStart + 1;
             FindLastKey();
             return false;
         }
         while (true)
         {
             var iter = new BTreeParentIterator(parent.Data);
             var childByPos = iter.FindChildByPos(sector.Position);
             if (childByPos == iter.Count)
             {
                 sector = parent;
                 parent = PopCurrentKeyParent();
                 if (parent == null)
                 {
                     _prefixKeyCount = _currentKeyIndex - _prefixKeyStart + 1;
                     FindLastKey();
                     return false;
                 }
                 continue;
             }
             var childSectorPtr = iter.GetChildSectorPtr(childByPos + 1);
             while (true)
             {
                 sector = LoadBTreeSector(childSectorPtr);
                 if (sector.Type == SectorType.BTreeChild)
                 {
                     _currentKeyIndexInLeaf = 0;
                     _currentKeyIndex++;
                     if (CheckPrefix())
                     {
                         return true;
                     }
                     _prefixKeyCount = _currentKeyIndex - _prefixKeyStart;
                     FindPreviousKey();
                     return false;
                 }
                 iter = new BTreeParentIterator(sector.Data);
                 childSectorPtr = iter.GetChildSectorPtr(0);
             }
         }
     }
     catch
     {
         InvalidateCurrentKey();
         throw;
     }
 }
Beispiel #8
0
 internal void FixChildrenParentPointers(Sector parent)
 {
     switch (parent.Type)
     {
         case SectorType.BTreeParent:
             {
                 var iter = new BTreeParentIterator(parent.Data);
                 for (int i = 0; i <= iter.Count; i++)
                 {
                     var childSectorPos = iter.GetChildSectorPos(i);
                     FixChildParentPointer(childSectorPos, parent);
                 }
                 break;
             }
         case SectorType.BTreeChild:
             {
                 var iter = new BTreeChildIterator(parent.Data);
                 iter.MoveFirst();
                 do
                 {
                     if (iter.HasKeySectorPtr)
                         FixChildParentPointer(iter.KeySectorPos, parent);
                     if (iter.HasValueSectorPtr)
                         FixChildParentPointer(iter.ValueSectorPos, parent);
                 } while (iter.MoveNext());
                 break;
             }
         case SectorType.DataChild:
         case SectorType.AllocChild:
             break;
         case SectorType.AllocParent:
         case SectorType.DataParent:
             {
                 var ptrCount = parent.Length / PtrDownSize;
                 for (int i = 0; i < ptrCount; i++)
                 {
                     var sectorPos = PackUnpack.UnpackInt64LE(parent.Data, i * PtrDownSize);
                     if (sectorPos == 0) break;
                     FixChildParentPointer(sectorPos, parent);
                 }
             }
             break;
         default:
             throw new InvalidOperationException();
     }
 }
Beispiel #9
0
 private FindKeyResult FindKey(byte[] keyBuf, int keyOfs, int keyLen, FindKeyStrategy strategy, byte[] valueBuf, int valueOfs, int valueLen)
 {
     if (keyLen < 0) throw new ArgumentOutOfRangeException("keyLen");
     if (strategy == FindKeyStrategy.Create) UpgradeToWriteTransaction();
     InvalidateCurrentKey();
     var rootBTree = GetRootBTreeSectorPtr();
     if (rootBTree.Ptr == 0)
     {
         return FindKeyInEmptyBTree(keyBuf, keyOfs, keyLen, strategy, valueBuf, valueOfs, valueLen);
     }
     Sector sector;
     try
     {
         long keyIndex = 0;
         while (true)
         {
             sector = LoadBTreeSector(rootBTree);
             if (sector.Type == SectorType.BTreeChild) break;
             var iterParent = new BTreeParentIterator(sector.Data);
             int bindexParent = iterParent.BinarySearch(_prefix, keyBuf, keyOfs, keyLen, sector, SectorDataCompare);
             rootBTree = iterParent.GetChildSectorPtr((bindexParent + 1) / 2, ref keyIndex);
         }
         var iter = new BTreeChildIterator(sector.Data);
         int bindex = iter.BinarySearch(_prefix, keyBuf, keyOfs, keyLen, sector, SectorDataCompare);
         _currentKeyIndexInLeaf = bindex / 2;
         _currentKeyIndex = keyIndex + _currentKeyIndexInLeaf;
         if ((bindex & 1) != 0)
         {
             return FindKeyResult.FoundExact;
         }
         if (strategy != FindKeyStrategy.Create)
         {
             return FindKeyNoncreateStrategy(strategy, iter);
         }
         int additionalLengthNeeded = BTreeChildIterator.HeaderForEntry +
             (valueLen >= 0 ? BTreeChildIterator.CalcEntrySize(_prefix.Length + keyLen, valueLen) :
             BTreeChildIterator.CalcEntrySize(_prefix.Length + keyLen));
         if (KeyValueDB.ShouldSplitBTreeChild(iter.TotalLength, additionalLengthNeeded, iter.Count))
         {
             SplitBTreeChild(keyBuf, keyOfs, keyLen, valueBuf, valueOfs, valueLen, sector, iter, additionalLengthNeeded);
         }
         else
         {
             var origsector = sector;
             sector = _owner.ResizeSectorWithUpdatePosition(sector, iter.TotalLength + additionalLengthNeeded,
                                                            sector.Parent, _currentKeySectorParents);
             if (sector != origsector)
             {
                 Array.Copy(origsector.Data, sector.Data, origsector.Data.Length);
                 _owner.FixChildrenParentPointers(sector);
             }
             _currentKeySector = sector;
             int insertOfs = iter.AddEntry(additionalLengthNeeded, sector.Data, _currentKeyIndexInLeaf);
             IncrementChildCountInBTreeParents(sector);
             SetBTreeChildKeyData(sector, keyBuf, keyOfs, keyLen, valueBuf, valueOfs, valueLen, insertOfs);
         }
         _owner.NewState.KeyValuePairCount++;
         if (_prefixKeyCount != -1) _prefixKeyCount++;
         return FindKeyResult.Created;
     }
     catch
     {
         InvalidateCurrentKey();
         throw;
     }
 }
Beispiel #10
0
 void ExtractFirstKey(Sector sector, out byte[] data, out int ofs, out int len, out int keyLen)
 {
     if (sector.Type == SectorType.BTreeChild)
     {
         var iter = new BTreeChildIterator(sector.Data);
         iter.MoveFirst();
         data = iter.Data;
         ofs = iter.KeyOffset;
         len = iter.ValueOffset - ofs;
         keyLen = iter.KeyLen;
         if (iter.HasKeySectorPtr) ForceKeyFlush(iter.KeySectorPtr, iter.KeyLen - iter.KeyLenInline, sector);
         Debug.Assert(data == sector.Data);
         return;
     }
     else
     {
         var iter = new BTreeParentIterator(sector.Data);
         var childSector = GetBTreeSector(iter.FirstChildSectorPtr, sector);
         ExtractFirstKey(childSector, out data, out ofs, out len, out keyLen);
     }
 }
Beispiel #11
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);
        }
Beispiel #12
0
 internal static void IncrementChildCount(byte[] parentData, long childPos)
 {
     var iterParent = new BTreeParentIterator(parentData);
     if ((iterParent.FirstChildSectorPos & KeyValueDB.MaskOfPosition) == childPos)
     {
         iterParent.IncrementFirstChildKeyCount();
         return;
     }
     if (iterParent.Count != 0)
     {
         iterParent.MoveFirst();
         do
         {
             if ((iterParent.ChildSectorPos & KeyValueDB.MaskOfPosition) == childPos)
             {
                 iterParent.IncrementChildKeyCount();
                 return;
             }
         } while (iterParent.MoveNext());
     }
     throw new BTDBException("ModifyChildCount child not found");
 }
Beispiel #13
0
 static int FindOfsInParent(Sector sector, Sector where)
 {
     switch (where.Type)
     {
         case SectorType.BTreeParent:
             {
                 var iter = new BTreeParentIterator(where.Data);
                 if ((iter.FirstChildSectorPos & MaskOfPosition) == sector.Position)
                     return BTreeParentIterator.FirstChildSectorPtrOffset;
                 if (iter.Count != 0)
                 {
                     iter.MoveFirst();
                     do
                     {
                         if ((iter.KeySectorPos & MaskOfPosition) == sector.Position)
                             return iter.KeySectorPtrOffset;
                         if ((iter.ChildSectorPos & MaskOfPosition) == sector.Position)
                             return iter.ChildSectorPtrOffset;
                     }
                     while (iter.MoveNext());
                 }
                 throw new BTDBException("Cannot FindOfsInParent");
             }
         case SectorType.BTreeChild:
             {
                 var iter = new BTreeChildIterator(where.Data);
                 iter.MoveFirst();
                 do
                 {
                     if ((iter.KeySectorPos & MaskOfPosition) == sector.Position)
                         return iter.KeySectorPtrOffset;
                     if ((iter.ValueSectorPos & MaskOfPosition) == sector.Position)
                         return iter.ValueSectorPtrOffset;
                 }
                 while (iter.MoveNext());
                 throw new BTDBException("Cannot FindOfsInParent");
             }
         case SectorType.AllocParent:
         case SectorType.DataParent:
             for (int i = 0; i < where.Length / PtrDownSize; i++)
             {
                 if ((PackUnpack.UnpackInt64LE(where.Data, i * PtrDownSize) & MaskOfPosition) == sector.Position)
                     return i * PtrDownSize;
             }
             throw new BTDBException("Cannot FindOfsInParent");
         case SectorType.DataChild:
             throw new BTDBException("DataChild cannot be parent");
         case SectorType.AllocChild:
             throw new BTDBException("AllocChild cannot be parent");
         default:
             throw new ArgumentOutOfRangeException();
     }
 }
Beispiel #14
0
 void AddToBTreeParent(Sector leftSector, Sector rightSector, byte[] middleKeyData, int middleKeyLen, int middleKeyOfs, int middleKeyLenInSector)
 {
     var parentSector = leftSector.Parent;
     var iter = new BTreeParentIterator(parentSector.Data);
     int additionalLengthNeeded = BTreeParentIterator.HeaderForEntry + BTreeParentIterator.CalcEntrySize(middleKeyLen);
     int leftIndexInParent = iter.FindChildByPos(leftSector.Position);
     bool splitting = true;
     if (!KeyValueDB.ShouldSplitBTreeParent(iter.TotalLength, additionalLengthNeeded, iter.Count + 1))
     {
         parentSector = _owner.ResizeSectorWithUpdatePositionNoWriteTruncate(
             parentSector,
             iter.TotalLength + additionalLengthNeeded,
             parentSector.Parent,
             _currentKeySectorParents);
         splitting = false;
     }
     var mergedData = new byte[iter.TotalLength + additionalLengthNeeded];
     BTreeParentIterator.SetCountToSectorData(mergedData, iter.Count + 1);
     int ofs;
     int splitOfs = iter.OffsetOfIndex(leftIndexInParent);
     if (leftIndexInParent == 0)
     {
         SectorPtr.Pack(mergedData, BTreeParentIterator.FirstChildSectorPtrOffset, leftSector.ToSectorPtr());
         PackUnpack.PackUInt64LE(mergedData, BTreeParentIterator.FirstChildSectorPtrOffset + KeyValueDB.PtrDownSize, CalcKeysInSector(leftSector));
         ofs = BTreeParentIterator.HeaderSize + BTreeParentIterator.HeaderForEntry * (iter.Count + 1);
     }
     else
     {
         Array.Copy(iter.Data, BTreeParentIterator.FirstChildSectorPtrOffset, mergedData, BTreeParentIterator.FirstChildSectorPtrOffset, KeyValueDB.PtrDownSize + 8);
         ofs = BTreeParentIterator.HeaderSize + BTreeParentIterator.HeaderForEntry * (iter.Count + 1);
         int splitOfsPrev = iter.OffsetOfIndex(leftIndexInParent - 1);
         Array.Copy(iter.Data, iter.FirstOffset, mergedData, ofs, splitOfsPrev - iter.FirstOffset);
         ofs += splitOfsPrev - iter.FirstOffset;
         Array.Copy(iter.Data, splitOfsPrev, mergedData, ofs, 4 + KeyValueDB.PtrDownSize);
         ofs += 4 + KeyValueDB.PtrDownSize;
         PackUnpack.PackUInt64LE(mergedData, ofs, CalcKeysInSector(leftSector));
         ofs += 8;
         splitOfsPrev += 4 + KeyValueDB.PtrDownSize + 8;
         Array.Copy(iter.Data, splitOfsPrev, mergedData, ofs, splitOfs - splitOfsPrev);
         ofs += splitOfs - splitOfsPrev;
     }
     PackUnpack.PackInt32LE(mergedData, ofs, middleKeyLen);
     ofs += 4;
     SectorPtr.Pack(mergedData, ofs, rightSector.ToSectorPtr());
     ofs += KeyValueDB.PtrDownSize;
     PackUnpack.PackUInt64LE(mergedData, ofs, CalcKeysInSector(rightSector));
     ofs += 8;
     Array.Copy(middleKeyData, middleKeyOfs, mergedData, ofs, middleKeyLenInSector);
     ofs += middleKeyLenInSector;
     Array.Copy(iter.Data, splitOfs, mergedData, ofs, iter.TotalLength - splitOfs);
     BTreeParentIterator.RecalculateHeader(mergedData, iter.Count + 1);
     if (!splitting)
     {
         Array.Copy(mergedData, parentSector.Data, mergedData.Length);
         leftSector.Parent = parentSector;
         rightSector.Parent = parentSector;
         IncrementChildCountInBTreeParents(parentSector);
         _owner.FixChildrenParentPointers(parentSector);
     }
     else
     {
         iter = new BTreeParentIterator(mergedData);
         int middleoffset = mergedData.Length / 2;
         iter.MoveFirst();
         int splitIndex = 0;
         int currentPos = iter.FirstOffset;
         while (currentPos < middleoffset)
         {
             currentPos += iter.CurrentEntrySize;
             splitIndex++;
             iter.MoveNext();
         }
         Sector leftParentSector = null;
         Sector rightParentSector = null;
         try
         {
             rightParentSector = _owner.NewSector();
             rightParentSector.Type = SectorType.BTreeParent;
             var rightCount = iter.Count - splitIndex - 1;
             var rightFirstOffset = BTreeParentIterator.HeaderSize + rightCount * BTreeParentIterator.HeaderForEntry;
             rightParentSector.SetLengthWithRound(rightFirstOffset + mergedData.Length - iter.NextEntryOffset);
             BTreeParentIterator.SetCountToSectorData(rightParentSector.Data, rightCount);
             rightParentSector.Parent = parentSector.Parent;
             var leftFirstOffset = BTreeParentIterator.HeaderSize + splitIndex * BTreeParentIterator.HeaderForEntry;
             leftParentSector = _owner.ResizeSectorWithUpdatePosition(parentSector,
                                                                      leftFirstOffset + currentPos -
                                                                      iter.FirstOffset, parentSector.Parent,
                                                                      _currentKeySectorParents);
             BTreeParentIterator.SetCountToSectorData(leftParentSector.Data, splitIndex);
             leftSector.Parent = leftParentSector;
             rightSector.Parent = leftParentSector;
             Array.Copy(mergedData, BTreeParentIterator.FirstChildSectorPtrOffset, leftParentSector.Data,
                        BTreeParentIterator.FirstChildSectorPtrOffset,
                        KeyValueDB.PtrDownSize + 8 + BTreeParentIterator.HeaderForEntry * splitIndex);
             Array.Copy(mergedData, iter.FirstOffset, leftParentSector.Data, leftFirstOffset,
                        currentPos - iter.FirstOffset);
             Array.Copy(mergedData, iter.ChildSectorPtrOffset, rightParentSector.Data, BTreeParentIterator.FirstChildSectorPtrOffset, KeyValueDB.PtrDownSize + 8);
             Array.Copy(mergedData, iter.NextEntryOffset, rightParentSector.Data, rightFirstOffset, iter.TotalLength - iter.NextEntryOffset);
             BTreeParentIterator.RecalculateHeader(rightParentSector.Data, rightCount);
             _owner.FixChildrenParentPointers(leftParentSector);
             _owner.PublishSector(rightParentSector, true);
             Interlocked.Increment(ref leftParentSector.ChildrenInCache);
             Interlocked.Increment(ref rightParentSector.ChildrenInCache);
             try
             {
                 _owner.TruncateSectorCache(true, 0);
                 int keyLenInSector = iter.KeyLenInline + (iter.HasKeySectorPtr ? KeyValueDB.PtrDownSize : 0);
                 if (leftParentSector.Parent == null)
                 {
                     CreateBTreeParentFromTwoChildren(leftParentSector, rightParentSector, iter.Data, iter.KeyLen, iter.KeyOffset, keyLenInSector);
                 }
                 else
                 {
                     AddToBTreeParent(leftParentSector, rightParentSector, iter.Data, iter.KeyLen, iter.KeyOffset, keyLenInSector);
                 }
             }
             finally
             {
                 Interlocked.Decrement(ref leftParentSector.ChildrenInCache);
                 Interlocked.Decrement(ref rightParentSector.ChildrenInCache);
             }
         }
         finally
         {
             if (leftSector.Parent == rightParentSector)
             {
                 for (int i = 0; i < _currentKeySectorParents.Count; i++)
                 {
                     if (_currentKeySectorParents[i] == leftParentSector)
                     {
                         _currentKeySectorParents[i] = rightParentSector;
                         break;
                     }
                 }
             }
         }
     }
 }
Beispiel #15
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);
 }
Beispiel #16
0
 void EraseCompletely(ref Sector sector)
 {
     if (sector.Type == SectorType.BTreeChild)
     {
         var iter = new BTreeChildIterator(sector.Data);
         iter.MoveFirst();
         do
         {
             if (iter.HasKeySectorPtr)
                 DeleteContentSector(iter.KeySectorPtr, iter.KeyLen - iter.KeyLenInline, sector);
             if (iter.HasValueSectorPtr)
                 DeleteContentSector(iter.ValueSectorPtr, iter.ValueLen - iter.ValueLenInline, sector);
         } while (iter.MoveNext());
     }
     else
     {
         var iter = new BTreeParentIterator(sector.Data);
         for (int i = 0; i <= iter.Count; i++)
         {
             var childSectorPtr = iter.GetChildSectorPtr(i);
             var childSector = GetBTreeSector(childSectorPtr, sector);
             EraseCompletely(ref childSector);
         }
     }
     _owner.DeallocateSector(sector);
     sector = null;
 }
Beispiel #17
0
 bool CheckBTree(SectorPtr sectorPtr)
 {
     byte[] sector = CheckSector(sectorPtr);
     if (sector == null) return false;
     if (BTreeChildIterator.IsChildFromSectorData(sector))
     {
         var iter = new BTreeChildIterator(sector);
         iter.MoveFirst();
         do
         {
             if (iter.HasKeySectorPtr)
             {
                 if (!CheckDataPages(iter.KeySectorPtr, iter.KeyLen - iter.KeyLenInline)) return false;
             }
             if (iter.HasValueSectorPtr)
             {
                 if (!CheckDataPages(iter.ValueSectorPtr, iter.ValueLen - iter.ValueLenInline)) return false;
             }
         } while (iter.MoveNext());
     }
     else
     {
         var iter = new BTreeParentIterator(sector);
         if (!CheckBTree(iter.FirstChildSectorPtr)) return false;
         iter.MoveFirst();
         do
         {
             if (iter.HasKeySectorPtr)
             {
                 if (!CheckDataPages(iter.KeySectorPtr, iter.KeyLen - iter.KeyLenInline)) return false;
             }
             if (!CheckBTree(iter.ChildSectorPtr)) return false;
         } while (iter.MoveNext());
     }
     return true;
 }