use super::*; use generational_arena::{ Arena, Index as ArenaIndex, }; use std::collections::BTreeMap; use std::collections::HashSet; use std::path::{Path, PathBuf}; use std::fs::File; use std::ffi::OsString; use memmap::Mmap; use bytes::Bytes; use cryptohelpers::{aes, sha256}; mod entry; pub use entry::Entry; mod cache; pub use cache::DataCacheState; mod metadata; pub use metadata::StoreMetadata; mod freeze; pub use freeze::Freeze; #[derive(Debug)] pub struct Store { metadata: StoreMetadata, data: HashSet, // The entry sha256 hash is used as the `key` here, as `Entry` both hasshes to, and `Borrow`s to `Sha256Hash`. data_hashes: Arena, // used to lookup in `data`. tag_mappings: Arena>, tags: BTreeMap, // string (tags) -> index (tag_mappings) -> index (data_hashes) -> hash used for lookup (data) } // Comptime asserts (TODO: Unneeded. Remove.) impl Store { fn _assert_tag_lookup_works(&self, tag: &str) -> &Entry { self.data.get(self.data_hashes.get(*self.tag_mappings.get(*self.tags.get(tag).unwrap()).unwrap().first().unwrap()).unwrap()).unwrap() // y-yes this also works... } fn _assert_lookup_internal_works(&self, data_idx: ArenaIndex) -> &Entry { self.data.get(self.data_hashes.get(data_idx).unwrap()).unwrap() // yes this works.. } } // Creating impl Store { /// Create a new empty store with this metadata. /// /// # Panics /// If the root directory specified in `metadata` does not exist or is not a directory. pub fn new(metadata: StoreMetadata) -> Self { assert!(metadata.root.exists() && metadata.root.is_dir(), "Metadata root {:?} passed to `new` not existant or not a directory", metadata.root); Self { metadata, data: HashSet::new(), data_hashes: Arena::new(), tag_mappings: Arena::new(), tags: BTreeMap::new(), } } /// Create a new empty store with this metadata and initial storage capacity /// /// # Panics /// If the root directory specified in `metadata` does not exist or is not a directory. pub fn with_capacity(metadata: StoreMetadata, cap: usize) -> Self { assert!(metadata.root.exists() && metadata.root.is_dir(), "Metadata root {:?} passed to `with_capacity` not existant or not a directory", metadata.root); Self { metadata, data: HashSet::with_capacity(cap), data_hashes: Arena::with_capacity(cap), tag_mappings: Arena::with_capacity(cap), tags: BTreeMap::new(), } } } // Freezing impl Store { /// Create a snapshot of this store, cloning all data into a frozen and serialisable version of it. /// # Notes /// This method clones the entire store into the new `Freeze`. To avoid this, use `into_freeze` if the store is no longer used after the freeze. #[inline] pub fn freeze(&self) -> Freeze { Freeze::new_ref(self) } /// Consume into a snapshot of this store, moving all data into a frozen and serializable version of it. #[inline] pub fn into_freeze(self) -> Freeze { Freeze::new_moved(self) } /// Create a new store instance by cloning from a frozen snapshot of it. /// # Notes /// This method clones the entire `Freeze` into the new store. To avoid this, use `from_freeze` if the snapshot is no longer used after the unfreeze. #[inline] pub fn unfreeze(freeze: &Freeze) -> Self { freeze.create_new() } /// Consume a store snapshot and move its entries into a new store. #[inline] pub fn from_freeze(freeze: Freeze) -> Self { freeze.into_new() } }