linliu-code opened a new pull request, #667:
URL: https://github.com/apache/hudi-rs/pull/667

   **Stacked on #639–#665** — review only the last commit.
   
   ## What was there
   
   ```rust
   fn create_corrupted_block_if_needed(&mut self, _pos: u64, _len: Option<u64>) 
-> Option<LogBlock> {
       // TODO: support creating corrupted block
       None
   }
   ```
   
   A corrupt or truncated block failed the entire log file. 
`BlockType::Corrupted` existed in the model but nothing could ever produce one.
   
   ## What it does now
   
   A well-formed Hudi log block records its total size **twice** — in the 
header length field and again in a trailing reverse pointer — and is followed 
by either another block or EOF. Three checks:
   
   1. the trailing pointer has to lie inside the file
   2. the size it records has to agree with the header
   3. what follows the block has to be a magic marker or the end
   
   Every offset is computed with `checked_add`/`checked_sub`, so a garbage 
length **reports corruption rather than panicking or allocating against it**. 
That is why the check runs before the body is parsed rather than after — a 
bogus content length would otherwise reach a `vec![0u8; len]`.
   
   When a block fails, the reader emits a corrupt marker and resumes at the 
next magic marker, found by scanning in 1 MB windows that overlap by 
`MAGIC.len() - 1` so a marker straddling a boundary is not missed. **One bad 
block now costs its own span instead of the rest of the file.**
   
   Adopted from the internal reader, which has carried this and the recovery 
tests for some time.
   
   ## Tests
   
   Two harness cases un-ignored and passing — a corrupt tail block, and a 
delete-ordering fixture that was failing behind the same read.
   
   Three unit tests on the check itself, since the harness cases only exercise 
one shape:
   
   - a length disagreeing with the trailing pointer is corrupt, and the real 
length is **not** — the negative case matters, since a check that always says 
"corrupt" would pass the positive one
   - a length past EOF, and `u64::MAX`, are corrupt — decided arithmetically, 
never by reading there
   - the recovery offset always lands within the file
   
   Full workspace green: 1185 lib + 79 table-read + 39 datafusion + 21 + 12. 
Ignored 7 → 5.
   
   ## Note
   
   While verifying this I hit 117 unrelated failures that turned out to be a 
**stale fixture-extraction cache** under `$TMPDIR/hudi-rs-test-fixtures`, not 
the change — they reproduce on a clean tree. Clearing the directory fixes it. 
The cache key includes the zip's mtime, so it should self-invalidate; worth a 
look separately if it recurs in CI.
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to