Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[db] Fix interior mutability of Storage #645 #646

Merged
merged 4 commits into from
Jul 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
149 changes: 73 additions & 76 deletions src/agdb/collections/indexed_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,97 +9,99 @@ use crate::storage::file_storage::FileStorage;
use crate::storage::Storage;
use crate::storage::StorageIndex;
use crate::utilities::stable_hash::StableHash;
use std::cell::RefCell;
use std::rc::Rc;
use std::marker::PhantomData;

pub struct IndexedMapImpl<K, T, DataKT, DataTK>
pub struct IndexedMapImpl<K, T, S, DataKT, DataTK>
where
DataKT: MapData<K, T>,
DataTK: MapData<T, K>,
DataKT: MapData<K, T, S>,
DataTK: MapData<T, K, S>,
{
pub(crate) keys_to_values: MapImpl<K, T, DataKT>,
pub(crate) values_to_keys: MapImpl<T, K, DataTK>,
pub(crate) keys_to_values: MapImpl<K, T, S, DataKT>,
pub(crate) values_to_keys: MapImpl<T, K, S, DataTK>,
pub(crate) storage: PhantomData<S>,
}

impl<K, T, DataKT, DataTK> IndexedMapImpl<K, T, DataKT, DataTK>
impl<K, T, S, DataKT, DataTK> IndexedMapImpl<K, T, S, DataKT, DataTK>
where
K: Default + PartialEq + StableHash,
T: Default + PartialEq + StableHash,
DataKT: MapData<K, T>,
DataTK: MapData<T, K>,
DataKT: MapData<K, T, S>,
DataTK: MapData<T, K, S>,
{
pub fn insert(&mut self, key: &K, value: &T) -> Result<(), DbError> {
if let Some(v) = self.keys_to_values.insert(key, value)? {
self.values_to_keys.remove(&v)?;
pub fn insert(&mut self, storage: &mut S, key: &K, value: &T) -> Result<(), DbError> {
if let Some(v) = self.keys_to_values.insert(storage, key, value)? {
self.values_to_keys.remove(storage, &v)?;
}

if let Some(k) = self.values_to_keys.insert(value, key)? {
self.keys_to_values.remove(&k)?;
if let Some(k) = self.values_to_keys.insert(storage, value, key)? {
self.keys_to_values.remove(storage, &k)?;
}

Ok(())
}

#[allow(dead_code)]
pub fn iter(&self) -> MapIterator<K, T, DataKT> {
pub fn iter(&self) -> MapIterator<K, T, S, DataKT> {
self.keys_to_values.iter()
}

pub fn key(&self, value: &T) -> Result<Option<K>, DbError> {
self.values_to_keys.value(value)
}

pub fn remove_key(&mut self, key: &K) -> Result<(), DbError> {
pub fn remove_key(&mut self, storage: &mut S, key: &K) -> Result<(), DbError> {
if let Some(value) = self.keys_to_values.value(key)? {
self.values_to_keys.remove(&value)?;
self.values_to_keys.remove(storage, &value)?;
}

self.keys_to_values.remove(key)
self.keys_to_values.remove(storage, key)
}

#[allow(dead_code)]
pub fn remove_value(&mut self, value: &T) -> Result<(), DbError> {
pub fn remove_value(&mut self, storage: &mut S, value: &T) -> Result<(), DbError> {
if let Some(key) = self.values_to_keys.value(value)? {
self.keys_to_values.remove(&key)?;
self.keys_to_values.remove(storage, &key)?;
}

self.values_to_keys.remove(value)
self.values_to_keys.remove(storage, value)
}

pub fn value(&self, key: &K) -> Result<Option<T>, DbError> {
self.keys_to_values.value(key)
}
}

pub type DbIndexedMap<K, T, Data = FileStorage> =
IndexedMapImpl<K, T, DbMapData<K, T, Data>, DbMapData<T, K, Data>>;
pub type DbIndexedMap<K, T, S = FileStorage> =
IndexedMapImpl<K, T, S, DbMapData<K, T, S>, DbMapData<T, K, S>>;

impl<K, T, Data> DbIndexedMap<K, T, Data>
impl<K, T, S> DbIndexedMap<K, T, S>
where
K: Default + Clone + VecValue,
T: Default + Clone + VecValue,
Data: Storage,
S: Storage,
{
pub fn new(storage: Rc<RefCell<Data>>) -> Result<Self, DbError> {
let keys_to_values = DbMap::<K, T, Data>::new(storage.clone())?;
let values_to_keys = DbMap::<T, K, Data>::new(storage)?;
pub fn new(storage: &mut S) -> Result<Self, DbError> {
let keys_to_values = DbMap::<K, T, S>::new(storage)?;
let values_to_keys = DbMap::<T, K, S>::new(storage)?;

Ok(Self {
keys_to_values,
values_to_keys,
storage: PhantomData,
})
}

pub fn from_storage(
storage: Rc<RefCell<Data>>,
storage: &mut S,
index: (StorageIndex, StorageIndex),
) -> Result<Self, DbError> {
let keys_to_values = DbMap::<K, T, Data>::from_storage(storage.clone(), index.0)?;
let values_to_keys = DbMap::<T, K, Data>::from_storage(storage, index.1)?;
let keys_to_values = DbMap::<K, T, S>::from_storage(storage, index.0)?;
let values_to_keys = DbMap::<T, K, S>::from_storage(storage, index.1)?;

Ok(Self {
keys_to_values,
values_to_keys,
storage: PhantomData,
})
}

Expand All @@ -119,35 +121,31 @@ mod tests {
#[test]
fn from_storage() {
let test_file = TestFile::new();
let storage = Rc::new(RefCell::new(
FileStorage::new(test_file.file_name()).unwrap(),
));
let mut storage = FileStorage::new(test_file.file_name()).unwrap();

let storage_index;

{
let mut map = DbIndexedMap::<String, u64>::new(storage.clone()).unwrap();
let mut map = DbIndexedMap::<String, u64>::new(&mut storage).unwrap();
let key = "alias".to_string();
let value = 1_u64;
map.insert(&key, &value).unwrap();
map.insert(&mut storage, &key, &value).unwrap();
storage_index = map.storage_index();
}

let map = DbIndexedMap::<String, u64>::from_storage(storage, storage_index).unwrap();
let map = DbIndexedMap::<String, u64>::from_storage(&mut storage, storage_index).unwrap();
assert_eq!(map.value(&"alias".to_string()).unwrap(), Some(1_u64));
}

#[test]
fn insert() {
let test_file = TestFile::new();
let storage = Rc::new(RefCell::new(
FileStorage::new(test_file.file_name()).unwrap(),
));
let mut map = DbIndexedMap::<String, u64>::new(storage).unwrap();
let mut storage = FileStorage::new(test_file.file_name()).unwrap();
let mut map = DbIndexedMap::<String, u64>::new(&mut storage).unwrap();
let key = "alias".to_string();
let value = 1_u64;

assert_eq!(map.insert(&key, &value), Ok(()));
assert_eq!(map.insert(&mut storage, &key, &value), Ok(()));

assert_eq!(map.value(&key), Ok(Some(value)));
assert_eq!(map.key(&value), Ok(Some(key)));
Expand All @@ -156,13 +154,20 @@ mod tests {
#[test]
fn iter() {
let test_file = TestFile::new();
let storage = Rc::new(RefCell::new(
FileStorage::new(test_file.file_name()).unwrap(),
));
let mut map = DbIndexedMap::<String, u64>::new(storage).unwrap();
assert_eq!(map.insert(&"alias1".to_string(), &1_u64), Ok(()));
assert_eq!(map.insert(&"alias2".to_string(), &2_u64), Ok(()));
assert_eq!(map.insert(&"alias3".to_string(), &3_u64), Ok(()));
let mut storage = FileStorage::new(test_file.file_name()).unwrap();
let mut map = DbIndexedMap::<String, u64>::new(&mut storage).unwrap();
assert_eq!(
map.insert(&mut storage, &"alias1".to_string(), &1_u64),
Ok(())
);
assert_eq!(
map.insert(&mut storage, &"alias2".to_string(), &2_u64),
Ok(())
);
assert_eq!(
map.insert(&mut storage, &"alias3".to_string(), &3_u64),
Ok(())
);

let mut values = Vec::<(String, u64)>::new();

Expand All @@ -185,16 +190,14 @@ mod tests {
#[test]
fn replace_by_key() {
let test_file = TestFile::new();
let storage = Rc::new(RefCell::new(
FileStorage::new(test_file.file_name()).unwrap(),
));
let mut map = DbIndexedMap::<String, u64>::new(storage).unwrap();
let mut storage = FileStorage::new(test_file.file_name()).unwrap();
let mut map = DbIndexedMap::<String, u64>::new(&mut storage).unwrap();
let key = "alias".to_string();
let value = 1_u64;
let new_value = 2_u64;

assert_eq!(map.insert(&key, &value), Ok(()));
assert_eq!(map.insert(&key, &new_value), Ok(()));
assert_eq!(map.insert(&mut storage, &key, &value), Ok(()));
assert_eq!(map.insert(&mut storage, &key, &new_value), Ok(()));

assert_eq!(map.value(&key), Ok(Some(new_value)));
assert_eq!(map.key(&new_value), Ok(Some(key)));
Expand All @@ -204,16 +207,14 @@ mod tests {
#[test]
fn replace_by_value() {
let test_file = TestFile::new();
let storage = Rc::new(RefCell::new(
FileStorage::new(test_file.file_name()).unwrap(),
));
let mut map = DbIndexedMap::<String, u64>::new(storage).unwrap();
let mut storage = FileStorage::new(test_file.file_name()).unwrap();
let mut map = DbIndexedMap::<String, u64>::new(&mut storage).unwrap();
let key = "alias".to_string();
let new_key = "new_alias".to_string();
let value = 1_u64;

assert_eq!(map.insert(&key, &value), Ok(()));
assert_eq!(map.insert(&new_key, &value), Ok(()));
assert_eq!(map.insert(&mut storage, &key, &value), Ok(()));
assert_eq!(map.insert(&mut storage, &new_key, &value), Ok(()));

assert_eq!(map.value(&key), Ok(None));
assert_eq!(map.value(&new_key), Ok(Some(value)));
Expand All @@ -223,20 +224,18 @@ mod tests {
#[test]
fn remove_key() {
let test_file = TestFile::new();
let storage = Rc::new(RefCell::new(
FileStorage::new(test_file.file_name()).unwrap(),
));
let mut map = DbIndexedMap::<String, u64>::new(storage).unwrap();
let mut storage = FileStorage::new(test_file.file_name()).unwrap();
let mut map = DbIndexedMap::<String, u64>::new(&mut storage).unwrap();
let key = "alias".to_string();
let value = 1_u64;

assert_eq!(map.insert(&key, &value), Ok(()));
assert_eq!(map.insert(&mut storage, &key, &value), Ok(()));

assert_eq!(map.value(&key), Ok(Some(value)));
assert_eq!(map.key(&value), Ok(Some(key.clone())));

map.remove_key(&key).unwrap();
map.remove_key(&key).unwrap();
map.remove_key(&mut storage, &key).unwrap();
map.remove_key(&mut storage, &key).unwrap();

assert_eq!(map.value(&key), Ok(None));
assert_eq!(map.key(&value), Ok(None));
Expand All @@ -245,20 +244,18 @@ mod tests {
#[test]
fn remove_value() {
let test_file = TestFile::new();
let storage = Rc::new(RefCell::new(
FileStorage::new(test_file.file_name()).unwrap(),
));
let mut map = DbIndexedMap::<String, u64>::new(storage).unwrap();
let mut storage = FileStorage::new(test_file.file_name()).unwrap();
let mut map = DbIndexedMap::<String, u64>::new(&mut storage).unwrap();
let key = "alias".to_string();
let value = 1_u64;

assert_eq!(map.insert(&key, &value), Ok(()));
assert_eq!(map.insert(&mut storage, &key, &value), Ok(()));

assert_eq!(map.value(&key), Ok(Some(value)));
assert_eq!(map.key(&value), Ok(Some(key.clone())));

map.remove_value(&value).unwrap();
map.remove_value(&value).unwrap();
map.remove_value(&mut storage, &value).unwrap();
map.remove_value(&mut storage, &value).unwrap();

assert_eq!(map.value(&key), Ok(None));
assert_eq!(map.key(&value), Ok(None));
Expand Down
Loading