diff --git a/Cargo.lock b/Cargo.lock index 5cdfbfe..700e5ed 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -201,9 +201,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.81" +version = "0.1.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" +checksum = "a27b8a3a6e1a44fa4c8baf1f653e4172e81486d4941f2237e20dc2d0cf4ddff1" dependencies = [ "proc-macro2", "quote", diff --git a/aper/src/aper.rs b/aper/src/aper.rs index cde114a..0563f34 100644 --- a/aper/src/aper.rs +++ b/aper/src/aper.rs @@ -1,7 +1,7 @@ use crate::{ connection::{ClientConnection, MessageToServer}, - store::Store, - Mutation, StoreHandle, + store::{Store, StoreHandle}, + Mutation, }; use serde::{Deserialize, Serialize}; use std::{ diff --git a/aper/src/data_structures/map.rs b/aper/src/data_structures/map.rs index 52c99c6..d27826d 100644 --- a/aper/src/data_structures/map.rs +++ b/aper/src/data_structures/map.rs @@ -33,5 +33,5 @@ impl Map { pub fn delete(&mut self, key: &K) { let key = bincode::serialize(key).unwrap(); self.map.delete_child(&key); - } + } } diff --git a/aper/src/store.rs b/aper/src/store/core.rs similarity index 61% rename from aper/src/store.rs rename to aper/src/store/core.rs index c460d18..20722c9 100644 --- a/aper/src/store.rs +++ b/aper/src/store/core.rs @@ -1,3 +1,7 @@ +use super::{ + handle::StoreHandle, + prefix_map::{PrefixMap, PrefixMapValue}, +}; use crate::{ listener::{self, ListenerMap}, Bytes, Mutation, @@ -10,62 +14,17 @@ use std::{ sync::{Arc, Mutex}, }; -#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] -pub enum PrefixMapValue { - Value(Bytes), - Deleted, -} - -#[derive(Clone, Serialize, Deserialize, Debug)] -pub enum PrefixMap { - Children(BTreeMap), - DeletedPrefixMap, -} - -impl PrefixMap { - fn get(&self, key: &Bytes) -> Option { - match self { - PrefixMap::Children(children) => children.get(key).cloned(), - PrefixMap::DeletedPrefixMap => Some(PrefixMapValue::Deleted), - } - } - - fn insert(&mut self, key: Bytes, value: PrefixMapValue) { - match self { - PrefixMap::Children(children) => { - children.insert(key, value); - } - PrefixMap::DeletedPrefixMap => { - if value == PrefixMapValue::Deleted { - // the prefix map is deleted, so we don't need to delete the value. - return; - } - - let mut new_children = BTreeMap::new(); - new_children.insert(key, value); - *self = PrefixMap::Children(new_children); - } - } - } -} - -impl Default for PrefixMap { - fn default() -> Self { - Self::Children(BTreeMap::new()) - } -} - #[derive(Default)] pub struct StoreLayer { /// Map of prefix to direct children at that prefix. - layer: BTreeMap, PrefixMap>, + pub(crate) layer: BTreeMap, PrefixMap>, /// A set of prefixes that have been modified in this layer. - dirty: HashSet>, + pub(crate) dirty: HashSet>, } pub struct StoreInner { - layers: Mutex>, - listeners: Mutex, + pub(crate) layers: Mutex>, + pub(crate) listeners: Mutex, } impl Default for StoreInner { @@ -79,7 +38,7 @@ impl Default for StoreInner { #[derive(Clone, Default)] pub struct Store { - inner: Arc, + pub(crate) inner: Arc, } impl Store { @@ -250,108 +209,7 @@ impl Store { } pub fn handle(&self) -> StoreHandle { - StoreHandle { - map: self.clone(), - prefix: vec![], - } - } -} - -#[derive(Clone)] -pub struct StoreHandle { - map: Store, - prefix: Vec, -} - -impl StoreHandle { - pub fn listen bool + 'static + Send + Sync>(&self, listener: F) { - let mut listeners = self.map.inner.listeners.lock().unwrap(); - listeners.listen(self.prefix.clone(), listener); - } - - pub fn get(&self, key: &Bytes) -> Option { - self.map.get(&self.prefix, key) - } - - pub fn set(&mut self, key: Bytes, value: Bytes) { - // set the value in the top layer. - - let mut layers = self.map.inner.layers.lock().unwrap(); - let mut top_layer = layers.last_mut().unwrap(); - - let mut map = top_layer.layer.entry(self.prefix.clone()).or_default(); - - top_layer.dirty.insert(self.prefix.clone()); - - map.insert(key, PrefixMapValue::Value(value)); - } - - pub fn delete(&mut self, key: Bytes) { - // delete the value in the top layer. - - let mut layers = self.map.inner.layers.lock().unwrap(); - let mut top_layer = layers.last_mut().unwrap(); - - let mut map = top_layer.layer.entry(self.prefix.clone()).or_default(); - - top_layer.dirty.insert(self.prefix.clone()); - - map.insert(key, PrefixMapValue::Deleted); - } - - pub fn child(&mut self, path_part: &[u8]) -> Self { - let mut prefix = self.prefix.clone(); - prefix.push(path_part.to_vec()); - self.map.ensure(&prefix); - Self { - map: self.map.clone(), - prefix, - } - } - - pub fn delete_child(&mut self, path_part: &[u8]) { - let mut prefix = self.prefix.clone(); - prefix.push(path_part.to_vec()); - - let mut layers = self.map.inner.layers.lock().unwrap(); - let mut top_layer = layers.last_mut().unwrap(); - - // When we delete a prefix, we delete not only that prefix but all of the prefixes under it. - // TODO: This is a bit expensive, in order to make a trade-off that reads are faster. Is the balance optimal? - - let mut prefixes_to_delete = HashSet::new(); - - for layer in layers.iter() { - for (pfx, val) in layer.layer.iter() { - if pfx.starts_with(&prefix) { - prefixes_to_delete.insert(pfx.clone()); - } - } - } - - let mut top_layer = layers.last_mut().unwrap(); - - for pfx in prefixes_to_delete.iter() { - top_layer - .layer - .insert(pfx.clone(), PrefixMap::DeletedPrefixMap); - top_layer.dirty.insert(pfx.clone()); - } - } -} - -impl Debug for Store { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - let layers = self.inner.layers.lock().unwrap(); - - for (i, layer) in layers.iter().enumerate() { - writeln!(f, "Layer {}", i)?; - for (prefix, map) in layer.layer.iter() { - writeln!(f, " {:?} -> {:?}", prefix, map)?; - } - } - - Ok(()) + StoreHandle::new(self.clone()) } } diff --git a/aper/src/store/handle.rs b/aper/src/store/handle.rs new file mode 100644 index 0000000..ae851c7 --- /dev/null +++ b/aper/src/store/handle.rs @@ -0,0 +1,120 @@ +use super::{ + core::Store, + prefix_map::{PrefixMap, PrefixMapValue}, +}; +use crate::{ + listener::{self, ListenerMap}, + Bytes, Mutation, +}; +use serde::{Deserialize, Serialize}; +use std::{ + cell::RefCell, + collections::{BTreeMap, HashSet}, + fmt::{Debug, Formatter}, + sync::{Arc, Mutex}, +}; + +#[derive(Clone)] +pub struct StoreHandle { + map: Store, + prefix: Vec, +} + +impl StoreHandle { + pub fn new(map: Store) -> Self { + Self { + map, + prefix: vec![], + } + } + + pub fn listen bool + 'static + Send + Sync>(&self, listener: F) { + let mut listeners = self.map.inner.listeners.lock().unwrap(); + listeners.listen(self.prefix.clone(), listener); + } + + pub fn get(&self, key: &Bytes) -> Option { + self.map.get(&self.prefix, key) + } + + pub fn set(&mut self, key: Bytes, value: Bytes) { + // set the value in the top layer. + + let mut layers = self.map.inner.layers.lock().unwrap(); + let mut top_layer = layers.last_mut().unwrap(); + + let mut map = top_layer.layer.entry(self.prefix.clone()).or_default(); + + top_layer.dirty.insert(self.prefix.clone()); + + map.insert(key, PrefixMapValue::Value(value)); + } + + pub fn delete(&mut self, key: Bytes) { + // delete the value in the top layer. + + let mut layers = self.map.inner.layers.lock().unwrap(); + let mut top_layer = layers.last_mut().unwrap(); + + let mut map = top_layer.layer.entry(self.prefix.clone()).or_default(); + + top_layer.dirty.insert(self.prefix.clone()); + + map.insert(key, PrefixMapValue::Deleted); + } + + pub fn child(&mut self, path_part: &[u8]) -> Self { + let mut prefix = self.prefix.clone(); + prefix.push(path_part.to_vec()); + self.map.ensure(&prefix); + Self { + map: self.map.clone(), + prefix, + } + } + + pub fn delete_child(&mut self, path_part: &[u8]) { + let mut prefix = self.prefix.clone(); + prefix.push(path_part.to_vec()); + + let mut layers = self.map.inner.layers.lock().unwrap(); + let mut top_layer = layers.last_mut().unwrap(); + + // When we delete a prefix, we delete not only that prefix but all of the prefixes under it. + // TODO: This is a bit expensive, in order to make a trade-off that reads are faster. Is the balance optimal? + + let mut prefixes_to_delete = HashSet::new(); + + for layer in layers.iter() { + for (pfx, val) in layer.layer.iter() { + if pfx.starts_with(&prefix) { + prefixes_to_delete.insert(pfx.clone()); + } + } + } + + let mut top_layer = layers.last_mut().unwrap(); + + for pfx in prefixes_to_delete.iter() { + top_layer + .layer + .insert(pfx.clone(), PrefixMap::DeletedPrefixMap); + top_layer.dirty.insert(pfx.clone()); + } + } +} + +impl Debug for Store { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + let layers = self.inner.layers.lock().unwrap(); + + for (i, layer) in layers.iter().enumerate() { + writeln!(f, "Layer {}", i)?; + for (prefix, map) in layer.layer.iter() { + writeln!(f, " {:?} -> {:?}", prefix, map)?; + } + } + + Ok(()) + } +} diff --git a/aper/src/store/mod.rs b/aper/src/store/mod.rs new file mode 100644 index 0000000..e8d643b --- /dev/null +++ b/aper/src/store/mod.rs @@ -0,0 +1,7 @@ +mod core; +mod handle; +mod prefix_map; + +pub use core::Store; +pub use handle::StoreHandle; +pub use prefix_map::{PrefixMap, PrefixMapValue}; diff --git a/aper/src/store/prefix_map.rs b/aper/src/store/prefix_map.rs new file mode 100644 index 0000000..62d847f --- /dev/null +++ b/aper/src/store/prefix_map.rs @@ -0,0 +1,56 @@ +use crate::{ + listener::{self, ListenerMap}, + Bytes, Mutation, +}; +use serde::{Deserialize, Serialize}; +use std::{ + cell::RefCell, + collections::{BTreeMap, HashSet}, + fmt::{Debug, Formatter}, + sync::{Arc, Mutex}, +}; + +#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] +pub enum PrefixMapValue { + Value(Bytes), + Deleted, +} + +#[derive(Clone, Serialize, Deserialize, Debug)] +pub enum PrefixMap { + Children(BTreeMap), + DeletedPrefixMap, +} + +impl PrefixMap { + pub fn get(&self, key: &Bytes) -> Option { + match self { + PrefixMap::Children(children) => children.get(key).cloned(), + PrefixMap::DeletedPrefixMap => Some(PrefixMapValue::Deleted), + } + } + + pub fn insert(&mut self, key: Bytes, value: PrefixMapValue) { + match self { + PrefixMap::Children(children) => { + children.insert(key, value); + } + PrefixMap::DeletedPrefixMap => { + if value == PrefixMapValue::Deleted { + // the prefix map is deleted, so we don't need to delete the value. + return; + } + + let mut new_children = BTreeMap::new(); + new_children.insert(key, value); + *self = PrefixMap::Children(new_children); + } + } + } +} + +impl Default for PrefixMap { + fn default() -> Self { + Self::Children(BTreeMap::new()) + } +}