- Reworked concurrency control into a fact-based MVCC model
- Added persisted global engine options
- Introduced an internal filesystem boundary for path-level operations with a fault-injecting implementation for tests
- Added SI/visibility, recovery and filesystem-failpoint test suites plus an
extra_check-gated testing surface for deterministic sync points
- Removed
Mace::vacuum_bucketandMace::is_bucket_vacuuming, and renamedvacuum_metatocompact_meta - Removed runtime background delta compaction from the evictor
- Standardized all persisted integer layouts on little-endian
- Hardened startup recovery teardown so a failed open releases manifest state, reconstructed abort-clean work and store resources instead of leaving partially initialized state behind
- Refreshed
docs/design.mdand the constraint registry to match the current runtime, recovery, checkpoint, WAL recycle and GC behavior - Reworked
README.md: storage format and public APIs are now considered essentially stable and ready for production evaluation
- Improved tree lookup and read-path locality
- Fixed a visibility hole caused by retiring same-generation structural junk too early
- Fixed durable-frontier information loss for remote values
- Fixed the WAL maintenance boundary reading a lagging source of truth
- Fixed foreground admission waiters stalling on snapshot-backed predicates that are not paired with a condvar signal, by rechecking on a bounded timeout
- Added optional zstd compression for persisted bucket data and blob records
- compression is controlled by bucket option
enable_compressionand defaults tofalse - GC rewrite and recovery paths preserve compressed record layout correctly
- compression is controlled by bucket option
- Reworked bucket cleanup and abort recovery to use bounded GC cleanup, keep abort-clean buckets pinned, and finish pending abort cleanup during recovery
- Added durable WAL recycle frontier metadata plus recovery/failpoint coverage for recycle crash windows
- Fixed flush/GC stale-stat races by skipping retired old-file stats, delaying junk-stat publication until manifest commit, and using conditional btree updates for old stat writes
- Fixed read-view
start_tspublication so active snapshot floor tracking cannot observe half-published views during view allocation handoff - Fixed checkpoint carry-over visibility so live
addr > snap_addrpages and retired lineage remain continuously visible acrosssealed -> hothandoff during concurrent GC reads
- Separated bucket-scoped runtime tuning from global
Optionsinto persistedBucketOptionsMace::new_bucketnow takesBucketOptions, andMace::update_bucket_optallows updating persisted bucket policy while the bucket is unloaded- bucket metadata now persists bucket options and rejects incompatible reopen-time changes to compatibility-sensitive fields such as
inline_sizeandsplit_elems
- Refined cache ownership so the shared LRU only tracks file-loaded blob values and sibling/history helper pages
- resident tree pages are no longer inserted into the shared LRU, reducing cache-role overlap between page residency and blob/helper-object caching
- eviction sampling and per-bucket cache pressure continue to be driven by bucket-local cache settings
- Added stateful
cargo-fuzzlifecycle targets plus a bounded fuzz regression script for checkpoint/reopen, publish/GC/reopen, and bucket lifecycle churn
- Fixed bucket-scoped evictor pressure handling
- Fixed read-view epoch handoff so lagging snapshot floor publication stays consistent across quiescent-view transitions and compaction does not miss live snapshot history
- Refactored transaction write path to metadata-only visibility checks
- Align GC victim selection and gates with intended semantics
- Removed undo replay path and moved transaction handling to abort-aware visibility with redo-only
WalUpdate- dropped rollback/undo payload fields and rollback replay flow from WAL/recovery paths
- added pending abort-clean tracking/state transitions and startup rebuild for unfinished abort cleanup
- foreground conflict handling can remove aborted heads before retry while readers always filter aborted versions
- Implemented
DoubleEndedIteratorfor seek/range iterators- added
next_back()with reverse leaf discovery (find_prev_leaf/find_leaf_for_next_back) and reverse raw-leaf iteration - ensured mixed
next()+next_back()consumes one shrinking key range with correct include/exclude bound semantics - added cross-node reverse iteration and MVCC visibility regression coverage in
tests/cc.rs
- added
- Reworked sibling/history layout from sibling-head chaining to key-local history region references
- introduced
HistRefregion descriptors (page_addr,slot,count) for bounded per-key history traversal - updated compact/build paths to persist history regions safely across shared history pages
- hardened traversal correctness to avoid cross-key history leakage during history fallback
- introduced
- Deleted incorrect assertionsn
- Fixed merge-path epoch split where
replaceand childmark_unmapcould cross checkpoint cut and classify one addr as both dirty root and junk - Fixed durability closure around directory metadata updates and expanded crash-window validation:
- Added cross-platform
sync_dirand used it for data/log directory sync after flush, WAL rotate/recycle, GC rewrite, delete-files, and recovery orphan cleanup - Added failpoints for file-sync/dir-sync boundaries and corresponding production recovery chaos tests
- Recovery now rejects sparse WAL gaps after checkpoint frontier instead of silently continuing replay
- Added cross-platform
- Fixed a reachable-junk lifecycle regression that could cause
addr not in interval/ falseNotFoundreads during checkpoint churn.- Junk handling now distinguishes structural junk from compaction junk: only structural junk is retired at publish time, while compaction junk remains readable in dirty generations until checkpoint durability closure.
- Checkpoint snapshot now tracks and filters newly produced junk addresses per epoch, and keeps sibling/remote-hint reachability traversal intact, preventing interval lookup holes for still-reachable addresses.
- Added a regression test (
reachable_junk_regression_guard) to verify lagging-view reads remain correct across split/consolidate/checkpoint churn.
- Refactored Pool from an arena/batch-oriented flush pipeline to a page-checkpoint pipeline: checkpoint now snapshots sealed page generations, frozen dirty roots, and retired chains directly from page state.
- Optimized flow control by replacing sleep-based debt throttling with checkpoint-aware foreground admission permits, progress-driven wakeups, and per-bucket controllers tuned by
checkpoint_sizeandpool_capacity.
- Fixed cross-bucket shared LRU cache key collisions during multi-bucket reopen/recovery reads, and reduced the repaired hot-path lookup overhead with
FxHasher.
- Added observer-based observability with GC coverage
- Added pending sibling metadata flow to preserve crash-closure and prevent arena exhaustion under excessive sibling chains
- Added backpressure-aware flush pacing and junk leak handling improvements
- Optimized scan hot paths and hardened ccpool shrink behavior
- Reduced key copies in index iterator filtering
- Fixed evictor panic on tagged swip during shutdown
- Fixed sibling junk collection routing through base iterator
- Fixed orphan marker cleanup to preserve max file IDs
- Added
Mace::vacuum_bucketandVacuumStats(scanned,compacted) to support explicit per-bucket vacuuming - Added
Mace::vacuum_metaandMetaVacuumStatsto compact manifest metadata btree - Added
Mace::is_bucket_vacuumingto expose bucket vacuum inflight state - Added production validation suites and scripts:
scripts/prod_test.sh(fast|stress|chaos|all),scripts/prod_soak.sh,scripts/perf_gate.sh
- Removed WAL descriptor side files (
meta_{group}) and rebuilt WAL bootstrap from WAL file scanning during recovery - Extended checkpoint records to carry checkpoint position in WAL and used latest valid checkpoint discovery during recovery
- Added explicit WAL durability barrier before manifest flush commit, then moved checkpoint advancement to post-
mark_donephase - Reworked WAL recycle boundary tracking from descriptor persistence to logging in-memory oldest-id propagation
- Added production integration tests across bucket/concurrency/evictor/gc/recovery/workload with failpoint chaos coverage
- Added failpoint runtime (
MACE_FAILPOINT) and injected crash/io/abort points across flush/wal/manifest/gc/evictor/txn commit boundaries
- Switched SMO flow to runtime markers and aligned split/merge execution paths to reduce structural race amplification
- Removed arena chunk allocator and reverted to direct allocation path
- Optimized rollback log sync path and
Tree::linklocking behavior - Simplified hot-path alloc API by removing redundant
bucket_idargument - Consolidated WAL/group optimization series for 16B/10K scale goals, including inflight-aware group selection, logging/checkpoint flow cleanup, in-memory oldest WAL boundary propagation, and reduced lock-held read contention in stat cache paths
- Fixed packed-allocation crash-closure correctness: dependent frames now stay in one packed allocation scope (same arena + contiguous address span), and plan/usage mismatch fails fast instead of silently degrading
- Fixed iterator lifetime UB in
Tree::iterand stabilized leaf iterator state to avoid intermittent crashes - Fixed orphan-file crash-recovery boundary by switching to marker-driven cleanup (
odf_*/obf_*) instead of tail probing - Fixed rollback WAL sync ordering on transaction drop
- Hardened bucket context reclaim lifecycle under gc/evictor concurrency
- Fixed GC/txn path correctness issues and improved error mapping (
btree_store::Error::Internal -> OpCode::Invalid)
- Bucket-centric lifecycle and runtime/metadata separation: Store owns bucket state, flush results are routed through Store to update Manifest, and runtime components no longer write metadata directly
- Metadata and interval structure refactor: ImTree moved to
src/utils, interval/stat paths updated, and per-bucket file indexes added for faster deletion - Manifest bucket tables migrated to
DashMapwith a structural lock to reduce contention on create/delete - Store API reorganization plus test/bench expansion, including new
src/store/store.rs,tests/bucket.rs, andbenches/perf.rs
- Enhanced error handling across the system
- Optimized Arena to avoid allocating small objects via alloc; integrated FxHash for DashMap
- Added version validation for metadata
- Simplified transaction recording for Flush and GC operations
- Removed TxnKV concurrency limits and decoupled Logging from TxnKV, allowing multiple TxnKV instances to share the same Logging component.
- Implemented full checksum support for every WAL entry to ensure data integrity
- Fixed an incorrect assertion in flush.rs:flush_data
- Refactor metadata storage with
btree-store - Add checksum to
WalUpdate - Add a scavenger routine to clean up stale versions
- Optimize random insert performance
- Fixed data race in
DataStatCtxandBlobStatCtx
- Separate Read-Only transaction from worker, use a pool which can dynamic allocate new ConcurrencyControl on demand
- Share ConcurrencyControl between
Iterand it's creator
- Crash when
extra_checkfeature enabled caused byFuseBaseItermay return duplicated keys - Crash in
rollbacktest. When the ring buffer was filled exactly to the boundary (modulo capacity), the subsequent allocation would start at index 0 without flushing the previous data. This caused flush to attempt to slice a contiguous range that actually wrapped around the physical buffer, leading to an out-of-bounds access. - Incorrect condition check in
Cache::evicttrigger assertion in evictor Tree::traverse_siblingnot walk through candidate versions
- Stop share cache_key with lo, because it's obscure and hard to understand
- Fxied Iter can return wrong key-value, because when newer version of key is in delta it's not separated to prefix + base, so store base in Filter is wrong, change to store full key
- Fxied
Node::find_latest, the expect behavior is return latest version of data based on given key and version, the original implementation use binary search which is wrong when key + version is not exist in ImTree, userange_frominstead
- Share cache_key with lo in Iter to avoid extra allocation
- Fixed scan crash when key in base was updated or deleted (or both), it's possible when a node was scanned and swith to another node and the key in that node was changed by other transaction
- Optimize prefix scanning performance
- Fixed compile error introduced in 0.0.18 on Windows
- Reduce
Relocsize
- Support value separate storage by default, user can set
Options::inline_sizeto control whether value should be stored in blob files
- Support verify checksum everytime when load data from disk (including GC)
- The data file footer has been changed (swapped relocations and intervals)
- Add priority LRU cache to support cache blob (which is Low priority)
- Fxied
index out of bound errorin builder.rs:redo_impl by neverclearthedata/blob_deleted - Fixed GC assertion because of remove
del_intervalsmore then once
- Fixed manifest's txid was not initialized correctly
- Fixed some obsolete WAL files can't be removed
- Optimize data file's gc_ratio calculation and victims selection
- Separate key-value storage, keys and small values are always stored in sst, while big value will be stored out of sst
- Fixed garbage can't be cleaned (active frames after filter mey be marked as deactive by flush thread)
- Add a layer of indirection allows the data file ID to be represented using 64 bits
- Force checkpoint when WAL file too large
- Reduce memory consumption
- always
cloneloader when a node was compacted - remove unnecessary
pininSysTxn - clear arena when it was flushed
- always
- Remove
rollback, if the txn is not committed, it will be implicitly rolled back
- Fixed
NodeCachenot being able to limit memory usage - Fix arena being flushed while still being mutably referenced
- Fix
LayoutinBlock
- Simplify data file layout, move meta fields into a manifest file actually, it's not the best solution, we should use something like BoltDB, so that we don't need to load all the mappings into memory
- Fix leak in cache evict
- Remove some unused wal record type, and unused fields in WalCheckpoint
- Bring back log flush before data
- Extend wal id and checkpoint position to 64 bits
- Partially support data file id wrapping (use an extra
tickto generateup2, an extraepochto keepMapEntryordered) - Allow to store wal file in separate directory
- Limit maximum node size
- Fix
warm_upnot change cache size - Fix possible assert in evictor (when pid unmap happens)
- Fix possible infinite loop in
NodeCache::evictandGarbageCollector::process_data - Fix
fetch_submemory order
- Add new evictor thread compact node on cache evict and randomly pick active node for compaction
- Change
consolidate_threshold's maximum value tosplit_elems - Create
SysTxnwhen it's necessary - Add
Mutexto each node which- mitigate multi-threaded contention in both compaction and SMO
- reduce wasted memory allocation
- remove check in
Node::insert_indexwhich is unnecessary now
- Move node compact in
Tree::linktoTree::try_find_leafwhich mitigate multi-threaded contention
- Fix
upsert - Enable missing node cache warm up when cache hits
- Fix GC remove WALs that still in use
- Fix duplicated garbage collection in
merge_node - Fix
MapBuilder:add's assert which is possible in some case - Fix
Node::search_sst's assert which is possible in some case
- Support prefix encoding
- Dynamic arena allocation
- Removed all xxRef except BoxRef
- Unified BoxRef management, which greatly reduces the occurrence of cloning, especially in ImTree
- Disabled cc compact for read-only txn
- Replaced the
Queueimplementation to improve concurrency
- Atomic
upsert
- Replace delta-chain implementation to ImTree
- Abstract
Nodeimplementation - Save remote addresses directly into sst for quickly recycle
- Reduce garbage creation
- Fix
LruInner::getdata race - Fix
log.rsrollback lsn point to junk data and subtraction overflow
- Separate
mapfromdatafile - Support
mapfile compaction
- Fix
BitMapbits calculation
consolidationwill collect remote frames- Simplify wal file cleaning
- Optimize branch misses by rearranging code layout
- Fix typo in
need_split - Fix
last_ckptinit inlog.rs - Fix
use-after-freeissue in consolidate
- Support key-value size up to half
buffer_size(it may cause up to 7% degradation in read/write performance, we will try to optimize it in subsequent versions)
- Fix a
use-after-freeissue that may occur when manually drop db instance
- Support
scalable-logging