file_backed
Provides types for managing collections of large objects, using an in-memory LRU cache backed by persistent storage (typically the filesystem).
Overview
This crate provides FBPool and Fb (File-Backed item) to manage data (T) that might be too large or numerous to keep entirely in memory. It uses a strategy similar to a swap partition:
- In-Memory Cache: An LRU cache (
FBPool) keeps frequently/recently used items readily available in memory. - Backing Store: When items are evicted from the cache, or when explicitly requested, they are serialized and written to a temporary location in a backing store (like disk).
- Lazy Loading: When an item not in the cache is accessed via its
Fbhandle (.load(),.blocking_load(), etc.), it's automatically read back from the backing store. - Automatic Cleanup: When an
Fbfor an item is dropped, its corresponding data in the temporary backing store is automatically deleted via a background task. - Persistence: Items can be explicitly "persisted" (e.g., hard-linked) to a separate, permanent location and later "registered" back into a pool, allowing data to survive application restarts.
Core Components
FBPool<T, B>: Manages the collection, including the LRU cache and interaction with the backing store.Fb<T, B>: A container for an item managed by the pool. Access requires calling a.load()variant.BackingStoreTTrait: Defines the low-level storage operations (delete, persist, register, etc.). You typically implement this or use a provided one (likeFBStore). This handles where and how raw data blobs (identified byUuid) are physically stored.Strategy<T>Trait: ExtendsBackingStoreT. Defines how your specific data typeTis serialized (store) and deserialized (load).BackingStore<B>Struct: A wrapper around aBackingStoreTimplementation that manages concurrency, background tasks (using Tokio), and tracking of persistent paths.FBPooluses this internally.ReadGuard/WriteGuard: RAII guards returned byloadmethods, providing access to the data and ensuring it stays loaded.WriteGuardmarks data as dirty for writing back to the store.
Features
bincodec: Providesfbstore::BinCodec, an implementation offbstore::Codec<T>usingbincodefor serialization (requiresT: Serialize + DeserializeOwned).prostcodec: Providesfbstore::ProstCodec, an implementation offbstore::Codec<T>usingprostfor serialization (requiresT: prost::Message + Default).dupe: Implementsdupe::DupeforFb.
Basic Usage
This example shows basic insertion, loading (which may come from cache or disk), and automatic cleanup.
// examples/simple_usage.rs
use Arc;
use tempdir;
use Handle;
use ;
use ;
async
Persistence
Items can be persisted to survive application restarts using persist and brought back using register. This typically uses hard links in file-based stores.
// examples/persistence.rs
use Arc;
use tempdir;
use Handle;
use ;
use ;
async
Provided Filesystem Backing (FBStore)
FBStore is a filesystem-based implementation of BackingStoreT.
- It requires a
Codec<T>(BinCodecorProstCodecvia features, or your own implementation) to handle serialization. - It uses a
PreparedPath, which manages a directory structure (subdirectories00toff) for sharding files based on theirUuid. persistandregisterare implemented usingstd::fs::hard_link.
Concurrency
- The
BackingStoreuses a Tokio runtime (tokio::runtime::Handle) provided during initialization to manage background tasks (like deletions, cache write-backs) and async operations. - Methods often come in pairs:
some_operation()/spawn_some_operation(): Return aFutureorJoinHandle, suitable for async contexts.blocking_some_operation(): Perform the operation blockingly. Must not be called from an async context unless usingspawn_blockingorblock_in_place.
Fb::load_in_place(): Special case. If data isn't in memory, it usestokio::task::block_in_placeto call the blocking load logic. Warning: This will panic if called within atokio::runtime::Runtimecreated usingRuntime::new_current_thread. Useloadin async code.- The library aims to be thread-safe and select/cancel-safe; concurrent access via different
Fbhandle references (even for the same data) or pool operations from multiple threads should be handled correctly via internal synchronization.
Running Examples
cargo run --example simple_usage --features=bincodec
cargo run --example persistence --features=bincodec