pager

package
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 23, 2026 License: BSD-3-Clause Imports: 7 Imported by: 0

Documentation

Overview

Package pager is aki's single-file pager and buffer pool (spec 2064 doc 03). It turns a flat VFS file into an array of fixed-size pages, caches hot pages in memory, tracks dirty pages, allocates and frees pages through a freelist, and commits a transaction atomically by swapping the double-buffered meta page (doc 02 §9). Durability via the write-ahead log is layered on top in the wal package (doc 04); on its own the pager is already crash-atomic because a commit becomes visible only when the higher-sequence meta page is fsynced.

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrClosed       = errors.New("aki/pager: pager is closed")
	ErrPinned       = errors.New("aki/pager: page still pinned")
	ErrInvalidPage  = errors.New("aki/pager: invalid page number")
	ErrNoMeta       = errors.New("aki/pager: no valid meta page")
	ErrReadOnlyMeta = errors.New("aki/pager: page 0/1/2 are reserved")
)

Errors returned by the pager.

Functions

This section is empty.

Types

type CommitInfo

type CommitInfo struct {
	CatalogRoot   uint32
	SystemRoot    uint32
	DBRootPages   [8]uint32
	WALCommitLSN  uint64
	SchemaVersion uint32
	// SetDBRoots, when true, replaces the DB root array; otherwise the existing
	// roots are kept.
	SetDBRoots bool
	// SetCatalogRoot, when true, replaces the catalog root.
	SetCatalogRoot bool
	// SetSystemRoot, when true, replaces the system table root.
	SetSystemRoot bool
}

CommitInfo carries the per-commit values the caller wants recorded in the new meta snapshot: the updated catalog root, the per-DB B-tree roots, and the WAL commit LSN (zero when the WAL is not in use). Fields left at their zero value inherit the current live meta.

type Options

type Options struct {
	// PageSize is used only by Create; Open reads it from the header. Zero means
	// format.DefaultPageSize.
	PageSize uint32
	// DBCount is used only by Create. Zero means format.DefaultDBCount.
	DBCount uint32
	// CachePages is the buffer-pool capacity in frames. Zero means a default.
	CachePages int
	// CreateTimeUS stamps the header at create time. Tests pass a fixed value;
	// the engine passes the wall clock. Zero is allowed.
	CreateTimeUS uint64
}

Options configure a new or opened pager.

type Page

type Page struct {
	No   uint32
	Data []byte
	// contains filtered or unexported fields
}

Page is a single in-memory page frame. Data is exactly pageSize bytes and is the authoritative copy while the page is cached; readers and writers operate on Data directly and mark the page dirty through the pager.

func (*Page) Header

func (p *Page) Header() (format.PageHeader, error)

Header parses the common page header from the front of the page.

func (*Page) PutHeader

func (p *Page) PutHeader(h format.PageHeader) error

PutHeader writes h into the front of the page and marks it dirty-pending; the caller still unpins with dirty=true to schedule write-back.

type Pager

type Pager struct {
	// contains filtered or unexported fields
}

Pager owns a single .aki file and its in-memory page cache.

func Create

func Create(fsys vfs.VFS, name string, opts Options) (*Pager, error)

Create initialises a fresh .aki file: page 0 header, meta pages 1 and 2, and an empty freelist. It fails if the file already exists with content.

func Open

func Open(fsys vfs.VFS, name string, opts Options) (*Pager, error)

Open opens an existing .aki file, validates the header, and selects the live meta page.

func (*Pager) Allocate

func (p *Pager) Allocate() (*Page, error)

Allocate returns a fresh page for writing, reusing a freelist page when one is available or extending the file otherwise. The returned page is pinned and already marked dirty; its contents are zeroed.

func (*Pager) CheckFreelist

func (p *Pager) CheckFreelist() (int, error)

CheckFreelist walks the on-disk freelist chain from the meta head, following the next-link in each free page. It detects a cycle and an out-of-range link, which a plain load cannot since it would loop or read garbage. It returns the number of free pages on a healthy chain. The integrity checker calls it.

func (*Pager) Close

func (p *Pager) Close() error

Close flushes nothing implicitly (callers Commit first) and releases the file handle. It errors if any page is still pinned.

func (*Pager) Commit

func (p *Pager) Commit(info CommitInfo) error

Commit makes the current set of dirty pages durable and atomically advances the live meta snapshot (doc 02 §9.1, doc 03 §8). The protocol is:

  1. flush every dirty data page to its slot and fsync, so the page images are durable before the meta pointer that references them;
  2. persist the freelist chain if it changed;
  3. build the next meta with seq = live+1, write it to the non-live meta slot, and fsync, which is the linearization point: the commit is visible exactly when this fsync returns;
  4. best-effort refresh of the file header's mutable fields.

A crash before step 3's fsync leaves the previous meta live, so the whole transaction rolls back atomically with no journal.

func (*Pager) Free

func (p *Pager) Free(pgno uint32) error

Free returns pgno to the freelist. Reserved pages (0, 1, 2) cannot be freed.

func (*Pager) FreeCount

func (p *Pager) FreeCount() int

FreeCount returns the number of pages currently on the freelist.

func (*Pager) FreePages

func (p *Pager) FreePages() []uint32

FreePages returns a copy of the in-memory freelist. The page-accounting check uses it to prove no live page is also free, and to find leaked pages that are neither live nor free.

func (*Pager) Get

func (p *Pager) Get(pgno uint32) (*Page, error)

Get pins and returns the page numbered pgno, faulting it in from disk if it is not resident. The caller must Unpin it when done.

func (*Pager) Header

func (p *Pager) Header() format.FileHeader

Header returns a copy of the file header.

func (*Pager) Meta

func (p *Pager) Meta() format.MetaPage

Meta returns a copy of the live meta snapshot.

func (*Pager) Name

func (p *Pager) Name() string

Name returns the file path this pager was opened with. It is empty for an in-memory backing.

func (*Pager) PageCount

func (p *Pager) PageCount() uint32

PageCount returns the current total page count.

func (*Pager) PageSize

func (p *Pager) PageSize() uint32

PageSize returns the file's page size.

func (*Pager) PinnedPages

func (p *Pager) PinnedPages() []uint32

PinnedPages returns the page numbers currently held with a non-zero pin count. After a command finishes every page should be unpinned, so a debug build calls this to catch a Get that was never matched by an Unpin (doc 23 section 9.4).

func (*Pager) Stats

func (p *Pager) Stats() Stats

Stats returns the current pager counters. FileBytes is the on-disk size the page count implies, which is what the dataset-file growth field reports.

func (*Pager) Unpin

func (p *Pager) Unpin(pg *Page, dirty bool)

Unpin releases a pin on pg. If dirty is true the page is marked for write-back at the next Commit.

type Stats

type Stats struct {
	PageSize      uint32
	PageCount     uint32
	FreeCount     int
	FileBytes     int64
	ResidentPages int
	DirtyPages    int
	CacheHits     uint64
	CacheMisses   uint64
}

Stats is a point-in-time snapshot of pager and buffer-pool counters. The server reads it for the file-growth INFO fields in doc 20 section 9.8.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL