From 11d7a673a7dcb214bcb273e1b33d6b1396e58adb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20Kr=C3=BCger?= Date: Wed, 14 Feb 2024 19:26:13 +0100 Subject: [PATCH] feat: Add `has_block` to `trait BlockStore` --- wnfs-common/src/blockstore.rs | 34 +++++++++++++++++++++++++++-- wnfs-common/src/utils/test.rs | 5 +++++ wnfs/examples/tiered_blockstores.rs | 8 +++++++ 3 files changed, 45 insertions(+), 2 deletions(-) diff --git a/wnfs-common/src/blockstore.rs b/wnfs-common/src/blockstore.rs index 81ec3c45..c683ad8c 100644 --- a/wnfs-common/src/blockstore.rs +++ b/wnfs-common/src/blockstore.rs @@ -50,14 +50,34 @@ pub const CODEC_RAW: u64 = 0x55; /// For types that implement block store operations like adding, getting content from the store. pub trait BlockStore: CondSync { + /// Retrieve a block from this store via its hash (`Cid`). + /// + /// If this store can't find the block, it may raise an error like `BlockNotFound`. fn get_block(&self, cid: &Cid) -> impl Future> + CondSend; + /// Put some bytes into the blockstore. These bytes should be encoded with the given codec. + /// + /// E.g. `CODEC_RAW` for raw bytes blocks, `CODEC_DAG_CBOR` for dag-cbor, etc. + /// + /// This codec will determine the codec encoded in the final `Cid` that's returned. + /// + /// If the codec is incorrect, this function won't fail, but any tools that depend on the + /// correctness of the codec may fail. (E.g. tools that follow the links of blocks). + /// + /// This funciton allows the blockstore to choose the hashing function itself. + /// The hashing function that was chosen will be readable from the `Cid` metadata. fn put_block( &self, bytes: impl Into + CondSend, codec: u64, ) -> impl Future> + CondSend; + /// Find out whether a call to `get_block` would return with a result or not. + /// + /// This is useful for data exchange protocols to find out what needs to be fetched + /// externally and what doesn't. + fn has_block(&self, cid: &Cid) -> impl Future> + CondSend; + // This should be the same in all implementations of BlockStore fn create_cid(&self, bytes: &[u8], codec: u64) -> Result { // If there are too many bytes, abandon this task @@ -88,6 +108,10 @@ impl BlockStore for &B { (**self).put_block(bytes, codec).await } + async fn has_block(&self, cid: &Cid) -> Result { + (**self).has_block(cid).await + } + fn create_cid(&self, bytes: &[u8], codec: u64) -> Result { (**self).create_cid(bytes, codec) } @@ -102,6 +126,10 @@ impl BlockStore for Box { (**self).put_block(bytes, codec).await } + async fn has_block(&self, cid: &Cid) -> Result { + (**self).has_block(cid).await + } + fn create_cid(&self, bytes: &[u8], codec: u64) -> Result { (**self).create_cid(bytes, codec) } @@ -126,7 +154,6 @@ impl MemoryBlockStore { } impl BlockStore for MemoryBlockStore { - /// Retrieves an array of bytes from the block store with given CID. async fn get_block(&self, cid: &Cid) -> Result { let bytes = self .0 @@ -138,7 +165,6 @@ impl BlockStore for MemoryBlockStore { Ok(bytes) } - /// Stores an array of bytes in the block store. async fn put_block(&self, bytes: impl Into + CondSend, codec: u64) -> Result { // Convert the bytes into a Bytes object let bytes: Bytes = bytes.into(); @@ -151,6 +177,10 @@ impl BlockStore for MemoryBlockStore { Ok(cid) } + + async fn has_block(&self, cid: &Cid) -> Result { + Ok(self.0.lock().contains_key(cid)) + } } //-------------------------------------------------------------------------------------------------- diff --git a/wnfs-common/src/utils/test.rs b/wnfs-common/src/utils/test.rs index 44d8a3b5..78994cc3 100644 --- a/wnfs-common/src/utils/test.rs +++ b/wnfs-common/src/utils/test.rs @@ -121,6 +121,11 @@ impl BlockStore for SnapshotBlockStore { async fn put_block(&self, bytes: impl Into + CondSend, codec: u64) -> Result { self.inner.put_block(bytes, codec).await } + + #[inline] + async fn has_block(&self, cid: &Cid) -> Result { + self.inner.has_block(cid).await + } } impl Sampleable for S diff --git a/wnfs/examples/tiered_blockstores.rs b/wnfs/examples/tiered_blockstores.rs index a46976bf..75d067db 100644 --- a/wnfs/examples/tiered_blockstores.rs +++ b/wnfs/examples/tiered_blockstores.rs @@ -108,4 +108,12 @@ impl BlockStore for TieredBlockStore { async fn put_block(&self, bytes: impl Into + CondSend, codec: u64) -> Result { self.hot.put_block(bytes.into(), codec).await } + + async fn has_block(&self, cid: &Cid) -> Result { + if self.hot.has_block(cid).await? { + return Ok(true); + } + + self.cold.has_block(cid).await + } }