public void SetChildSectorPtrWithKeyCount(int index, SectorPtr childSectorPtr, long keyCount) { if (index == 0) { FirstChildSectorPtr = childSectorPtr; FirstChildKeyCount = keyCount; return; } MoveTo(index - 1); ChildSectorPtr = childSectorPtr; ChildKeyCount = keyCount; }
void ForceKeyFlush(SectorPtr keySectorPtr, int keySize, Sector parent) { // Because parent of sector could be just one and we are going to point to same sector from 2 places it needs to be forcibly flushed ForceFlushContentSector(keySectorPtr, keySize, parent); }
void ForceFlushContentSector(SectorPtr sectorPtr, long len, Sector parent) { var sector = _owner.TryGetSector(sectorPtr.Ptr, true, parent); if (len <= KeyValueDB.MaxLeafDataSectorSize) { if (sector == null) return; _owner.ForceFlushSector(sector); return; } int downPtrCount; long bytesInDownLevel = KeyValueDB.GetBytesInDownLevel(len, out downPtrCount); sector = sector ?? _owner.ReadSector(sectorPtr, true, SectorTypeInit.DataParent, parent); for (int i = 0; i < downPtrCount; i++) { var downSectorPtr = SectorPtr.Unpack(sector.Data, i * KeyValueDB.PtrDownSize); ForceFlushContentSector(downSectorPtr, Math.Min(len, bytesInDownLevel), sector); len -= bytesInDownLevel; } _owner.ForceFlushSector(sector); }
long AllocBitsInAlloc(int grans, ref SectorPtr sectorPtr, long totalGrans, ulong startInBytes, Sector parent) { long startGran; Sector sector; if (totalGrans <= MaxLeafAllocSectorGrans) { var longestFree = _freeSpaceAllocatorOptimizer.QueryLongestForGran(startInBytes); if (longestFree < grans) return -1; sector = GetOrReadSector(sectorPtr, true, SectorTypeInit.AllocChild, parent); int startGranSearch = 0; while (true) { startGran = BitArrayManipulation.IndexOfFirstHole(sector.Data, grans, startGranSearch); if (startGran < 0) { if (sector.Length < MaxLeafAllocSectorSize) { var oldData = sector.Data; sector = ResizeSectorNoUpdatePosition(sector, sector.Length + AllocationGranularity, sector.Parent, null); Array.Copy(oldData, 0, sector.Data, 0, oldData.Length); sectorPtr.Ptr = sector.Position; continue; } _freeSpaceAllocatorOptimizer.UpdateLongestForGran(startInBytes, grans - 1); return -1; } ulong checkStartInBytes = startInBytes + (ulong)startGran * AllocationGranularity; ulong foundFreeInBytes = _spaceUsedByReadOnlyTransactions.FindFreeSizeAfter(checkStartInBytes, (ulong)grans * AllocationGranularity); if (checkStartInBytes == foundFreeInBytes) break; ulong newStartGranSearch = (foundFreeInBytes - startInBytes) / AllocationGranularity; if (newStartGranSearch > MaxLeafAllocSectorGrans) { _freeSpaceAllocatorOptimizer.UpdateLongestForGran(startInBytes, grans - 1); return -1; } startGranSearch = (int)newStartGranSearch; } sector = DirtizeSector(sector, parent, null); BitArrayManipulation.SetBits(sector.Data, (int)startGran, grans); sectorPtr = sector.ToSectorPtr(); return startGran; } int childSectors; long gransInChild = GetGransInDownLevel(totalGrans, out childSectors); sector = GetOrReadSector(sectorPtr, true, SectorTypeInit.AllocParent, parent); sector = DirtizeSector(sector, parent, null); sectorPtr = sector.ToSectorPtr(); var i = 0; long startingGranOfChild; SectorPtr childSectorPtr; for (; i < childSectors - 1; i++) { startingGranOfChild = i * gransInChild; childSectorPtr = SectorPtr.Unpack(sector.Data, i * PtrDownSize); startGran = AllocBitsInAlloc(grans, ref childSectorPtr, gransInChild, startInBytes + (ulong)(i * gransInChild * AllocationGranularity), sector); if (startGran < 0) continue; Debug.Assert(sector.Dirty); SectorPtr.Pack(sector.Data, i * PtrDownSize, childSectorPtr); startGran += startingGranOfChild; return startGran; } startingGranOfChild = i * gransInChild; childSectorPtr = SectorPtr.Unpack(sector.Data, i * PtrDownSize); startGran = AllocBitsInAlloc(grans, ref childSectorPtr, totalGrans - startingGranOfChild, startInBytes + (ulong)(i * gransInChild * AllocationGranularity), sector); if (startGran >= 0) { SectorPtr.Pack(sector.Data, i * PtrDownSize, childSectorPtr); startGran += startingGranOfChild; return startGran; } int childSectors2; long gransInChild2 = GetGransInDownLevel(totalGrans - startingGranOfChild, out childSectors2); Sector newLeafSector; if (gransInChild / MaxChildren != gransInChild2) { Debug.Assert(childSectors2 == MaxChildren); var newParentSector = NewSector(); newParentSector.Type = SectorType.AllocParent; newParentSector.SetLengthWithRound(2 * PtrDownSize); newParentSector.Parent = sector; newLeafSector = NewSector(); newLeafSector.Type = SectorType.AllocChild; newLeafSector.SetLengthWithRound((grans + 7) / 8); newLeafSector.Parent = newParentSector; BitArrayManipulation.SetBits(newLeafSector.Data, 0, grans); SectorPtr.Pack(newParentSector.Data, 0, childSectorPtr); SectorPtr.Pack(newParentSector.Data, PtrDownSize, newLeafSector.ToSectorPtr()); SectorPtr.Pack(sector.Data, i * PtrDownSize, newParentSector.ToSectorPtr()); FixChildParentPointer(childSectorPtr.Ptr, newParentSector); PublishSector(newLeafSector, false); PublishSector(newParentSector, false); TruncateSectorCache(true, 0); return startingGranOfChild + gransInChild2 * MaxChildren; } if (childSectors == MaxChildren) return -1; if (sector.Length < (childSectors + 1) * PtrDownSize) { var oldData = sector.Data; var oldSector = sector; sector = ResizeSectorNoUpdatePosition(sector, (childSectors + 1) * PtrDownSize, sector.Parent, null); if (oldSector != sector) { sectorPtr = sector.ToSectorPtr(); Array.Copy(oldData, 0, sector.Data, 0, oldData.Length); FixChildrenParentPointers(sector); } } newLeafSector = NewSector(); newLeafSector.Type = SectorType.AllocChild; newLeafSector.SetLengthWithRound((grans + 7) / 8); newLeafSector.Parent = sector; BitArrayManipulation.SetBits(newLeafSector.Data, 0, grans); SectorPtr.Pack(sector.Data, childSectors * PtrDownSize, newLeafSector.ToSectorPtr()); PublishSector(newLeafSector, false); TruncateSectorCache(true, 0); return gransInChild * childSectors; }
int ApproximateLengthOfBTreeChild(SectorPtr childSectorPtr) { if (childSectorPtr.Ptr >= 0) { return (int)(childSectorPtr.Ptr & KeyValueDB.MaskOfGranLength) * KeyValueDB.AllocationGranularity; } Sector child = _owner.TryGetSector(childSectorPtr.Ptr, false, null); return child.Length; }
void ResizeContentSectorChild(SectorPtr oldSectorPtr, int oldLength, int newLength, Sector parentSector, int ofsInParent, byte[] buf, int bufOfs) { var sector = _owner.GetOrReadSector(oldSectorPtr, true, SectorTypeInit.DataChild, parentSector); byte[] oldData = sector.Data; sector = _owner.ResizeSectorNoUpdatePosition(sector, newLength, parentSector, null); if (buf == null) { Array.Copy(oldData, 0, sector.Data, 0, Math.Min(oldLength, newLength)); } else { Array.Copy(buf, bufOfs, sector.Data, 0, newLength); } SectorPtr.Pack(parentSector.Data, ofsInParent, sector.ToSectorPtr()); }
void RecursiveWriteValue(SectorPtr sectorPtr, long valueLen, long ofs, int len, byte[] buf, int bufOfs, Sector newParent, int ofsInParent) { if (ofs < 0) throw new ArgumentOutOfRangeException("ofs"); if (ofs + len > valueLen) throw new ArgumentOutOfRangeException("ofs"); var dataSector = GetOrReadDataSector(sectorPtr, valueLen, newParent); if (dataSector.Type == SectorType.DataChild) { Debug.Assert(valueLen <= dataSector.Length); dataSector = _owner.ResizeSectorNoUpdatePosition(dataSector, dataSector.Length, newParent, null); // DirtizeSector but without update position if (buf != null) { Array.Copy(buf, bufOfs, dataSector.Data, (int)ofs, len); } else { Array.Clear(dataSector.Data, (int)ofs, len); } SectorPtr.Pack(newParent.Data, ofsInParent, dataSector.ToSectorPtr()); return; } dataSector = _owner.DirtizeSector(dataSector, newParent, null); SectorPtr.Pack(newParent.Data, ofsInParent, dataSector.ToSectorPtr()); int downPtrCount; long bytesInDownLevel = KeyValueDB.GetBytesInDownLevel(valueLen, out downPtrCount); var i = (int)(ofs / bytesInDownLevel); while (i < downPtrCount) { long newofs = ofs - i * bytesInDownLevel; if (newofs + len <= 0) break; long downValueLen; if (i < downPtrCount - 1) { downValueLen = bytesInDownLevel; } else { downValueLen = valueLen % bytesInDownLevel; if (downValueLen == 0) downValueLen = bytesInDownLevel; } SectorPtr downSectorPtr = SectorPtr.Unpack(dataSector.Data, i * KeyValueDB.PtrDownSize); int newBufOfs = bufOfs; int newlen = len; if (newofs < 0) { newlen += (int)newofs; newBufOfs -= (int)newofs; newofs = 0; } if (downValueLen - newofs < newlen) { newlen = (int)(downValueLen - newofs); } RecursiveWriteValue(downSectorPtr, downValueLen, newofs, newlen, buf, newBufOfs, dataSector, i * KeyValueDB.PtrDownSize); i++; } }
Sector LoadBTreeSector(SectorPtr sectorPtr) { Sector sector = _owner.GetOrReadSector(sectorPtr, IsWritting(), SectorTypeInit.BTreeChildOrParent, _currentKeySector); if (_currentKeySector != null) _currentKeySectorParents.Add(_currentKeySector); _currentKeySector = sector; return sector; }
internal Sector GetOrReadSector(SectorPtr sectorPtr, bool inWriteTransaction, SectorTypeInit typeInit, Sector parent) { return TryGetSector(sectorPtr.Ptr, inWriteTransaction, parent) ?? ReadSector(sectorPtr, inWriteTransaction, typeInit, parent); }
void UnsetBitsInAlloc(long startGran, int grans, ref SectorPtr sectorPtr, long totalGrans, Sector parent) { Sector sector = TryGetSector(sectorPtr.Ptr, true, parent); if (totalGrans <= MaxLeafAllocSectorGrans) { if (sector == null) { sector = ReadSector(sectorPtr, true, SectorTypeInit.AllocChild, parent); } sector = DirtizeSector(sector, parent, null); BitArrayManipulation.UnsetBits(sector.Data, (int)startGran, grans); sectorPtr = sector.ToSectorPtr(); return; } int childSectors; long gransInChild = GetGransInDownLevel(totalGrans, out childSectors); if (sector == null) { sector = ReadSector(sectorPtr, true, SectorTypeInit.AllocParent, parent); } sector = DirtizeSector(sector, parent, null); for (var i = (int)(startGran / gransInChild); i < childSectors; i++) { var startingGranOfChild = i * gransInChild; if (startGran + grans <= startingGranOfChild) break; var childSectorPtr = SectorPtr.Unpack(sector.Data, i * PtrDownSize); var currentStartGran = Math.Max(0, startGran - startingGranOfChild); UnsetBitsInAlloc(currentStartGran, (int)(Math.Min(startGran + grans - startingGranOfChild, gransInChild) - currentStartGran), ref childSectorPtr, Math.Min(totalGrans - startingGranOfChild, gransInChild), sector); SectorPtr.Pack(sector.Data, i * PtrDownSize, childSectorPtr); } sectorPtr = sector.ToSectorPtr(); }
byte[] CheckSector(SectorPtr sectorPtr) { if (sectorPtr.Ptr <= 0) return null; int size = (int)(sectorPtr.Ptr & MaskOfGranLength) + 1; size = size * AllocationGranularity; var sector = new byte[size]; if (_positionLessStream.Read(sector, 0, size, (ulong)(sectorPtr.Ptr & MaskOfPosition)) != size) { return null; } Interlocked.Add(ref _totalBytesRead, size); if (sectorPtr.Checksum != 0 && Checksum.CalcFletcher32(sector, 0, (uint)size) != sectorPtr.Checksum) { return null; } return sector; }
bool CheckDataPages(SectorPtr sectorPtr, long dataLen) { byte[] sector = CheckSector(sectorPtr); if (sector == null) return false; if (dataLen <= MaxLeafDataSectorSize) return true; int downPtrCount; long bytesInDownLevel = GetBytesInDownLevel(dataLen, out downPtrCount); for (int i = 0; i < downPtrCount; i++) { if (!CheckDataPages(SectorPtr.Unpack(sector, i * PtrDownSize), Math.Min(dataLen, bytesInDownLevel))) return false; dataLen -= bytesInDownLevel; } return true; }
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; }
bool CheckAllocPages(SectorPtr sectorPtr, long grans) { byte[] sector = CheckSector(sectorPtr); if (sector == null) return false; if (grans <= MaxLeafAllocSectorGrans) return true; int childSectors; long gransInChild = GetGransInDownLevel(grans, out childSectors); for (int i = 0; i < childSectors; i++) { if (!CheckAllocPages(SectorPtr.Unpack(sector, i * PtrDownSize), Math.Min(grans, gransInChild))) return false; grans -= gransInChild; } return true; }
Sector GetBTreeSector(SectorPtr childSectorPtr, Sector parent) { return _owner.GetOrReadSector(childSectorPtr, true, SectorTypeInit.BTreeChildOrParent, parent); }
Sector GetOrReadDataSector(SectorPtr sectorPtr, long dataLen, Sector parent) { return _owner.GetOrReadSector(sectorPtr, IsWritting(), dataLen > KeyValueDB.MaxLeafDataSectorSize ? SectorTypeInit.DataParent : SectorTypeInit.DataChild, parent); }
internal Sector ReadSector(SectorPtr sectorPtr, bool inWriteTransaction, SectorTypeInit typeInit, Sector parent) { Debug.Assert(sectorPtr.Ptr > 0); return ReadSector(sectorPtr.Ptr & MaskOfPosition, (int)(sectorPtr.Ptr & MaskOfGranLength) + 1, sectorPtr.Checksum, inWriteTransaction, typeInit, parent); }
void RecursiveReadOverflown(long ofs, SectorPtr dataSectorPtr, Sector parentOfSector, long dataLen, byte[] buf, ref int bufOfs, ref int len) { Sector dataSector = GetOrReadDataSector(dataSectorPtr, dataLen, parentOfSector); if (dataSector.Type == SectorType.DataChild) { var copyLen = Math.Min(len, (int)(dataSector.Length - ofs)); Array.Copy(dataSector.Data, (int)ofs, buf, bufOfs, copyLen); len -= copyLen; bufOfs += copyLen; return; } int downPtrCount; long bytesInDownLevel = KeyValueDB.GetBytesInDownLevel(dataLen, out downPtrCount); var childIndex = (int)(ofs / bytesInDownLevel); ofs = ofs % bytesInDownLevel; while (childIndex < downPtrCount && len > 0) { long childDataLen; if (childIndex < downPtrCount - 1) { childDataLen = bytesInDownLevel; } else { childDataLen = dataLen % bytesInDownLevel; if (childDataLen == 0) childDataLen = bytesInDownLevel; } dataSectorPtr = SectorPtr.Unpack(dataSector.Data, childIndex * KeyValueDB.PtrDownSize); RecursiveReadOverflown(ofs, dataSectorPtr, dataSector, childDataLen, buf, ref bufOfs, ref len); ofs = 0; childIndex++; } }
internal static void Pack(byte[] data, int offset, SectorPtr value) { PackUnpack.PackInt64LE(data, offset, value.Ptr); PackUnpack.PackUInt32LE(data, offset + 8, value.Checksum); }
void ResizeContentSector(SectorPtr oldSectorPtr, long oldSize, Sector parentSector, int ofsInParent, long newSize, byte[] buf, int bufOfs) { Debug.Assert(oldSize != 0 && newSize != 0); if (oldSize == newSize) { if (buf != null) { RecursiveWriteValue(oldSectorPtr, newSize, 0, (int)newSize, buf, bufOfs, parentSector, ofsInParent); return; } SectorPtr.Pack(parentSector.Data, ofsInParent, oldSectorPtr); return; } int oldDownPtrCount; var oldBytesInDownLevel = KeyValueDB.GetBytesInDownLevel(oldSize, out oldDownPtrCount); int newDownPtrCount; var newBytesInDownLevel = KeyValueDB.GetBytesInDownLevel(newSize, out newDownPtrCount); Sector sector; if (oldBytesInDownLevel < newBytesInDownLevel) { sector = _owner.NewSector(); sector.SetLengthWithRound(newDownPtrCount * KeyValueDB.PtrDownSize); sector.Parent = parentSector; sector.Type = SectorType.DataParent; SectorPtr.Pack(sector.Data, 0, oldSectorPtr); _owner.PublishSector(sector, true); SectorPtr.Pack(parentSector.Data, ofsInParent, sector.ToSectorPtr()); Interlocked.Increment(ref sector.ChildrenInCache); try { _owner.TruncateSectorCache(true, oldSectorPtr.Ptr); } finally { Interlocked.Decrement(ref sector.ChildrenInCache); } ResizeContentSector(oldSectorPtr, oldSize, sector, 0, newBytesInDownLevel, buf, bufOfs); for (int i = 1; i < newDownPtrCount; i++) { long downLevelSize = Math.Min(newSize - i * newBytesInDownLevel, newBytesInDownLevel); if (buf != null) CreateContentSector(buf, (int)(bufOfs + i * newBytesInDownLevel), (int)downLevelSize, sector, i * KeyValueDB.PtrDownSize); else CreateContentSector(downLevelSize, sector, i * KeyValueDB.PtrDownSize); } return; } if (oldBytesInDownLevel > newBytesInDownLevel) { sector = _owner.GetOrReadSector(oldSectorPtr, true, SectorTypeInit.DataParent, parentSector); for (int i = 1; i < oldDownPtrCount; i++) { long downLevelSize = Math.Min(oldSize - i * oldBytesInDownLevel, oldBytesInDownLevel); DeleteContentSector(SectorPtr.Unpack(sector.Data, i * KeyValueDB.PtrDownSize), downLevelSize, sector); } _owner.DeallocateSector(sector); ResizeContentSector(SectorPtr.Unpack(sector.Data, 0), oldBytesInDownLevel, parentSector, ofsInParent, newSize, buf, bufOfs); return; } if (oldBytesInDownLevel == 1) { ResizeContentSectorChild(oldSectorPtr, oldDownPtrCount, newDownPtrCount, parentSector, ofsInParent, buf, bufOfs); return; } sector = _owner.GetOrReadSector(oldSectorPtr, true, SectorTypeInit.DataParent, parentSector); SectorPtr lastSectorPtr; long lastOffset; for (int i = newDownPtrCount; i < oldDownPtrCount; i++) { lastOffset = i * oldBytesInDownLevel; lastSectorPtr = SectorPtr.Unpack(sector.Data, i * KeyValueDB.PtrDownSize); DeleteContentSector(lastSectorPtr, Math.Min(oldSize - lastOffset, oldBytesInDownLevel), sector); } var lastCommonPtrCount = Math.Min(oldDownPtrCount, newDownPtrCount) - 1; byte[] oldData = sector.Data; sector = _owner.ResizeSectorNoUpdatePosition(sector, newDownPtrCount * KeyValueDB.PtrDownSize, parentSector, null); var commonLength = (lastCommonPtrCount + 1) * KeyValueDB.PtrDownSize; Array.Copy(oldData, 0, sector.Data, 0, commonLength); Array.Clear(sector.Data, commonLength, sector.Data.Length - commonLength); SectorPtr.Pack(parentSector.Data, ofsInParent, sector.ToSectorPtr()); _owner.FixChildrenParentPointers(sector); if (buf != null) { for (int i = 0; i < lastCommonPtrCount; i++) { lastSectorPtr = SectorPtr.Unpack(sector.Data, i * KeyValueDB.PtrDownSize); lastOffset = i * newBytesInDownLevel; RecursiveWriteValue(lastSectorPtr, newBytesInDownLevel, 0, (int)newBytesInDownLevel, buf, (int)(bufOfs + lastOffset), sector, i * KeyValueDB.PtrDownSize); } } lastSectorPtr = SectorPtr.Unpack(sector.Data, lastCommonPtrCount * KeyValueDB.PtrDownSize); lastOffset = lastCommonPtrCount * newBytesInDownLevel; ResizeContentSector(lastSectorPtr, Math.Min(oldSize - lastOffset, oldBytesInDownLevel), sector, lastCommonPtrCount * KeyValueDB.PtrDownSize, Math.Min(newSize - lastOffset, newBytesInDownLevel), buf, (int)(bufOfs + lastOffset)); for (int i = oldDownPtrCount; i < newDownPtrCount; i++) { lastOffset = i * newBytesInDownLevel; if (buf != null) CreateContentSector(buf, (int)(bufOfs + lastOffset), (int)Math.Min(newSize - lastOffset, newBytesInDownLevel), sector, i * KeyValueDB.PtrDownSize); else CreateContentSector(Math.Min(newSize - lastOffset, newBytesInDownLevel), sector, i * KeyValueDB.PtrDownSize); } }
int SectorDataCompare(int startOfs, byte[] buf, int ofs, int len, SectorPtr sectorPtr, int dataLen, Sector parent) { var sector = GetOrReadDataSector(sectorPtr, dataLen, parent); if (sector.Type == SectorType.DataChild) { int dataOfs = 0; if (startOfs < _prefix.Length) { int compareLen = Math.Min(_prefix.Length - startOfs, sector.Length); int res = BitArrayManipulation.CompareByteArray(_prefix, startOfs, compareLen, sector.Data, dataOfs, compareLen); if (res != 0) return res; startOfs += compareLen; if (startOfs < _prefix.Length) return 0; dataOfs += compareLen; } if (ofs == -1) return 1; startOfs -= _prefix.Length; return BitArrayManipulation.CompareByteArray(buf, ofs + startOfs, Math.Min(len - startOfs, sector.Length - dataOfs), sector.Data, dataOfs, sector.Length - dataOfs); } int downPtrCount; var bytesInDownLevel = (int)KeyValueDB.GetBytesInDownLevel(dataLen, out downPtrCount); int i; SectorPtr downSectorPtr; for (i = 0; i < downPtrCount - 1; i++) { downSectorPtr = SectorPtr.Unpack(sector.Data, i * KeyValueDB.PtrDownSize); int res = SectorDataCompare(startOfs, buf, ofs, len, downSectorPtr, Math.Min(dataLen, bytesInDownLevel), sector); if (res != 0) return res; startOfs += bytesInDownLevel; dataLen -= bytesInDownLevel; } downSectorPtr = SectorPtr.Unpack(sector.Data, i * KeyValueDB.PtrDownSize); return SectorDataCompare(startOfs, buf, ofs, len, downSectorPtr, dataLen, sector); }
void DeleteContentSector(SectorPtr sectorPtr, long len, Sector parent) { var sector = GetOrReadDataSector(sectorPtr, len, parent); if (sector.Type == SectorType.DataChild) { _owner.DeallocateSector(sector); return; } int downPtrCount; long bytesInDownLevel = KeyValueDB.GetBytesInDownLevel(len, out downPtrCount); for (int i = 0; i < downPtrCount; i++) { var downSectorPtr = SectorPtr.Unpack(sector.Data, i * KeyValueDB.PtrDownSize); DeleteContentSector(downSectorPtr, Math.Min(len, bytesInDownLevel), sector); len -= bytesInDownLevel; } _owner.DeallocateSector(sector); }
long AllocBitsInAlloc(int grans, ref SectorPtr sectorPtr, long totalGrans, ulong startInBytes, Sector parent, long startSearchInGrans) { Sector sector; long startGran; if (totalGrans <= MaxLeafAllocSectorGrans) { var longestFree = _freeSpaceAllocatorOptimizer.QueryLongestForGran(startInBytes); if (longestFree < grans) return -1; sector = GetOrReadSector(sectorPtr, true, SectorTypeInit.AllocChild, parent); int startGranSearch = 0; while (true) { startGran = BitArrayManipulation.IndexOfFirstHole(sector.Data, grans, startGranSearch); if (startGran < 0) { if (sector.Length == MaxLeafAllocSectorSize) { _freeSpaceAllocatorOptimizer.UpdateLongestForGran(startInBytes, grans - 1); } return -1; } ulong checkStartInBytes = startInBytes + (ulong)startGran * AllocationGranularity; ulong foundFreeInBytes = _spaceUsedByReadOnlyTransactions.FindFreeSizeAfter(checkStartInBytes, (ulong)grans * AllocationGranularity); if (checkStartInBytes == foundFreeInBytes) break; ulong newStartGranSearch = (foundFreeInBytes - startInBytes) / AllocationGranularity; if (newStartGranSearch > MaxLeafAllocSectorGrans) { _freeSpaceAllocatorOptimizer.UpdateLongestForGran(startInBytes, grans - 1); return -1; } startGranSearch = (int)newStartGranSearch; } sector = DirtizeSector(sector, sector.Parent, null); BitArrayManipulation.SetBits(sector.Data, (int)startGran, grans); sectorPtr = sector.ToSectorPtr(); return startGran; } int childSectors; long gransInChild = GetGransInDownLevel(totalGrans, out childSectors); sector = GetOrReadSector(sectorPtr, true, SectorTypeInit.AllocParent, parent); sector = DirtizeSector(sector, parent, null); sectorPtr = sector.ToSectorPtr(); var i = 0; long startingGranOfChild; SectorPtr childSectorPtr; if (startSearchInGrans > 0) { i = (int)(startSearchInGrans / gransInChild); Debug.Assert(i < childSectors); } for (; i < childSectors - 1; i++) { startingGranOfChild = i * gransInChild; childSectorPtr = SectorPtr.Unpack(sector.Data, i * PtrDownSize); startGran = AllocBitsInAlloc(grans, ref childSectorPtr, gransInChild, startInBytes + (ulong)(i * gransInChild * AllocationGranularity), sector, startSearchInGrans - startingGranOfChild); if (startGran < 0) continue; Debug.Assert(sector.Dirty); SectorPtr.Pack(sector.Data, i * PtrDownSize, childSectorPtr); startGran += startingGranOfChild; return startGran; } startingGranOfChild = i * gransInChild; childSectorPtr = SectorPtr.Unpack(sector.Data, i * PtrDownSize); startGran = AllocBitsInAlloc(grans, ref childSectorPtr, totalGrans - startingGranOfChild, startInBytes + (ulong)(i * gransInChild * AllocationGranularity), sector, startSearchInGrans - startingGranOfChild); if (startGran >= 0) { SectorPtr.Pack(sector.Data, i * PtrDownSize, childSectorPtr); startGran += startingGranOfChild; return startGran; } return -1; }