Date: 2026-05-29
Time: 08:03
WAL.truncate — Write-Ahead Log ResetClears the WAL file so it contains zero bytes, then re-opens it in append mode for future writes. This is called after the memtable has been successfully flushed to an SSTable on disk — at that point the WAL's recovery data is no longer needed, because the data it protected is now durable in the SSTable.
Without truncation, the WAL would replay stale entries on the next startup, re-inserting data that's already persisted in SSTables.
self._fd is an open file handle (the constructor guarantees this).self.path exists and is empty (0 bytes). self.fd is a valid file handle open in append mode, ready for new append() calls.None (operates on instance state).
None.
1. Close the current handle — self._fd.close(). Flushes any OS-buffered data and releases the file descriptor.
2. Open in write-binary mode ("wb") — This is the key step. Opening with "wb" truncates the file to zero length per POSIX/Python semantics. The file now exists but is empty.
3. Close the write handle — The truncation is committed to the filesystem.
4. Re-open in append-binary mode ("ab") — Restores the handle to append mode so subsequent append() calls work correctly. Append mode guarantees all writes go to the end of file, which is critical for WAL correctness.
The two-open dance (wb then ab) exists because Python's open("wb") truncates on open but positions the cursor at offset 0 for overwrite — not safe for a WAL. The second open in "ab" ensures the invariant that all future writes append.
open/close cycles happen. This is fine for correctness but wouldn't be ideal in a hot path (it's called once per flush, so it's not).self._fd is replaced with a new file handle.None. If any open() or close() call raises an OSError (disk full, permission denied, file deleted), the exception propagates uncaught. This can leave the object in a partially broken state — e.g., if the second open fails, self._fd holds a closed handle from step 3, and subsequent append() calls will raise ValueError: I/O operation on closed file.
Called exactly once per flush cycle, from LSMTree._flush():
def _flush(self):
# ... write memtable to SSTable ...
self._wal.truncate() # SSTable is durable; WAL data is now redundant
The caller must ensure the SSTable write completed successfully before calling truncate. If truncate runs before the SSTable is durable, a crash would lose data — the WAL is gone and the SSTable never landed. The current code does this correctly: SSTable.write() completes (including closing the file) before truncate() is called.
open() / file object close(). No external libraries."wb" semantics for truncation.self.fd has not already been closed by a prior close() call — calling truncate() after close() will raise on the first self.fd.close().wal-truncate-clears-file — WAL.truncate() reduces the WAL file to zero bytes by opening it in "wb" mode, which truncates on open per POSIX semanticswal-truncate-restores-append-mode — After truncation, the file handle is re-opened in "ab" mode so the WAL can immediately accept new append() callswal-truncate-called-after-flush — truncate() is called by LSMTree._flush() only after SSTable.write() has completed, preserving the invariant that WAL data is cleared only when it's durable elsewherewal-truncate-no-error-recovery — If any open() or close() call within truncate() fails, the exception propagates uncaught and can leave self._fd in an unusable statewal-no-fsync — Neither WAL.truncate() nor WAL.append() calls os.fsync(), so durability depends on OS buffer flush timing rather than being guaranteed at the application level