co_storage/storage/
links.rs1use crate::{BlockStorageContentMapping, ExtendedBlock, ExtendedBlockStorage};
5use async_trait::async_trait;
6use cid::Cid;
7use co_primitives::{
8 Block, BlockLinks, BlockStat, BlockStorage, BlockStorageCloneSettings, BlockStorageStoreParams,
9 CloneWithBlockStorageSettings, MappedCid, StorageError,
10};
11use std::collections::BTreeSet;
12
13#[derive(Debug, Default, Clone)]
15pub struct LinksBlockStorage<S> {
16 links: Option<BlockLinks>,
17 next: S,
18}
19impl<S> LinksBlockStorage<S> {
20 pub fn new(next: S, links: Option<BlockLinks>) -> Self {
21 Self { next, links }
22 }
23}
24#[async_trait]
25impl<S> BlockStorage for LinksBlockStorage<S>
26where
27 S: BlockStorage + 'static,
28{
29 async fn get(&self, cid: &Cid) -> Result<Block, StorageError> {
30 self.next.get(cid).await
31 }
32
33 async fn set(&self, block: Block) -> Result<Cid, StorageError> {
34 if let Some(block_links) = &self.links {
36 if block_links.has_links(block.cid()) {
37 let links = block_links.links(&block)?;
38 for link in links {
39 match self.next.get(&link).await {
40 Ok(_) => {},
41 Err(err) => {
42 let err = StorageError::InvalidArgument(anyhow::Error::from(err).context(format!(
43 "Create block failed: {} reference failed: {}",
44 block.cid(),
45 &link
46 )));
47 tracing::error!(?err, "create-block-failed");
48 return Err(err);
49 },
50 }
51 }
52 }
53 }
54
55 self.next.set(block).await
57 }
58
59 async fn stat(&self, cid: &Cid) -> Result<BlockStat, StorageError> {
60 self.next.stat(cid).await
61 }
62
63 async fn remove(&self, cid: &Cid) -> Result<(), StorageError> {
64 self.next.remove(cid).await
65 }
66
67 fn max_block_size(&self) -> usize {
68 self.next.max_block_size()
69 }
70}
71#[async_trait]
72impl<S> ExtendedBlockStorage for LinksBlockStorage<S>
73where
74 S: ExtendedBlockStorage + 'static,
75{
76 async fn set_extended(&self, block: ExtendedBlock) -> Result<Cid, StorageError> {
77 self.next.set_extended(block).await
78 }
79
80 async fn exists(&self, cid: &Cid) -> Result<bool, StorageError> {
81 self.next.exists(cid).await
82 }
83
84 async fn clear(&self) -> Result<(), StorageError> {
85 self.next.clear().await
86 }
87}
88#[async_trait]
89impl<S> BlockStorageContentMapping for LinksBlockStorage<S>
90where
91 S: BlockStorage + BlockStorageContentMapping + 'static,
92{
93 async fn is_content_mapped(&self) -> bool {
94 self.next.is_content_mapped().await
95 }
96
97 async fn to_plain(&self, mapped: &Cid) -> Option<Cid> {
98 self.next.to_plain(mapped).await
99 }
100
101 async fn to_mapped(&self, plain: &Cid) -> Option<Cid> {
102 self.next.to_mapped(plain).await
103 }
104
105 async fn insert_mappings(&self, mappings: BTreeSet<MappedCid>) {
106 self.next.insert_mappings(mappings).await
107 }
108}
109#[async_trait]
110impl<S> CloneWithBlockStorageSettings for LinksBlockStorage<S>
111where
112 S: BlockStorage + CloneWithBlockStorageSettings + 'static,
113{
114 fn clone_with_settings(&self, settings: BlockStorageCloneSettings) -> Self {
115 Self::new(self.next.clone_with_settings(settings), self.links.clone())
116 }
117}
118impl<S> BlockStorageStoreParams for LinksBlockStorage<S>
119where
120 S: BlockStorageStoreParams,
121{
122 type StoreParams = S::StoreParams;
123}