@@ -335,6 +335,7 @@ private WalEntry ConvertToWalEntry(WalLogEntry logEntry)
335335 /// <summary>
336336 /// Serializes WalEntry to byte buffer with checksum.
337337 /// C# 14: Uses modern unsafe code patterns.
338+ /// Format: Lsn(8) + TxId(8) + Timestamp(8) + Op(2) + BlockIdx(2) + PageId(8) + DataLen(2) + Checksum(32) + Data(4000)
338339 /// </summary>
339340 private static unsafe void SerializeWalEntry ( Span < byte > buffer , WalEntry entry )
340341 {
@@ -369,22 +370,45 @@ private static unsafe void SerializeWalEntry(Span<byte> buffer, WalEntry entry)
369370 BinaryPrimitives . WriteUInt16LittleEndian ( buffer [ offset ..] , entry . DataLength ) ;
370371 offset += 2 ;
371372
372- // Skip checksum for now (will calculate after)
373+ // Mark checksum offset (will write after computing hash )
373374 var checksumOffset = offset ;
374375 offset += 32 ;
375376
377+ // Data payload comes after checksum (offset now at Data field)
378+ var dataOffset = offset ;
379+
376380 // Write data payload (if any)
377- if ( entry . DataLength > 0 )
381+ if ( entry . DataLength > 0 && entry . DataLength <= WalEntry . MAX_DATA_LENGTH )
378382 {
379- // In real implementation, copy from entry.Data
380- // For now, zero-filled as Data field needs to be populated by caller
383+ // In real implementation: copy from entry.Data
384+ // For Phase 3: zero-filled (data writing is stub)
385+ // Data will be populated when actual operations are logged
381386 }
382387
383388 // Calculate and write SHA-256 checksum
389+ // Hash: header (before checksum) + data payload
384390 using var sha256 = IncrementalHash . CreateHash ( HashAlgorithmName . SHA256 ) ;
385- sha256 . AppendData ( buffer [ ..checksumOffset ] ) ; // Header
386- sha256 . AppendData ( buffer [ offset ..( offset + entry . DataLength ) ] ) ; // Data
391+ sha256 . AppendData ( buffer [ ..checksumOffset ] ) ; // Header fields
392+
393+ if ( entry . DataLength > 0 && entry . DataLength <= WalEntry . MAX_DATA_LENGTH )
394+ {
395+ sha256 . AppendData ( buffer . Slice ( dataOffset , entry . DataLength ) ) ; // Data payload
396+ }
397+
387398 var checksum = sha256 . GetHashAndReset ( ) ;
399+
400+ // Validate checksum size and buffer space
401+ if ( checksum . Length != 32 )
402+ {
403+ throw new InvalidOperationException ( $ "SHA256 checksum must be 32 bytes, got { checksum . Length } ") ;
404+ }
405+
406+ if ( checksumOffset + 32 > buffer . Length )
407+ {
408+ throw new ArgumentOutOfRangeException ( nameof ( buffer ) ,
409+ $ "Buffer too small for checksum at offset { checksumOffset } , buffer size { buffer . Length } ") ;
410+ }
411+
388412 checksum . CopyTo ( buffer . Slice ( checksumOffset , 32 ) ) ;
389413 }
390414
@@ -647,37 +671,5 @@ internal enum WalOperation
647671 PageFree = 9
648672}
649673
650- internal struct WalHeader
651- {
652- public const uint MAGIC = 0x20230522 ;
653- public const ushort CURRENT_VERSION = 1 ;
654- public const int SIZE = 64 ;
655- public const int DEFAULT_ENTRY_SIZE = 4096 ;
656-
657- public uint Magic ;
658- public ushort Version ;
659- public ushort EntrySize ;
660- public uint MaxEntries ;
661- public ulong CurrentLsn ;
662- public ulong LastCheckpoint ;
663- public ulong HeadOffset ;
664- public ulong TailOffset ;
665- }
666-
667- #pragma warning disable CS0649 // Field is never assigned to, and will always have its default value
668- internal struct WalEntry
669- {
670- public const int SIZE = 64 ;
671- public const int MAX_DATA_LENGTH = 4000 ;
672-
673- public ulong Lsn ;
674- public ulong TransactionId ;
675- public ulong Timestamp ;
676- public ushort Operation ;
677- public ushort BlockIndex ;
678- public ulong PageId ;
679- public ushort DataLength ;
680- public unsafe fixed byte BlockName [ 32 ] ;
681- public unsafe fixed byte Checksum [ 32 ] ;
682- }
683- #pragma warning restore CS0649
674+ // ✅ PHASE 3 FIX: Using Scdb.WalHeader and Scdb.WalEntry from ScdbStructures.cs
675+ // Removed duplicate definitions that had incorrect SIZE (64 vs 4096)
0 commit comments