Class WriteAheadLog

java.lang.Object
dev.frostlake.persistence.WriteAheadLog

public class WriteAheadLog extends Object
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
    Constructor
    Description
     
  • Method Summary

    Modifier and Type
    Method
    Description
    void
    appendCheckpoint(String checkpointRef)
    Append a checkpoint marker referencing a durable state snapshot, and force it to disk.
    void
    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.
    void
    appendTransaction(List<String> statements, List<Instant> statementInstants)
    As appendTransaction(List), recording what these statements called "now" so replay can put it back instead of resolving CURRENT_TIMESTAMP to the recovery time.
    void
     
    All records in order (for replay); empty if the log doesn't exist yet or has only the header.
    void
    Rewrite the log keeping only the records from the given checkpoint marker onward (inclusive), bounding the log's growth after a checkpoint.

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Constructor Details

  • Method Details

    • appendTransaction

      public void appendTransaction(List<String> statements) throws IOException
      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
      As appendTransaction(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

      public void appendCheckpoint(String checkpointRef) throws IOException
      Append a checkpoint marker referencing a durable state snapshot, and force it to disk.
      Throws:
      IOException
    • readAll

      public List<WalRecord> readAll() throws IOException
      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

      public void truncateToCheckpoint(String checkpointRef) throws IOException
      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()