.__ .__
____ ____ | | | | _____
_/ ___\/ __ \| | | | \__ \
\ \__\ ___/| |_| |__/ __ \_
\___ >___ >____/____(____ /
\/ \/ \/
A crash-recoverable, single-writer, page-oriented B-tree key-value storage engine in Rust.
This project focuses on storage-layer fundamentals rather than SQL semantics. It implements durable set/get/delete/scan operations on a persistent B-tree, with write-ahead logging (WAL), recovery, page reuse, and a professional CLI for interactive and scripted usage.
- 4KB fixed-size page model (
Page { id, data: [u8; 4096] }) - Persistent B-tree with multi-level splits and recursive traversal
- Delete support with leaf/internal rebalancing (borrow/merge)
- Leaf sibling chain for range scans
- WAL-based crash recovery (redo-style page replay on startup)
- Manual checkpoint (
fsync+ WAL truncate) - Free-list page reuse with chained overflow freelist pages
- Structural invariants verification (
verify_tree) - CLI with subcommands, JSON output, REPL, benchmark tools, and DOT graph export
The engine is intentionally page-centric:
- Data file pages: B-tree internal/leaf nodes, freelist metadata, overflow pages
- WAL file: append-only records that log page images before data-page writes
- Recovery: on open, WAL records are replayed to data pages, then WAL is truncated
Core modules:
src/storage/page.rs: page header/layout, slot directory, cell operationssrc/storage/disk.rs: page file I/O, allocation, sync operationssrc/storage/btree.rs: B-tree logic, rebalancing, verification, stats, DOT dumpsrc/storage/wal.rs: WAL record append/read/truncatesrc/storage/freelist.rs: persistent free-list with overflow chainingsrc/main.rs: CLI + REPL
- Page size is fixed at 4096 bytes.
- Slotted-page layout supports variable-size cells.
- Leaf cells encode key/value bytes.
- Internal cells encode route entries (
min_key -> child_page_id). - Leaf pages maintain
next_leafpointers for ordered scans.
Write path:
- Append page image to WAL and sync WAL record.
- Write page to data file.
Startup path:
- Read all WAL records.
- Replay page payloads to target page IDs.
- Truncate WAL.
Checkpoint path:
- Sync data file.
- Truncate WAL.
Run REPL (default command when no subcommand is provided):
cargo run -- --db kv.db replOne-shot commands:
cargo run -- --db kv.db set user:1 alice
cargo run -- --db kv.db get user:1
cargo run -- --db kv.db del user:1
cargo run -- --db kv.db scan --start user:1 --limit 20
cargo run -- --db kv.db verify
cargo run -- --db kv.db checkpoint
cargo run -- --db kv.db statsJSON output (automation-friendly):
cargo run -- --db kv.db --json statsBenchmark commands:
cargo run -- --db kv.db bench 20000
cargo run -- --db kv.db benchmix 50000DOT graph export:
cargo run -- --db kv.db dumpdot --out tree.dot
dot -Tpng tree.dot -o tree.pngSET <key> <value>GET <key>DEL <key>SCAN [start_key] [limit]CHECKPOINTVERIFYSTATSBENCH [n]BENCHMIX [n]DUMPDOT [path]HELPEXIT
The REPL includes line editing, history, and typo-aware command suggestions.
cargo build
cargo testThis repository targets storage-engine internals, not SQL features. It is a single-writer engine focused on correctness, durability, and observability.
Not in scope (currently):
- SQL parser/planner/executor
- multi-writer concurrency control
- networked replication
- background compaction/checkpoint workers
The test suite covers:
- page layout invariants
- disk read/write and allocation behavior
- WAL append/truncate and recovery replay
- multi-level tree growth and lookups
- delete behavior with rebalance and collapse
- freelist overflow chaining and reuse
- crash-recovery scenarios
- Prometheus metrics endpoint + Grafana dashboard
- background checkpointing and batched WAL sync policy
- expanded randomized/fuzz crash testing in CI
- deeper page inspection/debug commands
MIT License