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; } } }
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); } }
public long GetValueSize() { if (_currentKeyIndexInLeaf < 0) return -1; var iter = new BTreeChildIterator(_currentKeySector.Data); iter.MoveTo(_currentKeyIndexInLeaf); return iter.ValueLen; }
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; } } }
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; }
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(); } }
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); }
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); }
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; } }
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"); } }
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); } }
internal static int CalcEntrySize(int keyLen) { return(4 + KeyValueDB.PtrDownSize + 8 + BTreeChildIterator.CalcKeyLenInline(keyLen) + (keyLen > BTreeChildIterator.MaxKeyLenInline ? KeyValueDB.PtrDownSize : 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(); } }
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); } }
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); }
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); } }
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; }
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); }
public int GetKeySize() { if (_currentKeyIndexInLeaf < 0) return -1; var iter = new BTreeChildIterator(_currentKeySector.Data); iter.MoveTo(_currentKeyIndexInLeaf); return iter.KeyLen - _prefix.Length; }
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); }
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; }