Recover a log with a torn final record

hardStorage~35 min · 8 tests

A process appends a record to a log file and the power goes out halfway through the write. On restart, the last record is cut short, or its bytes are garbage. Recovery has to keep every complete record and find exactly where the good data ends.

Each record in the file is laid out like this:

| length: 4 bytes | crc: 4 bytes | payload: length bytes |
  • length is the payload size, an unsigned 32-bit big-endian integer.
  • crc is zlib.crc32(payload), unsigned 32-bit big-endian.
  • payload is UTF-8 text.

Write read_log(data):

  • data is a bytes object holding zero or more records back to back.
  • Read records from the start. Stop at the first record that is incomplete (not enough bytes for the header or the payload) or whose checksum doesn’t match. Ignore everything from there on.
  • Return {"records": [...], "valid_bytes": n}: the decoded payloads in order, and the byte offset where the good data ends. Truncating the file to n bytes makes it clean again.
>>> import struct, zlib
>>> def rec(s):
...     b = s.encode()
...     return struct.pack(">II", len(b), zlib.crc32(b)) + b
>>> read_log(rec("a") + rec("bc") + rec("def")[:5])
{'records': ['a', 'bc'], 'valid_bytes': 19}
Learn the ideaRead the post →
solution.pyPython 3.14 · Pyodide

Press ⌘ ↵ or Run to check the visible tests. Submit runs the hidden ones too. Everything runs in your browser.

⌘ ↵ to run