Skip to content

Commit 8bd839a

Browse files
Add try_load_all_entries to CollectionView. (#4763)
## Motivation Just like for `ReentrantCollectionView`, we can load all entries at once in `CollectionView`. ## Proposal The code was added in a straightforward way. ## Test Plan The test has been to the CI. The consequence is that the `try_load_all_entries` has been tested for `ReentrantCollectionView`. This led to the removal of the `Q` types that was not used. ## Release Plan - Nothing to do / These changes follow the usual release cycle. ## Links None.
1 parent 03173c1 commit 8bd839a

File tree

3 files changed

+166
-28
lines changed

3 files changed

+166
-28
lines changed

linera-views/src/views/collection_view.rs

Lines changed: 146 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,87 @@ impl<W: View> ByteCollectionView<W::Context, W> {
415415
Ok(results)
416416
}
417417

418+
/// Load all entries for reading at once.
419+
/// ```rust
420+
/// # tokio_test::block_on(async {
421+
/// # use linera_views::context::MemoryContext;
422+
/// # use linera_views::collection_view::ByteCollectionView;
423+
/// # use linera_views::register_view::RegisterView;
424+
/// # use linera_views::views::View;
425+
/// # let context = MemoryContext::new_for_testing(());
426+
/// let mut view: ByteCollectionView<_, RegisterView<_, String>> =
427+
/// ByteCollectionView::load(context).await.unwrap();
428+
/// {
429+
/// let _subview = view.load_entry_or_insert(&[0, 1]).await.unwrap();
430+
/// }
431+
/// let subviews = view.try_load_all_entries().await.unwrap();
432+
/// assert_eq!(subviews.len(), 1);
433+
/// # })
434+
/// ```
435+
pub async fn try_load_all_entries(
436+
&self,
437+
) -> Result<Vec<(Vec<u8>, ReadGuardedView<W>)>, ViewError> {
438+
let updates = self.updates.read().await; // Acquire the read lock to prevent writes.
439+
let short_keys = self.keys().await?;
440+
let mut results = Vec::with_capacity(short_keys.len());
441+
442+
let mut keys_to_load = Vec::new();
443+
let mut keys_to_load_metadata = Vec::new();
444+
for (position, short_key) in short_keys.iter().enumerate() {
445+
match updates.get(short_key) {
446+
Some(update) => {
447+
let Update::Set(_) = update else {
448+
unreachable!();
449+
};
450+
let updates = self.updates.read().await;
451+
let view = ReadGuardedView::Loaded {
452+
updates,
453+
short_key: short_key.clone(),
454+
};
455+
results.push((short_key.clone(), Some(view)));
456+
}
457+
None => {
458+
// If a key is not in `updates`, then it is in storage.
459+
// The key exists since otherwise it would not be in `short_keys`.
460+
// Therefore we have `self.delete_storage_first = false`.
461+
assert!(!self.delete_storage_first);
462+
results.push((short_key.clone(), None));
463+
let key = self
464+
.context
465+
.base_key()
466+
.base_tag_index(KeyTag::Subview as u8, short_key);
467+
let subview_context = self.context.clone_with_base_key(key);
468+
keys_to_load.extend(W::pre_load(&subview_context)?);
469+
keys_to_load_metadata.push((position, subview_context, short_key.clone()));
470+
}
471+
}
472+
}
473+
474+
let values = self
475+
.context
476+
.store()
477+
.read_multi_values_bytes(keys_to_load)
478+
.await?;
479+
480+
for (loaded_values, (position, context, short_key)) in values
481+
.chunks_exact_or_repeat(W::NUM_INIT_KEYS)
482+
.zip(keys_to_load_metadata)
483+
{
484+
let view = W::post_load(context, loaded_values)?;
485+
let updates = self.updates.read().await;
486+
let guarded_view = ReadGuardedView::NotLoaded {
487+
_updates: updates,
488+
view,
489+
};
490+
results[position] = (short_key, Some(guarded_view));
491+
}
492+
493+
Ok(results
494+
.into_iter()
495+
.map(|(short_key, view)| (short_key, view.unwrap()))
496+
.collect::<Vec<_>>())
497+
}
498+
418499
/// Resets an entry to the default value.
419500
/// ```rust
420501
/// # tokio_test::block_on(async {
@@ -465,7 +546,7 @@ impl<W: View> ByteCollectionView<W::Context, W> {
465546
/// # })
466547
/// ```
467548
pub async fn contains_key(&self, short_key: &[u8]) -> Result<bool, ViewError> {
468-
let updates = self.updates.write().await;
549+
let updates = self.updates.read().await;
469550
Ok(match updates.get(short_key) {
470551
Some(entry) => match entry {
471552
Update::Set(_view) => true,
@@ -584,7 +665,7 @@ impl<W: View> ByteCollectionView<W::Context, W> {
584665
where
585666
F: FnMut(&[u8]) -> Result<bool, ViewError> + Send,
586667
{
587-
let updates = self.updates.write().await;
668+
let updates = self.updates.read().await;
588669
let mut updates = updates.iter();
589670
let mut update = updates.next();
590671
if !self.delete_storage_first {
@@ -749,10 +830,10 @@ impl<W: HashableView> HashableView for ByteCollectionView<W::Context, W> {
749830
#[cfg(with_metrics)]
750831
let _hash_latency = metrics::COLLECTION_VIEW_HASH_RUNTIME.measure_latency();
751832
let mut hasher = sha3::Sha3_256::default();
833+
let updates = self.updates.read().await; // Acquire the lock to prevent writes.
752834
let keys = self.keys().await?;
753835
let count = keys.len() as u32;
754836
hasher.update_with_bcs_bytes(&count)?;
755-
let updates = self.updates.read().await;
756837
for key in keys {
757838
hasher.update_with_bytes(&key)?;
758839
let hash = match updates.get(&key) {
@@ -967,6 +1048,37 @@ impl<I: Serialize, W: View> CollectionView<W::Context, I, W> {
9671048
self.collection.try_load_entries(short_keys).await
9681049
}
9691050

1051+
/// Load all entries for reading at once.
1052+
/// ```rust
1053+
/// # tokio_test::block_on(async {
1054+
/// # use linera_views::context::MemoryContext;
1055+
/// # use linera_views::collection_view::CollectionView;
1056+
/// # use linera_views::register_view::RegisterView;
1057+
/// # use linera_views::views::View;
1058+
/// # let context = MemoryContext::new_for_testing(());
1059+
/// let mut view: CollectionView<_, u64, RegisterView<_, String>> =
1060+
/// CollectionView::load(context).await.unwrap();
1061+
/// {
1062+
/// let _subview = view.load_entry_or_insert(&23).await.unwrap();
1063+
/// }
1064+
/// let subviews = view.try_load_all_entries().await.unwrap();
1065+
/// assert_eq!(subviews.len(), 1);
1066+
/// # })
1067+
/// ```
1068+
pub async fn try_load_all_entries(&self) -> Result<Vec<(I, ReadGuardedView<W>)>, ViewError>
1069+
where
1070+
I: DeserializeOwned,
1071+
{
1072+
let results = self.collection.try_load_all_entries().await?;
1073+
results
1074+
.into_iter()
1075+
.map(|(short_key, view)| {
1076+
let index = BaseKey::deserialize_value(&short_key)?;
1077+
Ok((index, view))
1078+
})
1079+
.collect()
1080+
}
1081+
9701082
/// Resets an entry to the default value.
9711083
/// ```rust
9721084
/// # tokio_test::block_on(async {
@@ -1351,6 +1463,37 @@ impl<I: CustomSerialize, W: View> CustomCollectionView<W::Context, I, W> {
13511463
self.collection.try_load_entries(short_keys).await
13521464
}
13531465

1466+
/// Load all entries for reading at once.
1467+
/// ```rust
1468+
/// # tokio_test::block_on(async {
1469+
/// # use linera_views::context::MemoryContext;
1470+
/// # use linera_views::collection_view::CustomCollectionView;
1471+
/// # use linera_views::register_view::RegisterView;
1472+
/// # use linera_views::views::View;
1473+
/// # let context = MemoryContext::new_for_testing(());
1474+
/// let mut view: CustomCollectionView<_, u128, RegisterView<_, String>> =
1475+
/// CustomCollectionView::load(context).await.unwrap();
1476+
/// {
1477+
/// let _subview = view.load_entry_or_insert(&23).await.unwrap();
1478+
/// }
1479+
/// let subviews = view.try_load_all_entries().await.unwrap();
1480+
/// assert_eq!(subviews.len(), 1);
1481+
/// # })
1482+
/// ```
1483+
pub async fn try_load_all_entries(&self) -> Result<Vec<(I, ReadGuardedView<W>)>, ViewError>
1484+
where
1485+
I: CustomSerialize,
1486+
{
1487+
let results = self.collection.try_load_all_entries().await?;
1488+
results
1489+
.into_iter()
1490+
.map(|(short_key, view)| {
1491+
let index = I::from_custom_bytes(&short_key)?;
1492+
Ok((index, view))
1493+
})
1494+
.collect()
1495+
}
1496+
13541497
/// Marks the entry so that it is removed in the next flush.
13551498
/// ```rust
13561499
/// # tokio_test::block_on(async {

linera-views/src/views/reentrant_collection_view.rs

Lines changed: 7 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1356,13 +1356,9 @@ where
13561356
/// assert_eq!(subviews.len(), 1);
13571357
/// # })
13581358
/// ```
1359-
pub async fn try_load_all_entries_mut<'a, Q>(
1360-
&'a mut self,
1361-
) -> Result<Vec<(I, WriteGuardedView<W>)>, ViewError>
1362-
where
1363-
I: Borrow<Q>,
1364-
Q: Serialize + 'a,
1365-
{
1359+
pub async fn try_load_all_entries_mut(
1360+
&mut self,
1361+
) -> Result<Vec<(I, WriteGuardedView<W>)>, ViewError> {
13661362
let results = self.collection.try_load_all_entries_mut().await?;
13671363
results
13681364
.into_iter()
@@ -1391,13 +1387,7 @@ where
13911387
/// assert_eq!(subviews.len(), 1);
13921388
/// # })
13931389
/// ```
1394-
pub async fn try_load_all_entries<'a, Q>(
1395-
&'a self,
1396-
) -> Result<Vec<(I, ReadGuardedView<W>)>, ViewError>
1397-
where
1398-
I: Borrow<Q>,
1399-
Q: Serialize + 'a,
1400-
{
1390+
pub async fn try_load_all_entries(&self) -> Result<Vec<(I, ReadGuardedView<W>)>, ViewError> {
14011391
let results = self.collection.try_load_all_entries().await?;
14021392
results
14031393
.into_iter()
@@ -1861,13 +1851,9 @@ where
18611851
/// assert_eq!(subviews.len(), 1);
18621852
/// # })
18631853
/// ```
1864-
pub async fn try_load_all_entries_mut<Q>(
1854+
pub async fn try_load_all_entries_mut(
18651855
&mut self,
1866-
) -> Result<Vec<(I, WriteGuardedView<W>)>, ViewError>
1867-
where
1868-
I: Borrow<Q>,
1869-
Q: CustomSerialize,
1870-
{
1856+
) -> Result<Vec<(I, WriteGuardedView<W>)>, ViewError> {
18711857
let results = self.collection.try_load_all_entries_mut().await?;
18721858
results
18731859
.into_iter()
@@ -1896,11 +1882,7 @@ where
18961882
/// assert_eq!(subviews.len(), 1);
18971883
/// # })
18981884
/// ```
1899-
pub async fn try_load_all_entries<Q>(&self) -> Result<Vec<(I, ReadGuardedView<W>)>, ViewError>
1900-
where
1901-
I: Borrow<Q>,
1902-
Q: CustomSerialize,
1903-
{
1885+
pub async fn try_load_all_entries(&self) -> Result<Vec<(I, ReadGuardedView<W>)>, ViewError> {
19041886
let results = self.collection.try_load_all_entries().await?;
19051887
results
19061888
.into_iter()

linera-views/tests/random_container_tests.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -532,6 +532,19 @@ impl<C: Context> NestedCollectionMapView<C> {
532532
let key_values = key_values1.into_iter().collect::<BTreeMap<String, u64>>();
533533
state_map.insert(index, key_values);
534534
}
535+
let key_subviews1 = self.map1.try_load_all_entries().await?;
536+
let key_subviews2 = self.map2.try_load_all_entries().await?;
537+
for ((key_subview1, key_subview2), index) in
538+
key_subviews1.into_iter().zip(key_subviews2).zip(indices2)
539+
{
540+
let (index1, subview1) = key_subview1;
541+
let (index2, subview2) = key_subview2;
542+
assert_eq!(index1, index, "index1 should be coherent");
543+
assert_eq!(index2, index, "index1 should be coherent");
544+
let key_values1 = subview1.index_values().await?;
545+
let key_values2 = subview2.index_values().await?;
546+
assert_eq!(key_values1, key_values2, "key-values should be equal");
547+
}
535548
Ok(state_map)
536549
}
537550
}

0 commit comments

Comments
 (0)