Documentation
¶
Overview ¶
Package logfile implements a log file optimized for SSD and concurrency. It's suitable to be used as a WAL file.
Design:
- Group Commit: a single background flusher batches concurrent or pipelined writes into one IO write and fsync operation, maximizing SSD throughput.
- Aligned Writes: File appends are explicitly padded to 4KB sector boundaries to optimize for SSD.
- Record Framing: Each record is prefixed with a 9-byte header (1 byte marker, 4 byte length, and 4 byte crc32).
- Zero heap allocations per write.
Writers append into an in-memory buffer. A single background flusher drains it using a ping-pong buffer so new appends can be staged while the previous batch is being fsynced. Two entry points are exposed:
- Write blocks until the appended record is durable. Best for many concurrent goroutines, which naturally batch into one fsync.
- WriteAsync returns as soon as the record is buffered. Best for a single writer that pipelines many records. Pair it with Flush to wait for durability at checkpoints.
The reader sequentially reads records using the 9-byte header and a provided buffer to avoid allocations, stopping on EOF or padding.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ( ErrInvalidRecord = errors.New("logfile: invalid record") ErrCRCMismatch = errors.New("logfile: crc checksum mismatch") ErrClosed = errors.New("logfile: closed") ErrRecordTooLarge = errors.New("logfile: record too large") ErrWriterInBadState = errors.New("logfile: writer in bad state") )
Functions ¶
This section is empty.
Types ¶
type LogFile ¶
type LogFile struct {
// contains filtered or unexported fields
}
func New ¶
New returns a LogFile.
- maxBufSize: threshold before applying backpressure.
- withCRC: CRC is optional and can be written on per record basis.
func (*LogFile) Close ¶
Close stops accepting new writes, lets the flusher drain whatever is buffered, and returns once the flusher has exited.
func (*LogFile) Write ¶
Write appends data and blocks until it's durable. Write returns the starting logical file offset of the framed record. Many concurrent Write calls naturally batch into a single fsync.
Context cancellation: If the context is canceled after data has been appended to the internal buffer but before the sync completes, the caller receives a context error. However, the data may still be flushed to disk by the background flusher. Callers should not assume that a context error means the write was not persisted.
func (*LogFile) WriteAsync ¶
WriteAsync appends data and returns as soon as it's buffered, without waiting for fsync. This is the entry point for a single writer that wants to pipeline many records: keep calling WriteAsync, then call Flush at a checkpoint to wait for durability.
The returned offset is reserved as if the write had completed. Backpressure still applies: WriteAsync may block briefly if the buffer is full.
type Reader ¶
type Reader struct {
// contains filtered or unexported fields
}
Reader provides sequential reading of framed LogFile records. Reader is not *thread-safe* unless it's wrapped in a mutex by the caller.
func NewReader ¶
NewReader creates a new Reader starting at the specified logical file offset. This should match an offset returned by LogFile.Write or be zero.