blob: c9a727e4ff7264fe3014049b1ff4d4e2b467c6a6 [file] [log] [blame]
use {
crate::object_store::{
allocator::{Allocator, SimpleAllocator},
constants::ROOT_PARENT_STORE_OBJECT_ID,
log::Log,
Device, ObjectStore, StoreOptions,
},
anyhow::Error,
std::{
collections::HashMap,
sync::{Arc, RwLock},
},
};
#[derive(Default)]
pub struct SyncOptions {
pub new_super_block: bool,
}
pub struct StoreManager {
stores: RwLock<Stores>,
}
struct Stores {
stores: HashMap<u64, Arc<ObjectStore>>,
root_store_object_id: u64,
}
impl StoreManager {
pub fn new() -> StoreManager {
StoreManager {
stores: RwLock::new(Stores { stores: HashMap::new(), root_store_object_id: 0 }),
}
}
pub fn root_parent_store(&self) -> Arc<ObjectStore> {
self.store(ROOT_PARENT_STORE_OBJECT_ID).unwrap()
}
pub fn new_store(&self, store: Arc<ObjectStore>) {
self.stores.write().unwrap().stores.insert(store.store_object_id(), store);
}
pub fn store(&self, store_object_id: u64) -> Option<Arc<ObjectStore>> {
self.stores.read().unwrap().stores.get(&store_object_id).cloned()
}
pub fn set_root_store(&self, store: Arc<ObjectStore>) {
let mut stores = self.stores.write().unwrap();
stores.root_store_object_id = store.store_object_id();
stores.stores.insert(store.store_object_id(), store);
}
pub fn root_store(&self) -> Arc<ObjectStore> {
let stores = self.stores.read().unwrap();
stores.stores.get(&stores.root_store_object_id).unwrap().clone()
}
}
pub struct Filesystem {
device: Arc<dyn Device>,
log: Arc<Log>,
stores: Arc<StoreManager>,
}
impl Filesystem {
pub fn new_empty(device: Arc<dyn Device>) -> Result<Filesystem, Error> {
let log = Arc::new(Log::new());
let allocator = Arc::new(SimpleAllocator::new(&log));
let stores = Arc::new(StoreManager::new());
stores.new_store(ObjectStore::new_empty(
None,
ROOT_PARENT_STORE_OBJECT_ID,
device.clone(),
&(allocator.clone() as Arc<dyn Allocator>),
&log,
StoreOptions::default(),
));
log.init_empty(&stores, &(allocator as Arc<dyn Allocator>))?;
Ok(Filesystem { device, log, stores })
}
pub fn open(device: Arc<dyn Device>) -> Result<Filesystem, Error> {
let log = Arc::new(Log::new());
let allocator = Arc::new(SimpleAllocator::new(&log));
let stores = Arc::new(StoreManager::new());
log.replay(device.clone(), stores.clone(), allocator.clone())?;
Ok(Filesystem { device, log, stores })
}
pub fn root_parent_store(&self) -> Arc<ObjectStore> {
self.stores.root_parent_store()
}
pub fn root_store(&self) -> Arc<ObjectStore> {
self.stores.root_store()
}
pub fn sync(&mut self, options: SyncOptions) -> Result<(), Error> {
self.log.sync(options)
}
pub fn device(&self) -> &Arc<dyn Device> {
return &self.device;
}
}
// TODO: Consider sync on drop