Skip to content

Commit d8070ac

Browse files
Change the API of read_blob_state to return options. (#4018)
## Motivation Following PR #4014 we look at the `read_blob_state` and change their API as options. The same design considerations apply here. ## Proposal The `read_blob_state(s)` were returning a ViewError that contained a `NotFound`. This is inadequate and in any case the `NotFound` is never processed. In all use cases of those functions, we had some `BlobsNotFound` variant in the relevant types, the error type was thus put there. It could change the behavior of some function. However, this is better than having some error buried in `ViewError`. The `NotFound` cannot yet be changed because it is used by the `read_certificate(s)`. Other changes: * After PR 4104, some of the metrics were placed before the storage calls. This has been corrected. * In some of the accounting of the calls, the plural calls were sometimes counting several calls as one, and in other cases as the number of entries in the call. This has been corrected. ## Test Plan The CI. ## Release Plan - Nothing to do / These changes follow the usual release cycle. ## Links None.
1 parent 870e287 commit d8070ac

File tree

9 files changed

+73
-39
lines changed

9 files changed

+73
-39
lines changed

linera-core/src/local_node.rs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use linera_chain::{
1818
types::{Block, GenericCertificate, LiteCertificate},
1919
ChainStateView,
2020
};
21-
use linera_execution::{committee::Committee, Query, QueryOutcome};
21+
use linera_execution::{committee::Committee, BlobState, Query, QueryOutcome};
2222
use linera_storage::Storage;
2323
use linera_views::ViewError;
2424
use thiserror::Error;
@@ -170,6 +170,31 @@ where
170170
Ok(storage.read_blobs(blob_ids).await?.into_iter().collect())
171171
}
172172

173+
/// Reads blob states from storage
174+
pub async fn read_blob_states_from_storage(
175+
&self,
176+
blob_ids: &[BlobId],
177+
) -> Result<Vec<BlobState>, LocalNodeError> {
178+
let storage = self.storage_client();
179+
let mut blobs_not_found = Vec::new();
180+
let mut blob_states = Vec::new();
181+
for (blob_state, blob_id) in storage
182+
.read_blob_states(blob_ids)
183+
.await?
184+
.into_iter()
185+
.zip(blob_ids)
186+
{
187+
match blob_state {
188+
None => blobs_not_found.push(*blob_id),
189+
Some(blob_state) => blob_states.push(blob_state),
190+
}
191+
}
192+
if !blobs_not_found.is_empty() {
193+
return Err(LocalNodeError::BlobsNotFound(blobs_not_found));
194+
}
195+
Ok(blob_states)
196+
}
197+
173198
/// Looks for the specified blobs in the local chain manager's locking blobs.
174199
/// Returns `Ok(None)` if any of the blobs is not found.
175200
pub async fn get_locking_blobs(

linera-core/src/unit_tests/test_utils.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -588,13 +588,19 @@ where
588588
sender: oneshot::Sender<Result<CryptoHash, NodeError>>,
589589
) -> Result<(), Result<CryptoHash, NodeError>> {
590590
let validator = self.client.lock().await;
591-
let certificate_hash = validator
591+
let blob_state = validator
592592
.state
593593
.storage_client()
594594
.read_blob_state(blob_id)
595595
.await
596-
.map(|blob_state| blob_state.last_used_by)
597596
.map_err(Into::into);
597+
let certificate_hash = match blob_state {
598+
Err(err) => Err(err),
599+
Ok(blob_state) => match blob_state {
600+
None => Err(NodeError::BlobsNotFound(vec![blob_id])),
601+
Some(blob_state) => Ok(blob_state.last_used_by),
602+
},
603+
};
598604

599605
sender.send(certificate_hash)
600606
}

linera-core/src/updater.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -317,8 +317,10 @@ where
317317
.node
318318
.missing_blob_ids(mem::take(&mut blob_ids))
319319
.await?;
320-
let local_storage = self.local_node.storage_client();
321-
let blob_states = local_storage.read_blob_states(&missing_blob_ids).await?;
320+
let blob_states = self
321+
.local_node
322+
.read_blob_states_from_storage(&missing_blob_ids)
323+
.await?;
322324
let mut chain_heights = BTreeMap::new();
323325
for blob_state in blob_states {
324326
let block_chain_id = blob_state.chain_id;

linera-execution/src/test_utils/solidity.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,10 +104,10 @@ pub fn load_solidity_example(path: &str) -> anyhow::Result<Vec<u8>> {
104104
.lines()
105105
.filter_map(|line| line.trim_start().strip_prefix("contract "))
106106
.next()
107-
.ok_or(anyhow::anyhow!("Not matching"))?;
107+
.ok_or_else(|| anyhow::anyhow!("Not matching"))?;
108108
let contract_name: &str = contract_name
109109
.strip_suffix(" {")
110-
.ok_or(anyhow::anyhow!("Not matching"))?;
110+
.ok_or_else(|| anyhow::anyhow!("Not matching"))?;
111111
get_bytecode(&source_code, contract_name)
112112
}
113113

linera-service/src/cli/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1325,7 +1325,7 @@ impl ClientOptions {
13251325
}
13261326

13271327
fn config_path(&self) -> Result<PathBuf, Error> {
1328-
let mut config_dir = dirs::config_dir().ok_or(anyhow!(
1328+
let mut config_dir = dirs::config_dir().ok_or_else(|| anyhow!(
13291329
"Default wallet directory is not supported in this platform: please specify storage and wallet paths"
13301330
))?;
13311331
config_dir.push("linera");

linera-service/src/proxy/grpc.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -473,9 +473,7 @@ where
473473
.read_network_description()
474474
.await
475475
.map_err(Self::error_to_status)?
476-
.ok_or(Status::not_found(
477-
"Cannot find network description in the database",
478-
))?;
476+
.ok_or_else(|| Status::not_found("Cannot find network description in the database"))?;
479477
Ok(Response::new(description.into()))
480478
}
481479

@@ -504,7 +502,7 @@ where
504502
.read_blob(blob_id)
505503
.await
506504
.map_err(Self::error_to_status)?;
507-
let blob = blob.ok_or(Status::not_found(format!("Blob not found {}", blob_id)))?;
505+
let blob = blob.ok_or_else(|| Status::not_found(format!("Blob not found {}", blob_id)))?;
508506
Ok(Response::new(blob.into_content().try_into()?))
509507
}
510508

@@ -626,6 +624,8 @@ where
626624
.read_blob_state(blob_id)
627625
.await
628626
.map_err(Self::error_to_status)?;
627+
let blob_state =
628+
blob_state.ok_or_else(|| Status::not_found(format!("Blob not found {}", blob_id)))?;
629629
Ok(Response::new(blob_state.last_used_by.into()))
630630
}
631631

linera-service/src/proxy/main.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ where
319319
.storage
320320
.read_network_description()
321321
.await?
322-
.ok_or(anyhow!("Cannot find network description in the database"))?;
322+
.ok_or_else(|| anyhow!("Cannot find network description in the database"))?;
323323
Ok(Some(RpcMessage::NetworkDescriptionResponse(Box::new(
324324
description,
325325
))))
@@ -335,7 +335,7 @@ where
335335
}
336336
DownloadBlob(blob_id) => {
337337
let blob = self.storage.read_blob(*blob_id).await?;
338-
let blob = blob.ok_or(anyhow!("Blob not found {}", blob_id))?;
338+
let blob = blob.ok_or_else(|| anyhow!("Blob not found {}", blob_id))?;
339339
let content = blob.into_content();
340340
Ok(Some(RpcMessage::DownloadBlobResponse(Box::new(content))))
341341
}
@@ -346,9 +346,13 @@ where
346346
let certificates = self.storage.read_certificates(hashes).await?;
347347
Ok(Some(RpcMessage::DownloadCertificatesResponse(certificates)))
348348
}
349-
BlobLastUsedBy(blob_id) => Ok(Some(RpcMessage::BlobLastUsedByResponse(Box::new(
350-
self.storage.read_blob_state(*blob_id).await?.last_used_by,
351-
)))),
349+
BlobLastUsedBy(blob_id) => {
350+
let blob_state = self.storage.read_blob_state(*blob_id).await?;
351+
let blob_state = blob_state.ok_or_else(|| anyhow!("Blob not found {}", blob_id))?;
352+
Ok(Some(RpcMessage::BlobLastUsedByResponse(Box::new(
353+
blob_state.last_used_by,
354+
))))
355+
}
352356
MissingBlobIds(blob_ids) => Ok(Some(RpcMessage::MissingBlobIdsResponse(
353357
self.storage.missing_blobs(&blob_ids).await?,
354358
))),

linera-storage/src/db_storage.rs

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -637,41 +637,35 @@ where
637637
.collect())
638638
}
639639

640-
async fn read_blob_state(&self, blob_id: BlobId) -> Result<BlobState, ViewError> {
640+
async fn read_blob_state(&self, blob_id: BlobId) -> Result<Option<BlobState>, ViewError> {
641641
let blob_state_key = bcs::to_bytes(&BaseKey::BlobState(blob_id))?;
642-
let maybe_blob_state = self.store.read_value::<BlobState>(&blob_state_key).await?;
642+
let blob_state = self.store.read_value::<BlobState>(&blob_state_key).await?;
643643
#[cfg(with_metrics)]
644644
metrics::READ_BLOB_STATE_COUNTER
645645
.with_label_values(&[])
646646
.inc();
647-
let blob_state = maybe_blob_state
648-
.ok_or_else(|| ViewError::not_found("blob state for blob ID", blob_id))?;
649647
Ok(blob_state)
650648
}
651649

652-
async fn read_blob_states(&self, blob_ids: &[BlobId]) -> Result<Vec<BlobState>, ViewError> {
650+
async fn read_blob_states(
651+
&self,
652+
blob_ids: &[BlobId],
653+
) -> Result<Vec<Option<BlobState>>, ViewError> {
653654
if blob_ids.is_empty() {
654655
return Ok(Vec::new());
655656
}
656657
let blob_state_keys = blob_ids
657658
.iter()
658659
.map(|blob_id| bcs::to_bytes(&BaseKey::BlobState(*blob_id)))
659660
.collect::<Result<_, _>>()?;
660-
let maybe_blob_states = self
661+
let blob_states = self
661662
.store
662663
.read_multi_values::<BlobState>(blob_state_keys)
663664
.await?;
664665
#[cfg(with_metrics)]
665666
metrics::READ_BLOB_STATES_COUNTER
666667
.with_label_values(&[])
667-
.inc();
668-
let blob_states = maybe_blob_states
669-
.into_iter()
670-
.zip(blob_ids)
671-
.map(|(blob_state, blob_id)| {
672-
blob_state.ok_or_else(|| ViewError::not_found("blob state for blob ID", blob_id))
673-
})
674-
.collect::<Result<_, _>>()?;
668+
.inc_by(blob_ids.len() as u64);
675669
Ok(blob_states)
676670
}
677671

@@ -705,14 +699,13 @@ where
705699
blob_id: BlobId,
706700
blob_state: BlobState,
707701
) -> Result<Epoch, ViewError> {
708-
let current_blob_state = self.read_blob_state(blob_id).await;
702+
let current_blob_state = self.read_blob_state(blob_id).await?;
709703
let (should_write, latest_epoch) = match current_blob_state {
710-
Ok(current_blob_state) => (
704+
Some(current_blob_state) => (
711705
current_blob_state.epoch < blob_state.epoch,
712706
current_blob_state.epoch.max(blob_state.epoch),
713707
),
714-
Err(ViewError::NotFound(_)) => (true, blob_state.epoch),
715-
Err(err) => return Err(err),
708+
None => (true, blob_state.epoch),
716709
};
717710

718711
if should_write {
@@ -856,7 +849,7 @@ where
856849
#[cfg(with_metrics)]
857850
metrics::READ_CERTIFICATES_COUNTER
858851
.with_label_values(&[])
859-
.inc();
852+
.inc_by(hashes.len() as u64);
860853
}
861854
let values = values?;
862855
let mut certificates = Vec::new();
@@ -869,9 +862,10 @@ where
869862

870863
async fn read_event(&self, event_id: EventId) -> Result<Option<Vec<u8>>, ViewError> {
871864
let event_key = bcs::to_bytes(&BaseKey::Event(event_id.clone()))?;
865+
let event = self.store.read_value_bytes(&event_key).await?;
872866
#[cfg(with_metrics)]
873867
metrics::READ_EVENT_COUNTER.with_label_values(&[]).inc();
874-
Ok(self.store.read_value_bytes(&event_key).await?)
868+
Ok(event)
875869
}
876870

877871
async fn contains_event(&self, event_id: EventId) -> Result<bool, ViewError> {

linera-storage/src/lib.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,13 @@ pub trait Storage: Sized {
9090
async fn read_blobs(&self, blob_ids: &[BlobId]) -> Result<Vec<Option<Blob>>, ViewError>;
9191

9292
/// Reads the blob state with the given blob ID.
93-
async fn read_blob_state(&self, blob_id: BlobId) -> Result<BlobState, ViewError>;
93+
async fn read_blob_state(&self, blob_id: BlobId) -> Result<Option<BlobState>, ViewError>;
9494

9595
/// Reads the blob states with the given blob IDs.
96-
async fn read_blob_states(&self, blob_ids: &[BlobId]) -> Result<Vec<BlobState>, ViewError>;
96+
async fn read_blob_states(
97+
&self,
98+
blob_ids: &[BlobId],
99+
) -> Result<Vec<Option<BlobState>>, ViewError>;
97100

98101
/// Reads the hashed certificate values in descending order from the given hash.
99102
async fn read_confirmed_blocks_downward(

0 commit comments

Comments
 (0)