Пример #1
0
 public void PeekValue(long ofs, out int len, out byte[] buf, out int bufOfs)
 {
     ThrowIfCurrentKeyIsInvalid();
     var iter = new BTreeChildIterator(_currentKeySector.Data);
     iter.MoveTo(_currentKeyIndexInLeaf);
     if (ofs < 0 || ofs >= iter.ValueLen)
     {
         len = 0;
         buf = null;
         bufOfs = 0;
         return;
     }
     if (ofs >= iter.ValueLen - iter.ValueLenInline)
     {
         len = (int)(iter.ValueLen - ofs);
         buf = _currentKeySector.Data;
         bufOfs = iter.ValueOffset + iter.ValueLenInline - len;
         return;
     }
     SectorPtr dataSectorPtr = iter.ValueSectorPtr;
     long dataLen = iter.ValueLen - iter.ValueLenInline;
     Sector parentOfSector = _currentKeySector;
     Debug.Assert(ofs < dataLen);
     while (true)
     {
         Sector dataSector = GetOrReadDataSector(dataSectorPtr, dataLen, parentOfSector);
         if (dataSector.Type == SectorType.DataChild)
         {
             buf = dataSector.Data;
             bufOfs = (int)ofs;
             len = (int)(dataSector.Length - ofs);
             return;
         }
         parentOfSector = dataSector;
         int downPtrCount;
         long bytesInDownLevel = KeyValueDB.GetBytesInDownLevel(dataLen, out downPtrCount);
         var i = (int)(ofs / bytesInDownLevel);
         ofs = ofs % bytesInDownLevel;
         dataSectorPtr = SectorPtr.Unpack(dataSector.Data, i * KeyValueDB.PtrDownSize);
         if (i < downPtrCount - 1)
         {
             dataLen = bytesInDownLevel;
         }
         else
         {
             dataLen = dataLen % bytesInDownLevel;
             if (dataLen == 0) dataLen = bytesInDownLevel;
         }
     }
 }
Пример #2
0
 public void ReadKey(int ofs, int len, byte[] buf, int bufOfs)
 {
     ThrowIfCurrentKeyIsInvalid();
     ofs += _prefix.Length;
     var iter = new BTreeChildIterator(_currentKeySector.Data);
     iter.MoveTo(_currentKeyIndexInLeaf);
     var keyLen = iter.KeyLen;
     if (ofs < 0 || ofs > keyLen) throw new ArgumentOutOfRangeException("ofs");
     if (len < 0 || ofs + len > keyLen) throw new ArgumentOutOfRangeException("len");
     if (len == 0) return;
     var keyLenInline = iter.KeyLenInline;
     if (ofs < keyLenInline)
     {
         var copyLen = Math.Min(len, keyLenInline - ofs);
         Array.Copy(_currentKeySector.Data, iter.KeyOffset + ofs, buf, bufOfs, copyLen);
         len -= copyLen;
         bufOfs += copyLen;
         ofs += copyLen;
     }
     if (len > 0)
     {
         ofs -= keyLenInline;
         int dataLen = keyLen - keyLenInline;
         RecursiveReadOverflown(ofs, iter.KeySectorPtr, _currentKeySector, dataLen, buf, ref bufOfs, ref len);
     }
 }
Пример #3
0
 public long GetValueSize()
 {
     if (_currentKeyIndexInLeaf < 0) return -1;
     var iter = new BTreeChildIterator(_currentKeySector.Data);
     iter.MoveTo(_currentKeyIndexInLeaf);
     return iter.ValueLen;
 }
Пример #4
0
 public void PeekKey(int ofs, out int len, out byte[] buf, out int bufOfs)
 {
     ThrowIfCurrentKeyIsInvalid();
     ofs += _prefix.Length;
     var iter = new BTreeChildIterator(_currentKeySector.Data);
     iter.MoveTo(_currentKeyIndexInLeaf);
     if (ofs >= iter.KeyLen)
     {
         len = 0;
         buf = null;
         bufOfs = 0;
         return;
     }
     if (ofs < iter.KeyLenInline)
     {
         len = iter.KeyLenInline - ofs;
         buf = _currentKeySector.Data;
         bufOfs = iter.KeyOffset + ofs;
         return;
     }
     ofs -= iter.KeyLenInline;
     SectorPtr dataSectorPtr = iter.KeySectorPtr;
     int dataLen = iter.KeyLen - iter.KeyLenInline;
     Sector parentOfSector = _currentKeySector;
     while (true)
     {
         Sector dataSector = GetOrReadDataSector(dataSectorPtr, dataLen, parentOfSector);
         if (dataSector.Type == SectorType.DataChild)
         {
             buf = dataSector.Data;
             bufOfs = ofs;
             len = dataSector.Length - ofs;
             return;
         }
         parentOfSector = dataSector;
         int downPtrCount;
         var bytesInDownLevel = (int)KeyValueDB.GetBytesInDownLevel(dataLen, out downPtrCount);
         int i = ofs / bytesInDownLevel;
         ofs = ofs % bytesInDownLevel;
         dataSectorPtr = SectorPtr.Unpack(dataSector.Data, i * KeyValueDB.PtrDownSize);
         if (i < downPtrCount - 1)
         {
             dataLen = bytesInDownLevel;
         }
         else
         {
             dataLen = dataLen % bytesInDownLevel;
             if (dataLen == 0) dataLen = bytesInDownLevel;
         }
     }
 }
Пример #5
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;
 }
Пример #6
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();
     }
 }
Пример #7
0
 void InternalWriteValue(long ofs, int len, byte[] buf, int bufOfs)
 {
     _currentKeySector = _owner.DirtizeSector(_currentKeySector, _currentKeySector.Parent, _currentKeySectorParents);
     var iter = new BTreeChildIterator(_currentKeySector.Data);
     iter.MoveTo(_currentKeyIndexInLeaf);
     var valueLen = iter.ValueLen;
     var valueLenInline = iter.ValueLenInline;
     if (ofs + len > valueLen - valueLenInline)
     {
         var inlineEnd = (int)(ofs + len - (valueLen - valueLenInline));
         var inlineStart = 0;
         if (ofs > valueLen - valueLenInline)
         {
             inlineStart = (int)(ofs - (valueLen - valueLenInline));
         }
         if (buf != null)
         {
             var inlineBufOfs = bufOfs + (int)(valueLen - valueLenInline + inlineStart - ofs);
             Array.Copy(buf, inlineBufOfs, iter.Data, iter.ValueOffset + inlineStart, inlineEnd - inlineStart);
         }
         else
         {
             Array.Clear(iter.Data, iter.ValueOffset + inlineStart, inlineEnd - inlineStart);
         }
         len -= inlineEnd - inlineStart;
         if (len == 0) return;
     }
     RecursiveWriteValue(iter.ValueSectorPtr, valueLen - valueLenInline, ofs, len, buf, bufOfs, _currentKeySector, iter.ValueSectorPtrOffset);
 }
Пример #8
0
 public void SetValueSize(long newSize)
 {
     if (newSize < 0) throw new ArgumentOutOfRangeException("newSize");
     if (_currentKeyIndexInLeaf < 0) throw new BTDBException("Current Key is invalid");
     var iter = new BTreeChildIterator(_currentKeySector.Data);
     iter.MoveTo(_currentKeyIndexInLeaf);
     long oldSize = iter.ValueLen;
     if (oldSize == newSize) return;
     UpgradeToWriteTransaction();
     int oldInlineSize = BTreeChildIterator.CalcValueLenInline(oldSize);
     int newInlineSize = BTreeChildIterator.CalcValueLenInline(newSize);
     var newEndContent = new byte[newInlineSize];
     byte[] oldEndContent = null;
     long newEndContentOfs = newSize - newEndContent.Length;
     if (oldSize < newSize)
     {
         oldEndContent = new byte[oldInlineSize];
         ReadValue(oldSize - oldInlineSize, oldInlineSize, oldEndContent, 0);
     }
     else
     {
         ReadValue(newEndContentOfs, (int)Math.Min(newEndContent.Length, oldSize - newEndContentOfs), newEndContent, 0);
     }
     long oldDeepSize = oldSize - oldInlineSize;
     long newDeepSize = newSize - newInlineSize;
     if (oldDeepSize > 0 && newDeepSize == 0)
         DeleteContentSector(iter.ValueSectorPtr, oldDeepSize, _currentKeySector);
     _currentKeySector = _owner.ResizeSectorWithUpdatePosition(_currentKeySector, iter.TotalLength - iter.CurrentEntrySize + BTreeChildIterator.CalcEntrySize(iter.KeyLen, newSize), _currentKeySector.Parent, _currentKeySectorParents);
     iter.ResizeValue(_currentKeySector.Data, newSize);
     _owner.FixChildrenParentPointers(_currentKeySector);
     if (oldDeepSize != newDeepSize)
     {
         if (oldDeepSize == 0)
         {
             CreateContentSector(newDeepSize, _currentKeySector, iter.ValueSectorPtrOffset);
         }
         else if (newDeepSize != 0)
         {
             ResizeContentSector(iter.ValueSectorPtr, oldDeepSize, _currentKeySector, iter.ValueSectorPtrOffset, newDeepSize, null, 0);
         }
     }
     if (newEndContent.Length > 0) InternalWriteValue(newEndContentOfs, newEndContent.Length, newEndContent, 0);
     if (oldEndContent != null && oldEndContent.Length > 0) InternalWriteValue(oldSize - oldInlineSize, oldInlineSize, oldEndContent, 0);
 }
Пример #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;
     }
 }
Пример #10
0
 FindKeyResult FindKeyNoncreateStrategy(FindKeyStrategy strategy, BTreeChildIterator iter)
 {
     switch (strategy)
     {
         case FindKeyStrategy.ExactMatch:
             return FindKeyNotFound();
         case FindKeyStrategy.OnlyNext:
             if (_currentKeyIndexInLeaf < iter.Count)
             {
                 return FindKeyResult.FoundNext;
             }
             _currentKeyIndexInLeaf--;
             _currentKeyIndex--;
             return FindNextKey() ? FindKeyResult.FoundNext : FindKeyNotFound();
         case FindKeyStrategy.PreferNext:
             if (_currentKeyIndexInLeaf < iter.Count)
             {
                 return FindKeyResult.FoundNext;
             }
             _currentKeyIndexInLeaf--;
             _currentKeyIndex--;
             return FindNextKey() ? FindKeyResult.FoundNext : FindKeyResult.FoundPrevious;
         case FindKeyStrategy.OnlyPrevious:
             if (_currentKeyIndexInLeaf > 0)
             {
                 _currentKeyIndexInLeaf--;
                 _currentKeyIndex--;
                 return FindKeyResult.FoundPrevious;
             }
             return FindPreviousKey() ? FindKeyResult.FoundPrevious : FindKeyNotFound();
         case FindKeyStrategy.PreferPrevious:
             if (_currentKeyIndexInLeaf > 0)
             {
                 _currentKeyIndexInLeaf--;
                 _currentKeyIndex--;
                 return FindKeyResult.FoundPrevious;
             }
             return FindPreviousKey() ? FindKeyResult.FoundPrevious : FindKeyResult.FoundNext;
         default:
             throw new ArgumentOutOfRangeException("strategy");
     }
 }
Пример #11
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);
     }
 }
Пример #12
0
 internal static int CalcEntrySize(int keyLen)
 {
     return(4 + KeyValueDB.PtrDownSize + 8 + BTreeChildIterator.CalcKeyLenInline(keyLen) +
            (keyLen > BTreeChildIterator.MaxKeyLenInline ? KeyValueDB.PtrDownSize : 0));
 }
Пример #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();
     }
 }
Пример #14
0
 public void ReadValue(long ofs, int len, byte[] buf, int bufOfs)
 {
     ThrowIfCurrentKeyIsInvalid();
     var iter = new BTreeChildIterator(_currentKeySector.Data);
     iter.MoveTo(_currentKeyIndexInLeaf);
     var valueLen = iter.ValueLen;
     if (ofs < 0 || ofs > valueLen) throw new ArgumentOutOfRangeException("ofs");
     if (len < 0 || ofs + len > valueLen) throw new ArgumentOutOfRangeException("len");
     if (len == 0) return;
     var valueLenInline = iter.ValueLenInline;
     long dataLen = valueLen - valueLenInline;
     if (ofs < dataLen)
     {
         RecursiveReadOverflown(ofs, iter.ValueSectorPtr, _currentKeySector, dataLen, buf, ref bufOfs, ref len);
         ofs = dataLen;
     }
     if (len > 0)
     {
         Debug.Assert(ofs >= dataLen);
         Array.Copy(_currentKeySector.Data, iter.ValueOffset + (int)(ofs - dataLen), buf, bufOfs, len);
     }
 }
Пример #15
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);
 }
Пример #16
0
 public void SetValue(byte[] buf, int bufOfs, int len)
 {
     if (len < 0) throw new ArgumentOutOfRangeException("len");
     if (_currentKeyIndexInLeaf < 0) throw new BTDBException("Current Key is invalid");
     var iter = new BTreeChildIterator(_currentKeySector.Data);
     iter.MoveTo(_currentKeyIndexInLeaf);
     long oldSize = iter.ValueLen;
     if (oldSize == len)
     {
         WriteValue(0, len, buf, bufOfs);
         return;
     }
     UpgradeToWriteTransaction();
     int oldInlineSize = BTreeChildIterator.CalcValueLenInline(oldSize);
     int newInlineSize = BTreeChildIterator.CalcValueLenInline(len);
     long oldDeepSize = oldSize - oldInlineSize;
     int newDeepSize = len - newInlineSize;
     if (oldDeepSize > 0 && newDeepSize == 0)
         DeleteContentSector(iter.ValueSectorPtr, oldDeepSize, _currentKeySector);
     _currentKeySector = _owner.ResizeSectorWithUpdatePosition(_currentKeySector, iter.TotalLength - iter.CurrentEntrySize + BTreeChildIterator.CalcEntrySize(iter.KeyLen, len), _currentKeySector.Parent, _currentKeySectorParents);
     iter.ResizeValue(_currentKeySector.Data, len);
     _owner.FixChildrenParentPointers(_currentKeySector);
     Array.Copy(buf, bufOfs + len - newInlineSize, _currentKeySector.Data, iter.ValueOffset, newInlineSize);
     if (oldDeepSize == 0)
     {
         if (newDeepSize != 0)
         {
             CreateContentSector(buf, bufOfs, newDeepSize, _currentKeySector, iter.ValueSectorPtrOffset);
         }
     }
     else if (newDeepSize != 0)
     {
         ResizeContentSector(iter.ValueSectorPtr, oldDeepSize, _currentKeySector, iter.ValueSectorPtrOffset, newDeepSize, buf, bufOfs);
     }
 }
Пример #17
0
 void SplitBTreeChild(byte[] keyBuf, int keyOfs, int keyLen, byte[] valueBuf, int valueOfs, int valueLen, Sector sector, BTreeChildIterator iter, int additionalLengthNeeded)
 {
     int middleoffset = (iter.TotalLength + iter.FirstOffset + additionalLengthNeeded) / 2;
     iter.MoveFirst();
     bool beforeNew = true;
     int splitIndex = 0;
     int currentPos = iter.FirstOffset;
     while (currentPos < middleoffset)
     {
         if (beforeNew && splitIndex == _currentKeyIndexInLeaf)
         {
             beforeNew = false;
             currentPos += additionalLengthNeeded - BTreeChildIterator.HeaderForEntry;
         }
         else
         {
             currentPos += iter.CurrentEntrySize;
             splitIndex++;
             iter.MoveNext();
         }
     }
     var rightSector = _owner.NewSector();
     rightSector.Type = SectorType.BTreeChild;
     int rightCount = iter.Count - splitIndex + (beforeNew ? 1 : 0);
     rightSector.SetLengthWithRound(BTreeChildIterator.HeaderSize + rightCount * BTreeChildIterator.HeaderForEntry + iter.TotalLength + additionalLengthNeeded - BTreeChildIterator.HeaderForEntry - currentPos);
     BTreeChildIterator.SetCountToSectorData(rightSector.Data, rightCount);
     rightSector.Parent = sector.Parent;
     int leftCount = splitIndex + (beforeNew ? 0 : 1);
     var leftSector = _owner.ResizeSectorWithUpdatePosition(sector, BTreeChildIterator.HeaderSize + leftCount * BTreeChildIterator.HeaderForEntry + currentPos - iter.FirstOffset, sector.Parent,
                                                               _currentKeySectorParents);
     _currentKeySector = leftSector;
     Sector newKeySector;
     BTreeChildIterator.SetCountToSectorData(leftSector.Data, leftCount);
     int newItemPos = iter.OffsetOfIndex(_currentKeyIndexInLeaf);
     int setActualDataPos;
     if (beforeNew)
     {
         Array.Copy(iter.Data, iter.FirstOffset, leftSector.Data, BTreeChildIterator.HeaderSize + BTreeChildIterator.HeaderForEntry * leftCount, currentPos - iter.FirstOffset);
         Array.Copy(iter.Data, currentPos, rightSector.Data, BTreeChildIterator.HeaderSize + BTreeChildIterator.HeaderForEntry * rightCount, newItemPos - currentPos);
         int rightPos = BTreeChildIterator.HeaderSize + BTreeChildIterator.HeaderForEntry * rightCount + newItemPos - currentPos;
         setActualDataPos = rightPos;
         SetBTreeChildKeyDataJustLengths(rightSector, keyLen, valueLen, rightPos);
         rightPos += additionalLengthNeeded - BTreeChildIterator.HeaderForEntry;
         Array.Copy(iter.Data, newItemPos, rightSector.Data, rightPos, iter.TotalLength - newItemPos);
         newKeySector = rightSector;
         _currentKeyIndexInLeaf -= splitIndex;
     }
     else
     {
         Array.Copy(iter.Data, iter.FirstOffset, leftSector.Data, BTreeChildIterator.HeaderSize + BTreeChildIterator.HeaderForEntry * leftCount, newItemPos - iter.FirstOffset);
         int leftPosInsert = BTreeChildIterator.HeaderSize + BTreeChildIterator.HeaderForEntry * leftCount + newItemPos - iter.FirstOffset;
         int leftPos = leftPosInsert;
         leftPos += additionalLengthNeeded - BTreeChildIterator.HeaderForEntry;
         Array.Copy(iter.Data, currentPos - additionalLengthNeeded + BTreeChildIterator.HeaderForEntry, rightSector.Data, BTreeChildIterator.HeaderSize + BTreeChildIterator.HeaderForEntry * rightCount,
                    iter.TotalLength + additionalLengthNeeded - BTreeChildIterator.HeaderForEntry - currentPos);
         Array.Copy(iter.Data, newItemPos, leftSector.Data, leftPos, currentPos - newItemPos - additionalLengthNeeded + BTreeChildIterator.HeaderForEntry);
         setActualDataPos = leftPosInsert;
         SetBTreeChildKeyDataJustLengths(leftSector, keyLen, valueLen, leftPosInsert);
         newKeySector = leftSector;
     }
     BTreeChildIterator.RecalculateHeader(leftSector.Data, leftCount);
     BTreeChildIterator.RecalculateHeader(rightSector.Data, rightCount);
     _owner.FixChildrenParentPointers(leftSector);
     _owner.PublishSector(rightSector, true);
     Interlocked.Increment(ref leftSector.ChildrenInCache);
     Interlocked.Increment(ref rightSector.ChildrenInCache);
     try
     {
         _owner.TruncateSectorCache(true, 0);
         SetBTreeChildKeyData(newKeySector, keyBuf, keyOfs, keyLen, valueBuf, valueOfs, valueLen, setActualDataPos);
         if (leftSector.Parent == null)
         {
             CreateBTreeParentFromTwoLeafs(leftSector, rightSector);
         }
         else
         {
             iter = new BTreeChildIterator(rightSector.Data);
             iter.MoveFirst();
             if (iter.HasKeySectorPtr) ForceKeyFlush(iter.KeySectorPtr, iter.KeyLen - iter.KeyLenInline, rightSector);
             int keyLenInSector = iter.KeyLenInline + (iter.HasKeySectorPtr ? KeyValueDB.PtrDownSize : 0);
             AddToBTreeParent(leftSector, rightSector, iter.Data, iter.KeyLen, iter.KeyOffset,
                              keyLenInSector);
         }
     }
     finally
     {
         Interlocked.Decrement(ref leftSector.ChildrenInCache);
         Interlocked.Decrement(ref rightSector.ChildrenInCache);
     }
     UnlockUselessAndFixKeySectorParents(newKeySector, leftSector, rightSector);
     _currentKeySector = newKeySector;
 }
Пример #18
0
 void CreateBTreeParentFromTwoLeafs(Sector leftSector, Sector rightSector)
 {
     var iter = new BTreeChildIterator(rightSector.Data);
     iter.MoveFirst();
     int keyLenInSector = iter.KeyLenInline + (iter.HasKeySectorPtr ? KeyValueDB.PtrDownSize : 0);
     if (iter.HasKeySectorPtr)
     {
         ForceKeyFlush(iter.KeySectorPtr, iter.KeyLen - iter.KeyLenInline, rightSector);
     }
     CreateBTreeParentFromTwoChildren(leftSector, rightSector, iter.Data, iter.KeyLen, iter.KeyOffset,
                                     keyLenInSector);
 }
Пример #19
0
 public int GetKeySize()
 {
     if (_currentKeyIndexInLeaf < 0) return -1;
     var iter = new BTreeChildIterator(_currentKeySector.Data);
     iter.MoveTo(_currentKeyIndexInLeaf);
     return iter.KeyLen - _prefix.Length;
 }
Пример #20
0
 void ErasePartiallyChild(ref Sector sector, long firstKeyIndex, long lastKeyIndex)
 {
     var iter = new BTreeChildIterator(sector.Data);
     iter.MoveTo((int)firstKeyIndex);
     var eraseFromOfs = iter.EntryOffset;
     while (true)
     {
         if (iter.HasKeySectorPtr)
             DeleteContentSector(iter.KeySectorPtr, iter.KeyLen - iter.KeyLenInline, sector);
         if (iter.HasValueSectorPtr)
             DeleteContentSector(iter.ValueSectorPtr, iter.ValueLen - iter.ValueLenInline, sector);
         if (iter.Index == (int)lastKeyIndex) break;
         iter.MoveNext();
     }
     var eraseToOfs = iter.EntryOffset + iter.CurrentEntrySize;
     var originalLength = iter.TotalLength;
     var newCount = iter.Count - 1 - (int)(lastKeyIndex - firstKeyIndex);
     sector = _owner.ResizeSectorNoUpdatePosition(sector,
                                                  originalLength - eraseToOfs + eraseFromOfs - BTreeChildIterator.HeaderForEntry * (iter.Count - newCount),
                                                  sector.Parent,
                                                  null);
     BTreeChildIterator.SetCountToSectorData(sector.Data, newCount);
     var ofs = BTreeChildIterator.HeaderSize + BTreeChildIterator.HeaderForEntry * newCount;
     Array.Copy(iter.Data, iter.FirstOffset, sector.Data, ofs, eraseFromOfs - iter.FirstOffset);
     ofs += eraseFromOfs - iter.FirstOffset;
     Array.Copy(iter.Data, eraseToOfs, sector.Data, ofs, originalLength - eraseToOfs);
     BTreeChildIterator.RecalculateHeader(sector.Data, newCount);
 }
Пример #21
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;
 }