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"); }
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; }
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; } }
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); }
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--; } }
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 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; } }
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(); } }
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; } }
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); } }
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); }
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(); } }
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; } } } } } }
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); }
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; }
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; }