From 7f9623f0f4809ac643d6c6738983be7bfdeca04f Mon Sep 17 00:00:00 2001 From: Max Fierro Date: Tue, 19 Nov 2024 01:07:52 -0800 Subject: [PATCH] Deleted volatile directory --- src/database/mod.rs | 1 - src/database/volatile/error.rs | 3 - src/database/volatile/mod.rs | 226 ------------------ src/database/volatile/resource/manager.rs | 239 ------------------- src/database/volatile/resource/mod.rs | 155 ------------ src/database/volatile/transaction/manager.rs | 52 ---- src/database/volatile/transaction/mod.rs | 193 --------------- 7 files changed, 869 deletions(-) delete mode 100644 src/database/volatile/error.rs delete mode 100644 src/database/volatile/mod.rs delete mode 100644 src/database/volatile/resource/manager.rs delete mode 100644 src/database/volatile/resource/mod.rs delete mode 100644 src/database/volatile/transaction/manager.rs delete mode 100644 src/database/volatile/transaction/mod.rs diff --git a/src/database/mod.rs b/src/database/mod.rs index 7e1da9c..57fb0cb 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -25,7 +25,6 @@ pub mod error; /* IMPLEMENTATION MODULES */ -pub mod volatile; pub mod record { pub mod mur; pub mod dir; diff --git a/src/database/volatile/error.rs b/src/database/volatile/error.rs deleted file mode 100644 index 2ac56cb..0000000 --- a/src/database/volatile/error.rs +++ /dev/null @@ -1,3 +0,0 @@ -//! # Volatile Database Error -//! -//! TODO diff --git a/src/database/volatile/mod.rs b/src/database/volatile/mod.rs deleted file mode 100644 index 25b4b93..0000000 --- a/src/database/volatile/mod.rs +++ /dev/null @@ -1,226 +0,0 @@ -//! # Volatile Database -//! -//! This module provides a trivial database implementation backed by a volatile -//! in-memory data structure arrangement. - -use anyhow::bail; -use anyhow::Result; -use bitvec::slice::BitSlice; - -use std::marker::PhantomData; -use std::sync::Arc; - -use crate::database::model::SequenceKey; -use crate::database::record::dir; -use crate::database::util::KeySequencer; -use crate::database::volatile::resource::Request; -use crate::database::volatile::resource::ResourceManager; -use crate::database::volatile::transaction::Transaction; -use crate::database::volatile::transaction::TransactionManager; -use crate::database::Map; -use crate::database::Schema; - -/* RE-EXPORTS */ - -pub use resource::Resource; -pub use transaction::WorkingSet; - -/* MODULES */ - -mod transaction; -mod resource; - -/* DEFINITIONS */ - -type TransactionID = SequenceKey; -type ResourceID = SequenceKey; - -pub struct Database { - transaction_manager: Arc, - resource_manager: Arc, - directory: Option, - sequencer: Arc, -} - -pub struct TransactionBuilder -where - F: FnOnce(WorkingSet) -> Result, -{ - transaction_manager: Arc, - resource_manager: Arc, - write_requests: Vec, - read_requests: Vec, - function: Option, - _out: PhantomData, -} - -#[derive(Default)] -struct Sequencer { - transaction: KeySequencer, - resource: KeySequencer, -} - -/* IMPLEMENTATION */ - -impl Sequencer { - pub fn next_transaction(&self) -> Result { - self.transaction.next() - } - - pub fn next_resource(&self) -> Result { - self.transaction.next() - } -} - -impl Database { - pub fn new() -> Result { - let directory = None; - let sequencer = Arc::new(Sequencer::default()); - let resource_manager = ResourceManager::new(sequencer.clone()); - let transaction_manager = TransactionManager::new( - resource_manager.clone(), - sequencer.clone(), - ); - - let mut db = Self { - transaction_manager, - resource_manager, - directory, - sequencer, - }; - - let directory = db - .start_transaction(Request::empty())? - .create_resource(dir::schema()?)?; - - db.directory = Some(directory); - Ok(db) - } - - pub fn build_transaction(&self) -> TransactionBuilder - where - F: FnOnce(WorkingSet) -> Result, - { - TransactionBuilder { - transaction_manager: self.transaction_manager.clone(), - resource_manager: self.resource_manager.clone(), - write_requests: Vec::new(), - read_requests: Vec::new(), - function: None, - _out: PhantomData, - } - } - - pub fn start_transaction( - &self, - request: Request, - ) -> Result> { - let txn = self - .resource_manager - .initialize_transaction( - request, - self.transaction_manager.clone(), - )?; - - self.transaction_manager - .add_transaction(txn.clone())?; - - Ok(txn) - } - - pub fn create_resource(&self, schema: Schema, name: &str) -> Result<()> { - let directory = self - .directory - .expect("Database directory table found uninitialized."); - - let txn = self.start_transaction(Request { - write: vec![self.directory.unwrap()], - read: vec![], - })?; - - let mut directory = txn.write(directory)?; - let dir_key = &BitSlice::from_slice(name.as_bytes()); - if let Some(_) = directory.get(dir_key) { - bail!("Resource '{name}' already exists.") - } - - let id = txn.create_resource(schema.clone())?; - let mut record = dir::RecordBuffer::try_from(schema)?; - record.set_offset(id); - - directory.insert(dir_key, &record); - Ok(id) - } - - pub fn drop_resource(&self, name: &str) -> Result<()> { - let directory = self - .directory - .expect("Database directory table found uninitialized."); - - let txn = self.start_transaction(Request { - write: vec![self.directory.unwrap()], - read: vec![], - })?; - - let dir_key = &BitSlice::from_slice(name.as_bytes()); - let mut directory = txn.write(directory)?; - if let Some(value) = directory.get(dir_key) { - let record = dir::RecordBuffer::new(value)?; - let id = record.get_offset(); - txn.drop_resource(id)?; - directory.remove(dir_key); - } - - Ok(()) - } -} - -impl TransactionBuilder -where - F: FnOnce(WorkingSet) -> Result, -{ - pub fn writing(mut self, id: ResourceID) -> Self { - self.read_requests.push(id); - self - } - - pub fn reading(mut self, id: ResourceID) -> Self { - self.write_requests.push(id); - self - } - - pub fn action(mut self, function: F) -> Self { - self.function = Some(function); - self - } - - pub fn execute(self) -> Result { - if self.read_requests.is_empty() && self.write_requests.is_empty() { - bail!("No resource acquisition requests provided.") - } - - let function = if let Some(func) = self.function { - func - } else { - bail!("No actionable provided to transaction builder.") - }; - - let request = Request { - write: self.write_requests, - read: self.read_requests, - }; - - let txn = self - .resource_manager - .initialize_transaction( - request, - self.transaction_manager.clone(), - )?; - - self.transaction_manager - .add_transaction(txn.clone())?; - - let working_set = txn.resources()?; - function(working_set) - } -} diff --git a/src/database/volatile/resource/manager.rs b/src/database/volatile/resource/manager.rs deleted file mode 100644 index b90ac43..0000000 --- a/src/database/volatile/resource/manager.rs +++ /dev/null @@ -1,239 +0,0 @@ -//! # Volatile Database Resource Manager -//! -//! TODO - -use anyhow::anyhow; -use anyhow::bail; -use anyhow::Result; - -use std::collections::HashMap; -use std::collections::HashSet; -use std::sync::Condvar; -use std::sync::Mutex; -use std::sync::MutexGuard; -use std::sync::{Arc, RwLock}; - -use crate::database::volatile::resource::Resource; -use crate::database::volatile::transaction::ResourceHandles; -use crate::database::volatile::transaction::Transaction; -use crate::database::volatile::transaction::TransactionManager; -use crate::database::volatile::ResourceID; -use crate::database::volatile::Sequencer; -use crate::database::volatile::TransactionID; - -/* DEFINITIONS */ - -pub struct ResourceManager { - pub sequencer: Arc, - access: Mutex, - signal: Condvar, -} - -#[derive(Default)] -pub struct Request { - pub write: Vec, - pub read: Vec, -} - -#[derive(Default)] -pub struct AccessControl { - pool: HashMap>>, - owners: HashMap, - reading: HashMap, - writing: HashSet, - dropped: HashSet, -} - -/* IMPLEMENTATION */ - -impl Request { - pub fn empty() -> Self { - Self::default() - } -} - -impl AccessControl { - fn conflict(&self, request: &Request) -> bool { - request - .read - .iter() - .chain(&request.write) - .any(|id| self.writing.contains(id)) - } -} - -impl ResourceManager { - pub fn new(sequencer: Arc) -> Arc { - let access = Mutex::new(AccessControl::default()); - let signal = Condvar::new(); - let manager = Self { - sequencer, - access, - signal, - }; - - Arc::new(manager) - } - - pub fn add_resource(&self, resource: Resource) -> Result<()> { - let mut resources = self - .access - .lock() - .map_err(|_| anyhow!("Resource access lock poisoned."))?; - - let id = resource.id(); - let lock = RwLock::new(resource); - resources - .pool - .insert(id, Arc::new(lock)); - - Ok(()) - } - - pub fn drop_resource( - &self, - rid: ResourceID, - tid: TransactionID, - ) -> Result<()> { - let mut resources = self - .access - .lock() - .map_err(|_| anyhow!("Resource access lock poisoned."))?; - - if let Some(&owner) = resources.owners.get(&rid) { - if owner == tid && !resources.dropped.contains(&rid) { - resources.dropped.insert(rid); - resources.pool.remove(&rid); - } - } - - Err(anyhow!( - "Attempted to drop resource without ownership." - )) - } - - pub fn initialize_transaction( - &self, - request: Request, - manager: Arc, - ) -> Result> { - let mut resources = self.lock()?; - loop { - if request - .write - .iter() - .chain(&request.read) - .any(|id| !resources.pool.contains_key(id)) - { - bail!("Attempted to acquire non-existent resource."); - } - - if !resources.conflict(&request) { - let id = self.sequencer.next_transaction()?; - self.acquire_resources(&request, id, &mut resources); - let handles = self.generate_handles(&request, &mut resources); - let transaction = - Transaction::new(manager, handles, request, id); - - return Ok(transaction); - } - - resources = self - .signal - .wait(resources) - .map_err(|_| anyhow!("Resource access lock poisoned."))?; - } - } - - /* UTILITIES */ - - pub fn lock(&self) -> Result> { - self.access - .lock() - .map_err(|_| anyhow!("Resource access lock poisoned.")) - } - - pub fn signal_waiters(&self) { - self.signal.notify_all() - } - - pub fn acquire_resources( - &self, - request: &Request, - transaction: TransactionID, - resources: &mut MutexGuard, - ) { - request - .write - .iter() - .for_each(|id| { - resources.writing.insert(*id); - resources - .owners - .insert(*id, transaction); - }); - - request.read.iter().for_each(|id| { - let count = resources - .reading - .entry(*id) - .or_insert(0); - - *count += 1; - resources - .owners - .insert(*id, transaction); - }); - } - - pub fn release_resources( - &self, - request: &Request, - resources: &mut MutexGuard, - ) { - request - .write - .iter() - .for_each(|id| { - resources.owners.remove(id); - resources.writing.remove(id); - }); - - request.read.iter().for_each(|id| { - resources.owners.remove(id); - let count = resources - .reading - .entry(*id) - .or_insert(1); - - *count -= 1; - }); - } - - fn generate_handles( - &self, - request: &Request, - resources: &mut MutexGuard, - ) -> ResourceHandles { - let mut handles = ResourceHandles::default(); - for &id in request.write.iter() { - let lock = resources - .pool - .get(&id) - .expect("Attempted to fetch non-existent resource lock."); - - handles.add_write(id, lock.clone()); - } - - for &id in request.read.iter() { - let lock = resources - .pool - .get(&id) - .expect("Attempted to fetch non-existent resource lock."); - - handles.add_read(id, lock.clone()); - } - - handles - } -} diff --git a/src/database/volatile/resource/mod.rs b/src/database/volatile/resource/mod.rs deleted file mode 100644 index 2dae416..0000000 --- a/src/database/volatile/resource/mod.rs +++ /dev/null @@ -1,155 +0,0 @@ -//! # Volatile Database Resource -//! -//! TODO - -use anyhow::Result; -use bitvec::order::Msb0; -use bitvec::slice::BitSlice; -use bitvec::vec::BitVec; - -use std::collections::HashMap; -use std::sync::{Arc, Weak}; - -use crate::database::model::Key; -use crate::database::model::SequenceKey; -use crate::database::model::Value; -use crate::database::volatile::ResourceID; -use crate::database::Map; -use crate::database::Record; -use crate::database::Relation; -use crate::database::Schema; - -/* RE-EXPORTS */ - -pub use manager::Request; -pub use manager::ResourceManager; - -/* MODULES */ - -mod manager; - -/* DEFINITIONS */ - -pub struct Resource { - manager: Weak, - schema: Schema, - data: Content, - id: ResourceID, -} - -struct Content { - indices: HashMap, usize>, - storage: BitVec, - current: usize, - size: u64, -} - -/* IMPLEMENTATION */ - -impl Resource { - pub(in crate::database::volatile) fn new( - manager: Arc, - schema: Schema, - id: ResourceID, - ) -> Self { - Self { - manager: Arc::downgrade(&manager), - schema, - data: Content { - indices: HashMap::new(), - storage: BitVec::new(), - current: 0, - size: 0, - }, - id, - } - } - - pub(in crate::database::volatile) fn id(&self) -> ResourceID { - self.id - } - - /* UTILITIES */ - - fn data_slice( - &self, - from: usize, - to: usize, - ) -> Option<&BitSlice> { - if to > self.data.storage.len() { - None - } else { - Some(&self.data.storage[from..to]) - } - } - - fn index_removed(&self, index: usize) -> bool { - *self - .data - .storage - .get(index + self.schema.size()) - .expect("Out-of-bounds removal check on storage array.") - } - - fn mark_removed(&mut self, index: usize) { - self.data - .storage - .set(index + self.schema.size(), true); - } -} - -impl Map for Resource { - fn insert(&mut self, key: &Key, record: &R) -> Result<()> { - let key_bits = BitVec::from(key); - self.data - .indices - .insert(key_bits, self.data.current); - - self.data - .storage - .extend(record.raw()); - - self.data.storage.push(false); - self.data.current += self.schema.size() + 1; - self.data.size += 1; - Ok(()) - } - - fn get(&self, key: &Key) -> Option<&Value> { - let key_bits = BitVec::from(key); - if let Some(&location) = self.data.indices.get(&key_bits) { - if self.index_removed(location) { - return None; - } - self.data_slice(location, location + self.schema.size()) - } else { - None - } - } - - fn remove(&mut self, key: &Key) { - let key_bits = BitVec::from(key); - if let Some(&location) = self.data.indices.get(&key_bits) { - self.mark_removed(location); - self.data.size -= 1; - } - } -} - -impl Relation for Resource { - fn schema(&self) -> &Schema { - &self.schema - } - - fn count(&self) -> u64 { - self.data.size - } - - fn bytes(&self) -> u64 { - (self.data.storage.len() as u64) / 8 - } - - fn id(&self) -> SequenceKey { - self.id() - } -} diff --git a/src/database/volatile/transaction/manager.rs b/src/database/volatile/transaction/manager.rs deleted file mode 100644 index a8cd97a..0000000 --- a/src/database/volatile/transaction/manager.rs +++ /dev/null @@ -1,52 +0,0 @@ -//! # Volatile Database Transaction Manager -//! -//! TODO - -use anyhow::anyhow; -use anyhow::Result; - -use std::collections::HashMap; -use std::sync::{Arc, RwLock}; - -use crate::database::volatile::transaction::Transaction; -use crate::database::volatile::ResourceManager; -use crate::database::volatile::Sequencer; -use crate::database::volatile::TransactionID; - -/* DEFINITIONS */ - -pub struct TransactionManager { - transactions: RwLock>>, - pub resource_manager: Arc, - pub sequencer: Arc, -} - -/* IMPLEMENTATION */ - -impl TransactionManager { - pub fn new( - resource_manager: Arc, - sequencer: Arc, - ) -> Arc { - let transactions = RwLock::new(HashMap::new()); - let manager = Self { - resource_manager, - transactions, - sequencer, - }; - - Arc::new(manager) - } - - pub fn add_transaction(&self, transaction: Arc) -> Result<()> { - let mut txns = self - .transactions - .write() - .map_err(|_| anyhow!("Transaction manager lock poisoned."))?; - - { - txns.insert(transaction.id(), transaction); - Ok(()) - } - } -} diff --git a/src/database/volatile/transaction/mod.rs b/src/database/volatile/transaction/mod.rs deleted file mode 100644 index 350ea8e..0000000 --- a/src/database/volatile/transaction/mod.rs +++ /dev/null @@ -1,193 +0,0 @@ -//! # Volatile Database Transaction -//! -//! TODO - -use anyhow::anyhow; -use anyhow::Result; - -use std::collections::HashMap; -use std::sync::RwLockReadGuard; -use std::sync::{Arc, RwLock, RwLockWriteGuard, Weak}; - -use crate::database::volatile::resource::Resource; -use crate::database::volatile::Request; -use crate::database::volatile::{ResourceID, TransactionID}; -use crate::database::Schema; - -/* RE-EXPORTS */ - -pub use manager::TransactionManager; - -/* MODULES */ - -mod manager; - -/* DEFINITIONS */ - -pub struct Transaction { - manager: Weak, - handles: ResourceHandles, - request: Request, - id: TransactionID, -} - -#[derive(Default)] -pub struct ResourceHandles { - write: HashMap>>, - read: HashMap>>, -} - -pub struct WorkingSet<'a> { - write: HashMap>, - read: HashMap>, -} - -/* IMPLEMENTATION */ - -impl WorkingSet<'_> { - pub fn get_reading(&mut self, name: &str) -> RwLockReadGuard { - self.read.remove(name).unwrap() - } - - pub fn get_writing(&mut self, name: &str) -> RwLockWriteGuard { - self.write.remove(name).unwrap() - } -} - -impl ResourceHandles { - pub fn add_read(&mut self, name: String, lock: Arc>) { - self.read.insert(name, lock); - } - - pub fn add_write(&mut self, name: String, lock: Arc>) { - self.write.insert(name, lock); - } - - fn read(&self, name: &str) -> Result> { - if let Some(ref resource) = self.read.get(name) { - Ok(resource - .read() - .map_err(|_| anyhow!("Read on poisoned resource lock."))?) - } else { - Err(anyhow!( - "Attempted read on unacquired resource {}.", - name - )) - } - } - - fn write(&self, name: &str) -> Result> { - if let Some(ref resource) = self.write.get(name) { - Ok(resource - .write() - .map_err(|_| anyhow!("Write on poisoned resource lock."))?) - } else { - Err(anyhow!( - "Attempted write on unacquired resource {}.", - name - )) - } - } - - pub fn lock_all(&self) -> Result { - let read = self - .read - .iter() - .map(|(name, l)| { - l.read() - .map(|l| (name.clone(), l)) - .map_err(|_| anyhow!("Read on poisoned resource lock.")) - }) - .collect::>>()?; - - let write = self - .write - .iter() - .map(|(name, l)| { - l.write() - .map(|l| (name.clone(), l)) - .map_err(|_| anyhow!("Write on poisoned resource lock.")) - }) - .collect::>>()?; - - Ok(WorkingSet { write, read }) - } -} - -impl Transaction { - pub fn read(&self, name: &str) -> Result> { - self.handles.read(name) - } - - pub fn write(&self, name: &str) -> Result> { - self.handles.write(name) - } - - pub fn resources(&self) -> Result { - self.handles.lock_all() - } - - pub fn id(&self) -> TransactionID { - self.id - } - - /* PROTECTED */ - - pub(in crate::database::volatile) fn new( - manager: Arc, - handles: ResourceHandles, - request: Request, - id: TransactionID, - ) -> Arc { - let manager = Arc::downgrade(&manager); - let transaction = Self { - manager, - handles, - request, - id, - }; - - Arc::new(transaction) - } - - pub(in crate::database::volatile) fn create_resource( - &self, - schema: Schema, - ) -> Result { - if let Some(manager) = self.manager.upgrade() { - let id = manager.sequencer.next_resource()?; - let resource_manager = manager.resource_manager.clone(); - let resource = Resource::new(resource_manager.clone(), schema, id); - resource_manager.add_resource(resource)?; - Ok(id) - } else { - Err(anyhow!("Transaction manager was dropped.")) - } - } - - pub(in crate::database::volatile) fn drop_resource( - &self, - id: ResourceID, - ) -> Result<()> { - if let Some(manager) = self.manager.upgrade() { - manager - .resource_manager - .drop_resource(id, self.id())?; - - Ok(()) - } else { - Err(anyhow!("Transaction manager was dropped.")) - } - } -} - -impl Drop for Transaction { - fn drop(&mut self) { - if let Some(manager) = self.manager.upgrade() { - let resource_manager = &manager.resource_manager; - let mut resources = resource_manager.lock().unwrap(); - resource_manager.release_resources(&self.request, &mut resources); - resource_manager.signal_waiters(); - } - } -}