Multi-Version & Garbage Collection (Experimental)
Preview — 0.8.0-preview1: APIs may change before stable release.
The StateTree and GC APIs used in this section are experimental and not ready for production use. They are available for testing and feedback but may change significantly before stable release.
RocksDbStateTrees
RocksDbStateTrees provides multi-version support, allowing you to maintain versioned snapshots of the trie and
roll back to any previous version.
Setup
import com.bloxbean.cardano.vds.mpf.rocksdb.RocksDbStateTrees;
import com.bloxbean.cardano.vds.mpf.MpfTrie;
import com.bloxbean.cardano.vds.core.api.StorageMode;
// Enable versioning
RocksDbStateTrees stateTrees = new RocksDbStateTrees("data/mpf", StorageMode.MULTI_VERSION);
// Get node store and create MpfTrie
MpfTrie trie = new MpfTrie(stateTrees.nodeStore());Versioning
// Version 1
trie.put("alice".getBytes(), "100".getBytes());
long v1 = stateTrees.putRootWithRefcount(trie.getRootHash());
// Version 2
trie.put("alice".getBytes(), "150".getBytes());
long v2 = stateTrees.putRootWithRefcount(trie.getRootHash());
// Rollback to version 1
byte[] rootV1 = stateTrees.rootsIndex().get(v1);
trie.setRootHash(rootV1);
byte[] value = trie.get("alice".getBytes()); // Returns "100"API Reference
// Constructors
RocksDbStateTrees(String path)
RocksDbStateTrees(String path, StorageMode mode)
RocksDbStateTrees(RocksDB db, StorageMode mode)
// Version management
long putRootWithRefcount(byte[] rootHash) // Stores root hash, returns version number
// Access internals
RocksDbNodeStore nodeStore()
RocksDbRootsIndex rootsIndex() // Access version→root mapping
RocksDB db()Garbage Collection (Experimental)
Experimental: Garbage collection is available for testing but APIs may change significantly before stable release.
MPF with RocksDB includes a mark-sweep GC strategy to reclaim space from stale nodes that are no longer reachable from any retained root.
Mark-Sweep GC
Marks reachable nodes from retained roots, then sweeps unreachable ones. Uses a temporary RocksDB column family to persist the mark set, keeping memory usage low even for large tries.
import com.bloxbean.cardano.vds.mpf.rocksdb.gc.*;
import com.bloxbean.cardano.vds.mpf.rocksdb.gc.strategy.OnDiskMarkSweepStrategy;
GcManager gcManager = new GcManager(
stateTrees.nodeStore(),
stateTrees.rootsIndex()
);
GcOptions options = new GcOptions();
options.deleteBatchSize = 10_000;
options.progress = deleted -> System.out.println("Deleted: " + deleted);
// Run GC (keep latest 5 versions)
RetentionPolicy policy = RetentionPolicy.keepLatestN(5);
GcStrategy strategy = new OnDiskMarkSweepStrategy();
GcReport report = gcManager.runSync(strategy, policy, options);
System.out.println("Deleted nodes: " + report.deleted);
System.out.println("Duration: " + report.durationMillis + "ms");GcManager API
// Constructor
GcManager(RocksDbNodeStore nodeStore, RocksDbRootsIndex rootsIndex)
// Synchronous GC
GcReport runSync(GcStrategy strategy, RetentionPolicy policy, GcOptions options)
// Asynchronous GC
CompletableFuture<GcReport> runAsync(GcStrategy strategy, RetentionPolicy policy, GcOptions options)GcOptions
GcOptions options = new GcOptions();
options.deleteBatchSize = 10_000; // Nodes per delete batch
options.progress = n -> log.info("{}", n); // Progress callback
options.dryRun = false; // Set true to simulateGcReport
GcReport {
long marked; // Nodes marked as reachable
long deleted; // Nodes deleted
long total; // Total nodes processed
long durationMillis; // Execution time
}Retention Policies
Retention policies determine which versions to keep during GC.
// Keep latest N versions
RetentionPolicy.keepLatestN(10);
// Keep specific versions
RetentionPolicy.keepVersions(List.of(1L, 5L, 10L));
// Keep a range of versions (inclusive)
RetentionPolicy.keepRange(5, 15);