fs.rs
Overview
The fs.rs file implements a filesystem-backed key-value storage system through the FsStore struct, which conforms to the KeyValueStore trait. It serializes and deserializes Aerospike data types to and from the local filesystem, storing each record as a separate file within a specified directory. This approach enables persistent storage of key-value pairs on disk, leveraging Rust's type system and serialization libraries for safe and efficient data handling.
The file also contains serialization helper enums (SerdeValue and SerdeFloatValue) that convert between Aerospike's internal Value types and their serializable counterparts, facilitating the persistence process.
Structs and Enums
FsStore
Represents a filesystem-based key-value store.
Fields
data_dir: PathBuf
The directory path where key-value files are stored.
Methods
new(data_dir: impl Into<PathBuf>) -> anyhow::Result<Self>
Creates a new FsStore, ensuring the data directory exists by creating it if necessary.
Parameters:
data_dir: A path or string convertible to aPathBufdesignating the storage directory.
Returns:
Ok(FsStore) if the directory was created or already exists.
Errif directory creation fails.
Usage example:
let store = FsStore::new("/var/lib/myapp/data")?;
persist(tmp: NamedTempFile, path: &Path) -> anyhow::Result<()>
Attempts to atomically persist a temporary file to the target path.
Parameters:
tmp: A temporary file handle containing serialized data.path: The destination path for the persisted file.
Returns:
Ok(())on success or if the file already exists.Erron other IO errors.
Implementation details:
UsesNamedTempFile::persist()and handles theAlreadyExistserror gracefully to avoid overwriting existing data.
key_path(&self, key: &Key) -> PathBuf
Generates the full filesystem path for a given Aerospike Key.
Parameters:
key: The Aerospike key to be converted.
Returns:
A
PathBufformed by joining the store’s base directory and the string representation of the key.
Trait Implementation: KeyValueStore for FsStore
This implementation integrates FsStore into the system as a backend for key-value operations.
get(&self, key: &Key, _values: &Bins, _label: &'static str) -> anyhow::Result<Option<ValueMap>>
Retrieves the value map associated with a key.
Parameters:
key: The Aerospike key to retrieve._values: Ignored; placeholder for requested bins._label: Ignored; debugging label.
Returns:
Ok(Some(ValueMap))if the key exists and is successfully deserialized.Ok(None)if the key file does not exist.Errif reading or deserialization fails.
Implementation details:
Reads the file at the path computed bykey_path(), deserializes it usingbincodeinto aHashMap<String, SerdeValue>, then converts it into aValueMap.Usage example:
if let Some(value_map) = store.get(&key, &bins, "label")? { // process value_map }
put(&self, key: &Key, bins: &[Bin], _until: bool, _label: &'static str) -> anyhow::Result<()>
Stores or updates the value map for a key.
Parameters:
key: The Aerospike key to store.bins: A slice ofBinstructs representing the data to store._until: Ignored; placeholder for expiration logic._label: Ignored; debugging label.
Returns:
Ok(())on successful write.Erron failure to serialize or write.
Implementation details:
Converts bins into aValueMap, serializes it to a temporary file withbincode, then persists atomically usingpersist().Usage example:
store.put(&key, &bins, false, "label")?;
db_reads() and db_writes() (Debug-only)
Stub methods intended to track database read and write counts during debug builds. Currently unimplemented (todo!()).
Serialization Helper Enums
SerdeFloatValue
An enum to serialize and deserialize Aerospike's FloatValue (which can be either F32 or F64).
Variants:
F32(u32)- 32-bit float represented as raw bits.F64(u64)- 64-bit float represented as raw bits.
Implements
From<FloatValue>andInto<FloatValue>for bidirectional conversion.
SerdeValue
An enum representing all possible Aerospike Value variants in a serializable form.
Variants:
NilBool(bool)Int(i64)UInt(u64)Float(SerdeFloatValue)String(String)Blob(Vec<u8>)List(Vec<SerdeValue>)HashMap(Vec<(SerdeValue, SerdeValue)>)OrderedMap(Vec<(SerdeValue, SerdeValue)>)GeoJSON(String)HLL(Vec<u8>)
Implements
From<Value>andInto<Value>for conversion betweenSerdeValueand Aerospike'sValue.
Important Implementation Details
Data Storage Format:
Data is serialized using thebincodecrate, which produces compact binary representation of theHashMap<String, SerdeValue>. Each key corresponds to a file named after the Aerospike key's string form.Atomic Writes:
Writes usetempfile::NamedTempFileto write to a temporary file in the target directory, then atomically renamed to the final path to avoid partial writes or corruption.Error Handling:
Usesanyhowfor error context and propagation, ensuring any IO or serialization errors are reported with context.Serialization Strategy:
Custom serialization viaSerdeValueintermediate enum enables handling of complex nested Aerospike types (lists, maps, geoJSON, etc.) safely and consistently.
Interactions with Other Modules
Implements the
KeyValueStoretrait defined incrate::storage, enabling it to be used interchangeably with other storage backends.Uses the
aerospikecrate's types such asKey,Bin,Bins,Value, andFloatValuefor data representation, ensuring compatibility with Aerospike client types.Uses
ValueMapfromcrate::storage, which is constructed from and converted into the serializedHashMap<String, SerdeValue>.
Visual Diagram
classDiagram
class FsStore {
-data_dir: PathBuf
+new()
-persist()
-key_path()
+get()
+put()
+db_reads()
+db_writes()
}
class SerdeFloatValue {
<<enum>>
+F32
+F64
}
class SerdeValue {
<<enum>>
+Nil
+Bool
+Int
+UInt
+Float
+String
+Blob
+List
+HashMap
+OrderedMap
+GeoJSON
+HLL
}
FsStore ..|> KeyValueStore
FsStore o-- NamedTempFile : uses
FsStore o-- PathBuf : uses
FsStore ..> SerdeValue : serializes/deserializes
SerdeValue ..> SerdeFloatValue : contains
SerdeValue <--> Value : conversion
SerdeFloatValue <--> FloatValue : conversion
Summary of Key Relationships
FsStoreserves as a persistent storage layer by saving serializedValueMapdata to disk files.Serialization is mediated by
SerdeValueandSerdeFloatValueenums, converting Aerospike values into a form suitable forbincodeserialization.Implements
KeyValueStoretrait, enabling polymorphic usage in the storage system.Uses atomic file operations to ensure data integrity during writes.
Interacts closely with types from the
aerospikecrate and internalcrate::storagemodule types.