Package dev.frostlake.persistence
Class WriteAheadLog
java.lang.Object
dev.frostlake.persistence.WriteAheadLog
Append-only write-ahead log — a logical (redo) log of committed transactions. Each committed transaction
is appended as ONE record (its mutating statements) and fsync'd before COMMIT returns, so a committed
transaction is durable atomically: a crash mid-append leaves a torn trailing record that replay discards,
so a transaction is recovered only when its whole record reached disk. On startup the engine replays the
records to rebuild state. This covers both autocommit statements (a one-statement record) and explicit
BEGIN…COMMIT blocks (a multi-statement record); a rolled-back transaction is never written.
A WalRecordType.CHECKPOINT marker records that a full state snapshot is durable; every record
before the last marker folds into that snapshot, so recovery loads the snapshot and replays only the
records after it, and the log can be truncated to the marker to bound its
growth. The marker is the atomic pivot: a crash before it leaves an ignored orphan snapshot (no
double-apply), a crash after it recovers from the snapshot. See docs/acid-snowflake-plan.md.
Logical (statement) logging means replay RE-EXECUTES the SQL, so non-deterministic constructs (CURRENT_TIMESTAMP, RANDOM, sequence NEXTVAL) can differ on recovery — acceptable for this engine's local/CI-testing purpose.
-
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionvoidappendCheckpoint(String checkpointRef) Append a checkpoint marker referencing a durable state snapshot, and force it to disk.voidappendTransaction(List<String> statements) Append one committed transaction's statements as a single record and force it to disk — the fsync is the durability point, and writing the whole record under one fsync makes the transaction atomic on recovery.voidappendTransaction(List<String> statements, List<Instant> statementInstants) AsappendTransaction(List), recording what these statements called "now" so replay can put it back instead of resolving CURRENT_TIMESTAMP to the recovery time.voidclose()readAll()All records in order (for replay); empty if the log doesn't exist yet or has only the header.voidtruncateToCheckpoint(String checkpointRef) Rewrite the log keeping only the records from the given checkpoint marker onward (inclusive), bounding the log's growth after a checkpoint.
-
Constructor Details
-
WriteAheadLog
- Throws:
IOException
-
-
Method Details
-
appendTransaction
Append one committed transaction's statements as a single record and force it to disk — the fsync is the durability point, and writing the whole record under one fsync makes the transaction atomic on recovery. No-op for a null/empty statement list (a read-only transaction logs nothing).- Throws:
IOException
-
appendTransaction
public void appendTransaction(List<String> statements, List<Instant> statementInstants) throws IOException AsappendTransaction(List), recording what these statements called "now" so replay can put it back instead of resolving CURRENT_TIMESTAMP to the recovery time.- Throws:
IOException
-
appendCheckpoint
Append a checkpoint marker referencing a durable state snapshot, and force it to disk.- Throws:
IOException
-
readAll
All records in order (for replay); empty if the log doesn't exist yet or has only the header. A torn trailing record left by a crash mid-append is discarded, so only fully-written, fsync'd records are returned.- Throws:
IOException
-
truncateToCheckpoint
Rewrite the log keeping only the records from the given checkpoint marker onward (inclusive), bounding the log's growth after a checkpoint. The rewrite goes through a temp file + atomic rename so a crash can't leave a half-written log. No-op if the marker isn't found.- Throws:
IOException
-
close
public void close()
-