@@ -72,7 +72,7 @@ public class FileBasedKVLogManager : KVLogManager
7272 private readonly string _fileName ;
7373 private readonly string ? _metadataFileName ;
7474
75- public FileBasedKVLogManager ( string fileName , string ? metadataFileName = null , bool waitForFlush = true )
75+ public FileBasedKVLogManager ( string fileName , string ? metadataFileName = null , bool waitForFlush = true , int channelCapacity = 4096 )
7676 {
7777 _metadataFileName = metadataFileName ;
7878 _fileName = fileName ;
@@ -86,7 +86,11 @@ public FileBasedKVLogManager(string fileName, string? metadataFileName = null, b
8686 _kvLogStream . Seek ( 0 , SeekOrigin . End ) ;
8787 _kvLogWriter = PipeWriter . Create ( _kvLogStream ) ;
8888
89- _channel = Channel . CreateUnbounded < PutOperation > ( ) ;
89+ _channel = Channel . CreateBounded < PutOperation > ( new BoundedChannelOptions ( channelCapacity )
90+ {
91+ FullMode = BoundedChannelFullMode . Wait ,
92+ SingleReader = true ,
93+ } ) ;
9094 _consumerTask = Task . Run ( ( ) => ConsumeOperationsFromChannel ( ) ) ;
9195 }
9296
@@ -259,20 +263,20 @@ public override async Task<Memory<byte>> ReadValueAtLocation(long offset)
259263 var intBuffer = new byte [ sizeof ( int ) ] ;
260264
261265 // Skip past key
262- await fs . ReadAsync ( intBuffer . AsMemory ( ) ) ;
266+ await fs . ReadExactlyAsync ( intBuffer . AsMemory ( ) ) ;
263267 var keyLen = BinaryPrimitives . ReadInt32LittleEndian ( intBuffer ) ;
264268 fs . Seek ( keyLen , SeekOrigin . Current ) ;
265269
266270 // Skip deleted flag
267271 fs . Seek ( 1 , SeekOrigin . Current ) ;
268272
269273 // Read value
270- await fs . ReadAsync ( intBuffer . AsMemory ( ) ) ;
274+ await fs . ReadExactlyAsync ( intBuffer . AsMemory ( ) ) ;
271275 var valSize = BinaryPrimitives . ReadInt32LittleEndian ( intBuffer ) ;
272276 var valBuffer = new byte [ valSize ] ;
273277 if ( valSize > 0 )
274278 {
275- await fs . ReadAsync ( valBuffer . AsMemory ( ) ) ;
279+ await fs . ReadExactlyAsync ( valBuffer . AsMemory ( ) ) ;
276280 }
277281 return new Memory < byte > ( valBuffer , 0 , valSize ) ;
278282 }
@@ -332,7 +336,7 @@ public async Task<long> ReadOffset()
332336 if ( metaFs . Length >= sizeof ( long ) )
333337 {
334338 var offsetBuffer = new byte [ sizeof ( long ) ] ;
335- await metaFs . ReadAsync ( offsetBuffer . AsMemory ( ) ) ;
339+ await metaFs . ReadExactlyAsync ( offsetBuffer . AsMemory ( ) ) ;
336340 lastCommitted = BinaryPrimitives . ReadInt64LittleEndian ( offsetBuffer ) ;
337341 }
338342 }
@@ -369,34 +373,33 @@ public override async IAsyncEnumerable<PutOperation> GetUncommittedOperations()
369373
370374 if ( keySize <= 0 ) break ; // corrupt or unknown
371375
372- var putOperation = new PutOperation ( ) ;
373-
374376 // Read key
375377 var keyBuffer = new byte [ keySize ] ;
376- await fs . ReadAsync ( keyBuffer . AsMemory ( ) ) ;
378+ await fs . ReadExactlyAsync ( keyBuffer . AsMemory ( ) ) ;
377379
378- // Read deleted flag
379- var deletedByte = new byte [ 1 ] ;
380- await fs . ReadAsync ( deletedByte . AsMemory ( ) ) ;
381- var isDeleted = deletedByte [ 0 ] != 0 ;
380+ // Read deleted flag — single byte, no allocation
381+ var deletedRaw = fs . ReadByte ( ) ;
382+ if ( deletedRaw < 0 ) break ;
383+ var isDeleted = deletedRaw != 0 ;
382384
383385 // Read value length + value
384- await fs . ReadAsync ( intBuffer . AsMemory ( ) ) ;
386+ await fs . ReadExactlyAsync ( intBuffer . AsMemory ( ) ) ;
385387 var valSize = BinaryPrimitives . ReadInt32LittleEndian ( intBuffer ) ;
386388 var valBuffer = new byte [ valSize ] ;
387389 if ( valSize > 0 )
388390 {
389- await fs . ReadAsync ( valBuffer . AsMemory ( ) ) ;
391+ await fs . ReadExactlyAsync ( valBuffer . AsMemory ( ) ) ;
390392 }
391393
392394 // Advance position: keyLen(4) + key(N) + deleted(1) + valLen(4) + val(N)
393395 currentPos += sizeof ( int ) + keySize + 1 + sizeof ( int ) + valSize ;
394396
395- putOperation . Key = keyBuffer ;
396- putOperation . Value = valBuffer ;
397- putOperation . Deleted = isDeleted ;
398-
399- yield return putOperation ;
397+ yield return new PutOperation
398+ {
399+ Key = keyBuffer ,
400+ Value = valBuffer ,
401+ Deleted = isDeleted ,
402+ } ;
400403 }
401404 }
402405
0 commit comments