RoughDB
Embedded key-value storage written in Rust — a port of LevelDB to Rust.
RoughDB is an LSM-tree key-value store with a LevelDB-compatible on-disk format. It supports persistent (WAL + MANIFEST + SSTables) and in-memory operation, multi-level compaction, and bidirectional iteration.
[!WARNING] While I started this all "manually", many years ago... This is an experiment of sort. While I'm relatively serious about this, I also used it more recently to experiment with different things, including generative AI. I'm reviewing all changes manually and carefully.
Getting started
Opening a database
use ;
let mut opts = default;
opts.create_if_missing = true;
let db = open?;
Use Db::default() for a lightweight in-memory database (no WAL, no flush):
let db = default;
Basic reads and writes
use ;
// Write
db.put?;
db.delete?;
// Read
match db.get
Atomic batch writes
use ;
let mut batch = new;
batch.put;
batch.put;
batch.delete;
db.write?;
Iterating over keys
Iterators start unpositioned — call seek_to_first, seek_to_last, or
seek before reading.
use ReadOptions;
let mut it = db.new_iterator?;
// Forward
it.seek_to_first;
while it.valid
// Backward
it.seek_to_last;
while it.valid
// Range scan from "b" onward
it.seek;
while it.valid
Snapshots
A snapshot pins the database to a specific point in time; reads through it see only writes that preceded the snapshot.
use ReadOptions;
let snap = db.get_snapshot;
// Reads with this snapshot see the state at the moment it was taken.
let opts = ReadOptions ;
let value = db.get_with_options?;
let mut it = db.new_iterator?;
// snap releases automatically when it goes out of scope.
Manual compaction
// Compact everything
db.compact_range?;
// Compact a specific key range
db.compact_range?;
Building and testing
Status
RoughDB is in active development. The on-disk format is LevelDB-compatible.
Implemented:
- WAL + MANIFEST + SSTable flush and crash-safe recovery
- Multi-level compaction (L0→L1,
compact_range) with snapshot-aware pruning and tombstone elision - Bidirectional iteration (
seek_to_first,seek_to_last,seek,next,prev) - Snapshots (
get_snapshot/release_snapshot) - Bloom filter support (
Options::filter_policy) - Block compression: Snappy (default) and Zstd (
Options::compression) get_property—leveldb.num-files-at-level<N>,leveldb.stats,leveldb.sstables,leveldb.approximate-memory-usageget_approximate_sizes— byte-range estimation via index-block seeksdestroy— safely removes a database directoryLOCKfile — prevents concurrent opens by multiple processes- Table cache — LRU open-file-handle cache bounded by
Options::max_open_files
Not yet implemented:
- Block cache (
ReadOptions::fill_cacheis accepted but ignored) - Batch-grouped writes (writes are serialised one at a time)
- Custom comparators
License
Apache License 2.0 — see LICENSE.