Skip to content

Commit

Permalink
Correct the get_mut and get_mut_or_default for ByteMapView (lin…
Browse files Browse the repository at this point in the history
…era-io#2238)

* Correct a bug with `get_mut` and `get_mut_or_default` for the `deleted_prefixes`.
* Add a test to handle that scenario.
* Merge the random tests of the complex views in a single file for better CI.
* Removal of unwrap() and replacement by ? and Result<()> when needed.
* Change the API from `Vec<u8>` to `&[u8]` for `collection_view` / `reentrant_collection_view`.
  • Loading branch information
MathieuDutSik authored Jul 15, 2024
1 parent 2554efe commit f59ad4d
Show file tree
Hide file tree
Showing 10 changed files with 1,020 additions and 1,041 deletions.
82 changes: 44 additions & 38 deletions linera-views/src/collection_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,12 +210,12 @@ where
/// # use crate::linera_views::views::View;
/// # let context = create_memory_context();
/// let mut view : ByteCollectionView<_, RegisterView<_,String>> = ByteCollectionView::load(context).await.unwrap();
/// let subview = view.load_entry_mut(vec![0, 1]).await.unwrap();
/// let subview = view.load_entry_mut(&[0, 1]).await.unwrap();
/// let value = subview.get();
/// assert_eq!(*value, String::default());
/// # })
/// ```
pub async fn load_entry_mut(&mut self, short_key: Vec<u8>) -> Result<&mut W, ViewError> {
pub async fn load_entry_mut(&mut self, short_key: &[u8]) -> Result<&mut W, ViewError> {
self.do_load_entry_mut(short_key).await
}

Expand All @@ -230,13 +230,13 @@ where
/// # use crate::linera_views::views::View;
/// # let context = create_memory_context();
/// let mut view : ByteCollectionView<_, RegisterView<_,String>> = ByteCollectionView::load(context).await.unwrap();
/// view.load_entry_mut(vec![0, 1]).await.unwrap();
/// let subview = view.load_entry_or_insert(vec![0, 1]).await.unwrap();
/// view.load_entry_mut(&[0, 1]).await.unwrap();
/// let subview = view.load_entry_or_insert(&[0, 1]).await.unwrap();
/// let value = subview.get();
/// assert_eq!(*value, String::default());
/// # })
/// ```
pub async fn load_entry_or_insert(&mut self, short_key: Vec<u8>) -> Result<&W, ViewError> {
pub async fn load_entry_or_insert(&mut self, short_key: &[u8]) -> Result<&W, ViewError> {
Ok(self.do_load_entry_mut(short_key).await?)
}

Expand All @@ -252,46 +252,52 @@ where
/// # let context = create_memory_context();
/// let mut view : ByteCollectionView<_, RegisterView<_,String>> = ByteCollectionView::load(context).await.unwrap();
/// {
/// let _subview = view.load_entry_or_insert(vec![0, 1]).await.unwrap();
/// let _subview = view.load_entry_or_insert(&[0, 1]).await.unwrap();
/// }
/// {
/// let subview = view.try_load_entry(vec![0, 1]).await.unwrap().unwrap();
/// let subview = view.try_load_entry(&[0, 1]).await.unwrap().unwrap();
/// let value = subview.get();
/// assert_eq!(*value, String::default());
/// }
/// assert!(view.try_load_entry(vec![0, 2]).await.unwrap().is_none());
/// assert!(view.try_load_entry(&[0, 2]).await.unwrap().is_none());
/// # })
/// ```
pub async fn try_load_entry(
&self,
short_key: Vec<u8>,
short_key: &[u8],
) -> Result<Option<ReadGuardedView<W>>, ViewError> {
let mut updates = self
.updates
.try_write()
.ok_or(ViewError::CannotAcquireCollectionEntry)?;
match updates.entry(short_key.clone()) {
match updates.entry(short_key.to_vec()) {
btree_map::Entry::Occupied(entry) => {
let entry = entry.into_mut();
match entry {
Update::Set(_) => {
let guard = RwLockWriteGuard::downgrade(updates);
Ok(Some(ReadGuardedView { guard, short_key }))
Ok(Some(ReadGuardedView {
guard,
short_key: short_key.to_vec(),
}))
}
Update::Removed => Ok(None),
}
}
btree_map::Entry::Vacant(entry) => {
let key_index = self.context.base_tag_index(KeyTag::Index as u8, &short_key);
let key_index = self.context.base_tag_index(KeyTag::Index as u8, short_key);
if !self.delete_storage_first && self.context.contains_key(&key_index).await? {
let key = self
.context
.base_tag_index(KeyTag::Subview as u8, &short_key);
.base_tag_index(KeyTag::Subview as u8, short_key);
let context = self.context.clone_with_base_key(key);
let view = W::load(context).await?;
entry.insert(Update::Set(view));
let guard = RwLockWriteGuard::downgrade(updates);
Ok(Some(ReadGuardedView { guard, short_key }))
Ok(Some(ReadGuardedView {
guard,
short_key: short_key.to_vec(),
}))
} else {
Ok(None)
}
Expand All @@ -308,16 +314,16 @@ where
/// # use crate::linera_views::views::View;
/// # let context = create_memory_context();
/// let mut view : ByteCollectionView<_, RegisterView<_,String>> = ByteCollectionView::load(context).await.unwrap();
/// let subview = view.load_entry_mut(vec![0, 1]).await.unwrap();
/// let subview = view.load_entry_mut(&[0, 1]).await.unwrap();
/// let value = subview.get_mut();
/// *value = String::from("Hello");
/// view.reset_entry_to_default(vec![0, 1]).await.unwrap();
/// let subview = view.load_entry_mut(vec![0, 1]).await.unwrap();
/// view.reset_entry_to_default(&[0, 1]).await.unwrap();
/// let subview = view.load_entry_mut(&[0, 1]).await.unwrap();
/// let value = subview.get_mut();
/// assert_eq!(*value, String::default());
/// # })
/// ```
pub async fn reset_entry_to_default(&mut self, short_key: Vec<u8>) -> Result<(), ViewError> {
pub async fn reset_entry_to_default(&mut self, short_key: &[u8]) -> Result<(), ViewError> {
let view = self.load_entry_mut(short_key).await?;
view.clear();
Ok(())
Expand All @@ -333,7 +339,7 @@ where
/// # let context = create_memory_context();
/// let mut view : ByteCollectionView<_, RegisterView<_,String>> = ByteCollectionView::load(context).await.unwrap();
/// {
/// let _subview = view.load_entry_mut(vec![0, 1]).await.unwrap();
/// let _subview = view.load_entry_mut(&[0, 1]).await.unwrap();
/// }
/// assert!(view.contains_key(&[0, 1]).await.unwrap());
/// assert!(!view.contains_key(&[0, 2]).await.unwrap());
Expand Down Expand Up @@ -362,7 +368,7 @@ where
/// # use crate::linera_views::views::View;
/// # let context = create_memory_context();
/// let mut view : ByteCollectionView<_, RegisterView<_,String>> = ByteCollectionView::load(context).await.unwrap();
/// let subview = view.load_entry_mut(vec![0, 1]).await.unwrap();
/// let subview = view.load_entry_mut(&[0, 1]).await.unwrap();
/// let value = subview.get_mut();
/// assert_eq!(*value, String::default());
/// view.remove_entry(vec![0, 1]);
Expand All @@ -384,16 +390,16 @@ where
self.context.extra()
}

async fn do_load_entry_mut(&mut self, short_key: Vec<u8>) -> Result<&mut W, ViewError> {
match self.updates.get_mut().entry(short_key.clone()) {
async fn do_load_entry_mut(&mut self, short_key: &[u8]) -> Result<&mut W, ViewError> {
match self.updates.get_mut().entry(short_key.to_vec()) {
btree_map::Entry::Occupied(entry) => {
let entry = entry.into_mut();
match entry {
Update::Set(view) => Ok(view),
Update::Removed => {
let key = self
.context
.base_tag_index(KeyTag::Subview as u8, &short_key);
.base_tag_index(KeyTag::Subview as u8, short_key);
let context = self.context.clone_with_base_key(key);
// Obtain a view and set its pending state to the default (e.g. empty) state
let mut view = W::load(context).await?;
Expand All @@ -409,7 +415,7 @@ where
btree_map::Entry::Vacant(entry) => {
let key = self
.context
.base_tag_index(KeyTag::Subview as u8, &short_key);
.base_tag_index(KeyTag::Subview as u8, short_key);
let context = self.context.clone_with_base_key(key);
let mut view = W::load(context).await?;
if self.delete_storage_first {
Expand Down Expand Up @@ -441,8 +447,8 @@ where
/// # use crate::linera_views::views::View;
/// # let context = create_memory_context();
/// let mut view : ByteCollectionView<_, RegisterView<_,String>> = ByteCollectionView::load(context).await.unwrap();
/// view.load_entry_mut(vec![0, 1]).await.unwrap();
/// view.load_entry_mut(vec![0, 2]).await.unwrap();
/// view.load_entry_mut(&[0, 1]).await.unwrap();
/// view.load_entry_mut(&[0, 2]).await.unwrap();
/// let mut count = 0;
/// view.for_each_key_while(|_key| {
/// count += 1;
Expand Down Expand Up @@ -506,8 +512,8 @@ where
/// # use crate::linera_views::views::View;
/// # let context = create_memory_context();
/// let mut view : ByteCollectionView<_, RegisterView<_,String>> = ByteCollectionView::load(context).await.unwrap();
/// view.load_entry_mut(vec![0, 1]).await.unwrap();
/// view.load_entry_mut(vec![0, 2]).await.unwrap();
/// view.load_entry_mut(&[0, 1]).await.unwrap();
/// view.load_entry_mut(&[0, 2]).await.unwrap();
/// let mut count = 0;
/// view.for_each_key(|_key| {
/// count += 1;
Expand Down Expand Up @@ -536,8 +542,8 @@ where
/// # use crate::linera_views::views::View;
/// # let context = create_memory_context();
/// let mut view : ByteCollectionView<_, RegisterView<_,String>> = ByteCollectionView::load(context).await.unwrap();
/// view.load_entry_mut(vec![0, 1]).await.unwrap();
/// view.load_entry_mut(vec![0, 2]).await.unwrap();
/// view.load_entry_mut(&[0, 1]).await.unwrap();
/// view.load_entry_mut(&[0, 2]).await.unwrap();
/// let keys = view.keys().await.unwrap();
/// assert_eq!(keys, vec![vec![0, 1], vec![0, 2]]);
/// # })
Expand Down Expand Up @@ -708,7 +714,7 @@ where
Q: Serialize + ?Sized,
{
let short_key = C::derive_short_key(index)?;
self.collection.load_entry_mut(short_key).await
self.collection.load_entry_mut(&short_key).await
}

/// Loads a subview for the data at the given index in the collection. If an entry
Expand All @@ -734,7 +740,7 @@ where
Q: Serialize + ?Sized,
{
let short_key = C::derive_short_key(index)?;
self.collection.load_entry_or_insert(short_key).await
self.collection.load_entry_or_insert(&short_key).await
}

/// Loads a subview for the data at the given index in the collection. If an entry
Expand Down Expand Up @@ -768,7 +774,7 @@ where
Q: Serialize + ?Sized,
{
let short_key = C::derive_short_key(index)?;
self.collection.try_load_entry(short_key).await
self.collection.try_load_entry(&short_key).await
}

/// Resets an entry to the default value.
Expand All @@ -795,7 +801,7 @@ where
Q: Serialize + ?Sized,
{
let short_key = C::derive_short_key(index)?;
self.collection.reset_entry_to_default(short_key).await
self.collection.reset_entry_to_default(&short_key).await
}

/// Removes an entry from the CollectionView. If absent nothing happens.
Expand Down Expand Up @@ -1047,7 +1053,7 @@ where
Q: CustomSerialize,
{
let short_key = index.to_custom_bytes()?;
self.collection.load_entry_mut(short_key).await
self.collection.load_entry_mut(&short_key).await
}

/// Loads a subview for the data at the given index in the collection. If an entry
Expand All @@ -1073,7 +1079,7 @@ where
Q: CustomSerialize,
{
let short_key = index.to_custom_bytes()?;
self.collection.load_entry_or_insert(short_key).await
self.collection.load_entry_or_insert(&short_key).await
}

/// Loads a subview for the data at the given index in the collection. If an entry
Expand Down Expand Up @@ -1107,7 +1113,7 @@ where
Q: CustomSerialize,
{
let short_key = index.to_custom_bytes()?;
self.collection.try_load_entry(short_key).await
self.collection.try_load_entry(&short_key).await
}

/// Marks the entry so that it is removed in the next flush.
Expand All @@ -1134,7 +1140,7 @@ where
Q: CustomSerialize,
{
let short_key = index.to_custom_bytes()?;
self.collection.reset_entry_to_default(short_key).await
self.collection.reset_entry_to_default(&short_key).await
}

/// Removes an entry from the CollectionView. If absent nothing happens.
Expand Down
Loading

0 comments on commit f59ad4d

Please sign in to comment.