void CompactOnePureValueFileIteration(ref StructList <uint> toRemoveFileIds) { _cancellation.ThrowIfCancellationRequested(); _writerBytesPerSecondLimiter = new BytesPerSecondLimiter(_keyValueDB.CompactorWriteBytesPerSecondLimit); var writer = _keyValueDB.StartPureValuesFile(out var valueFileId); var firstIteration = true; while (true) { var wastefulFileId = FindMostWastefulFile(firstIteration ? uint.MaxValue : _keyValueDB.MaxTrLogFileSize - writer.GetCurrentPositionWithoutWriter()); firstIteration = false; if (wastefulFileId == 0) { break; } MoveValuesContent(writer, wastefulFileId, valueFileId); if (_fileStats.GetOrFakeValueRef(wastefulFileId).IsFreeToDelete()) { toRemoveFileIds.Add(wastefulFileId); } _fileStats.GetOrFakeValueRef(wastefulFileId) = new FileStat(0); } var valueFile = _keyValueDB.FileCollection.GetFile(valueFileId); valueFile !.HardFlushTruncateSwitchToReadOnlyMode(); _keyValueDB.Logger?.CompactionCreatedPureValueFile(valueFileId, valueFile.GetSize(), (uint)_newPositionMap.Count, 28 * (ulong)_newPositionMap.EnsureCapacity(0) ); }
void MoveValuesContent(ISpanWriter writer, uint wastefulFileId, uint pvlFileId) { const uint blockSize = 256 * 1024; var wastefulStream = _keyValueDB.FileCollection.GetFile(wastefulFileId); var totalSize = wastefulStream !.GetSize(); var blocks = (int)((totalSize + blockSize - 1) / blockSize); var wasteInMemory = new byte[blocks][]; var pos = 0UL; var readLimiter = new BytesPerSecondLimiter(_keyValueDB.CompactorReadBytesPerSecondLimit); for (var i = 0; i < blocks; i++) { _cancellation.ThrowIfCancellationRequested(); wasteInMemory[i] = new byte[blockSize]; var readSize = totalSize - pos; if (readSize > blockSize) { readSize = blockSize; } wastefulStream.RandomRead(wasteInMemory[i].AsSpan(0, (int)readSize), pos, true); pos += readSize; readLimiter.Limit(pos); } _keyValueDB.IterateRoot(_root, (valueFileId, valueOfs, valueSize) => { if (valueFileId != wastefulFileId) { return; } var size = (uint)Math.Abs(valueSize); _newPositionMap.Add(((ulong)wastefulFileId << 32) | valueOfs, ((ulong)pvlFileId << 32) + (ulong)writer.GetCurrentPositionWithoutWriter()); pos = valueOfs; while (size > 0) { _cancellation.ThrowIfCancellationRequested(); var blockId = pos / blockSize; var blockStart = pos % blockSize; var writeSize = (uint)(blockSize - blockStart); if (writeSize > size) { writeSize = size; } writer.WriteBlockWithoutWriter( ref MemoryMarshal.GetReference(wasteInMemory[blockId].AsSpan((int)blockStart, (int)writeSize)), writeSize); size -= writeSize; pos += writeSize; _writerBytesPerSecondLimiter.Limit((ulong)writer.GetCurrentPositionWithoutWriter()); } }); }