Split out storage_val

This commit is contained in:
Andrew Morris
2023-10-27 11:24:23 +11:00
parent 25e64ae09b
commit 5fba28c872
6 changed files with 156 additions and 150 deletions

View File

@@ -6,6 +6,7 @@ mod sled_backend;
mod storage_backend;
mod storage_ops;
mod storage_ptr;
mod storage_val;
mod tests;
pub use self::storage::Storage;

View File

@@ -1,14 +1,10 @@
use std::rc::Rc;
use serde::{Deserialize, Serialize};
use crate::serde_rc::{deserialize_rc, serialize_rc};
use crate::storage_ops::StorageOps;
use crate::storage_ptr::{tmp_at_ptr, tmp_count_ptr, StorageEntryPtr, StorageHeadPtr};
use crate::storage_val::StorageVal;
use crate::StorageBackend;
pub struct Storage<SB: StorageBackend> {
sb: SB,
pub(crate) sb: SB,
}
impl<SB: StorageBackend> Storage<SB> {
@@ -72,142 +68,3 @@ impl<SB: StorageBackend> Storage<SB> {
.transaction(|sb| Ok(sb.read(key)?.map(|entry| entry.ref_count)))
}
}
#[derive(Serialize, Deserialize)]
pub struct StorageEntry {
pub(crate) ref_count: u64,
#[serde(serialize_with = "serialize_rc", deserialize_with = "deserialize_rc")]
pub(crate) refs: Rc<Vec<StorageEntryPtr>>,
data: Vec<u8>,
}
#[derive(Default, Serialize, Deserialize, PartialEq, Eq, Debug, Clone)]
pub enum StoragePoint {
#[default]
Void,
Number(u64),
Array(
#[serde(serialize_with = "serialize_rc", deserialize_with = "deserialize_rc")]
Rc<Vec<StoragePoint>>,
),
Ref(u64),
}
impl StoragePoint {
pub fn maybe_replace_store<E, SO: StorageOps<E>>(
&self,
tx: &mut SO,
refs: &Rc<Vec<StorageEntryPtr>>,
) -> Result<Option<StorageEntryPtr>, E> {
Ok(match &self {
StoragePoint::Void => None,
StoragePoint::Number(_) => None,
StoragePoint::Array(arr) => 'b: {
let mut replacements: Vec<(usize, StorageEntryPtr)> = Vec::new();
for i in 0..arr.len() {
if let Some(key) = arr[i].maybe_replace_store(tx, refs)? {
replacements.push((i, key));
}
}
if replacements.is_empty() {
break 'b Some(tx.store(&StorageVal {
point: StoragePoint::Array(arr.clone()),
refs: refs.clone(),
})?);
}
let mut new_arr = Vec::<StoragePoint>::new();
let mut new_refs = (**refs).clone();
let mut replacements_iter = replacements.iter();
let mut next_replacement = replacements_iter.next();
for (i, point) in arr.iter().enumerate() {
if let Some((j, entry_ptr)) = next_replacement {
if *j == i {
new_arr.push(StoragePoint::Ref(new_refs.len() as u64));
new_refs.push(*entry_ptr);
next_replacement = replacements_iter.next();
continue;
}
}
new_arr.push(point.clone());
}
Some(tx.store(&StorageVal {
point: StoragePoint::Array(Rc::new(new_arr)),
refs: Rc::new(new_refs),
})?)
}
StoragePoint::Ref(_) => None,
})
}
#[cfg(test)]
fn numbers<E, SO: StorageOps<E>>(
&self,
tx: &mut SO,
refs: &Rc<Vec<StorageEntryPtr>>,
) -> Result<Vec<u64>, E> {
match &self {
StoragePoint::Void => Ok(Vec::new()),
StoragePoint::Number(n) => Ok(vec![*n]),
StoragePoint::Array(arr) => {
let mut numbers = Vec::new();
for point in arr.iter() {
numbers.extend(point.numbers(tx, refs)?);
}
Ok(numbers)
}
StoragePoint::Ref(i) => {
let key = refs[*i as usize];
let val = tx.read(key)?.unwrap().to_val();
val.point.numbers(tx, &val.refs)
}
}
}
}
#[derive(Serialize, Deserialize, Debug)]
pub struct StorageVal {
pub point: StoragePoint,
#[serde(serialize_with = "serialize_rc", deserialize_with = "deserialize_rc")]
pub refs: Rc<Vec<StorageEntryPtr>>,
}
impl StorageEntry {
pub fn to_val(&self) -> StorageVal {
StorageVal {
point: bincode::deserialize(&self.data).unwrap(),
refs: self.refs.clone(),
}
}
}
impl StorageVal {
pub fn to_entry(&self) -> StorageEntry {
StorageEntry {
ref_count: 1,
refs: self.refs.clone(),
data: bincode::serialize(&self.point).unwrap(),
}
}
#[cfg(test)]
pub(crate) fn numbers<SB: StorageBackend>(
&self,
storage: &mut Storage<SB>,
) -> Result<Vec<u64>, SB::Error<()>> {
storage
.sb
.transaction(|sb| self.point.numbers(sb, &self.refs))
}
}

View File

@@ -2,9 +2,9 @@ use rand::thread_rng;
use serde::{Deserialize, Serialize};
use crate::{
storage::StorageVal,
storage_backend::StorageBackendHandle,
storage_ptr::{StorageEntryPtr, StorageHeadPtr, StoragePtr},
storage_val::StorageVal,
};
pub trait StorageOps<E> {

View File

@@ -1,6 +1,6 @@
use rand::{rngs::ThreadRng, Rng};
use crate::storage::StorageEntry;
use crate::storage_val::StorageEntry;
#[derive(serde::Serialize, serde::Deserialize, Hash, PartialEq, Eq)]
pub struct StoragePtr<T> {

149
storage/src/storage_val.rs Normal file
View File

@@ -0,0 +1,149 @@
use std::rc::Rc;
use serde::{Deserialize, Serialize};
use crate::serde_rc::{deserialize_rc, serialize_rc};
use crate::storage_ops::StorageOps;
use crate::storage_ptr::StorageEntryPtr;
#[cfg(test)]
use crate::{Storage, StorageBackend};
#[derive(Serialize, Deserialize, Debug)]
pub struct StorageVal {
pub point: StoragePoint,
#[serde(serialize_with = "serialize_rc", deserialize_with = "deserialize_rc")]
pub refs: Rc<Vec<StorageEntryPtr>>,
}
impl StorageVal {
pub fn to_entry(&self) -> StorageEntry {
StorageEntry {
ref_count: 1,
refs: self.refs.clone(),
data: bincode::serialize(&self.point).unwrap(),
}
}
#[cfg(test)]
pub(crate) fn numbers<SB: StorageBackend>(
&self,
storage: &mut Storage<SB>,
) -> Result<Vec<u64>, SB::Error<()>> {
storage
.sb
.transaction(|sb| self.point.numbers(sb, &self.refs))
}
}
#[derive(Default, Serialize, Deserialize, PartialEq, Eq, Debug, Clone)]
pub enum StoragePoint {
#[default]
Void,
Number(u64),
Array(
#[serde(serialize_with = "serialize_rc", deserialize_with = "deserialize_rc")]
Rc<Vec<StoragePoint>>,
),
Ref(u64),
}
impl StoragePoint {
pub fn maybe_replace_store<E, SO: StorageOps<E>>(
&self,
tx: &mut SO,
refs: &Rc<Vec<StorageEntryPtr>>,
) -> Result<Option<StorageEntryPtr>, E> {
Ok(match &self {
StoragePoint::Void => None,
StoragePoint::Number(_) => None,
StoragePoint::Array(arr) => 'b: {
let mut replacements: Vec<(usize, StorageEntryPtr)> = Vec::new();
for i in 0..arr.len() {
if let Some(key) = arr[i].maybe_replace_store(tx, refs)? {
replacements.push((i, key));
}
}
if replacements.is_empty() {
break 'b Some(tx.store(&StorageVal {
point: StoragePoint::Array(arr.clone()),
refs: refs.clone(),
})?);
}
let mut new_arr = Vec::<StoragePoint>::new();
let mut new_refs = (**refs).clone();
let mut replacements_iter = replacements.iter();
let mut next_replacement = replacements_iter.next();
for (i, point) in arr.iter().enumerate() {
if let Some((j, entry_ptr)) = next_replacement {
if *j == i {
new_arr.push(StoragePoint::Ref(new_refs.len() as u64));
new_refs.push(*entry_ptr);
next_replacement = replacements_iter.next();
continue;
}
}
new_arr.push(point.clone());
}
Some(tx.store(&StorageVal {
point: StoragePoint::Array(Rc::new(new_arr)),
refs: Rc::new(new_refs),
})?)
}
StoragePoint::Ref(_) => None,
})
}
#[cfg(test)]
fn numbers<E, SO: StorageOps<E>>(
&self,
tx: &mut SO,
refs: &Rc<Vec<StorageEntryPtr>>,
) -> Result<Vec<u64>, E> {
match &self {
StoragePoint::Void => Ok(Vec::new()),
StoragePoint::Number(n) => Ok(vec![*n]),
StoragePoint::Array(arr) => {
let mut numbers = Vec::new();
for point in arr.iter() {
numbers.extend(point.numbers(tx, refs)?);
}
Ok(numbers)
}
StoragePoint::Ref(i) => {
let key = refs[*i as usize];
let val = tx.read(key)?.unwrap().to_val();
val.point.numbers(tx, &val.refs)
}
}
}
}
#[derive(Serialize, Deserialize)]
pub struct StorageEntry {
pub(crate) ref_count: u64,
#[serde(serialize_with = "serialize_rc", deserialize_with = "deserialize_rc")]
pub(crate) refs: Rc<Vec<StorageEntryPtr>>,
data: Vec<u8>,
}
impl StorageEntry {
pub fn to_val(&self) -> StorageVal {
StorageVal {
point: bincode::deserialize(&self.data).unwrap(),
refs: self.refs.clone(),
}
}
}

View File

@@ -5,8 +5,9 @@ mod tests_ {
use crate::{
memory_backend::MemoryBackend,
sled_backend::SledBackend,
storage::{Storage, StoragePoint, StorageVal},
storage::Storage,
storage_ptr::storage_head_ptr,
storage_val::{StoragePoint, StorageVal},
StorageBackend,
};
@@ -115,8 +116,6 @@ mod tests_ {
.unwrap()
.unwrap();
dbg!(&value);
let numbers = value.numbers(storage).unwrap();
assert_eq!(numbers, vec![1, 2, 3, 4]);