bucky_objects/objects/object_map/
visitor.rs

1use super::object_map::*;
2use crate::*;
3
4use std::any::Any;
5use std::sync::Arc;
6
7#[async_trait::async_trait]
8pub trait ObjectMapVisitor: Send + Sync {
9    async fn visit_hub_item(&mut self, item: &ObjectId) -> BuckyResult<()>;
10    async fn visit_map_item(&mut self, key: &str, item: &ObjectId) -> BuckyResult<()>;
11    async fn visit_set_item(&mut self, item: &ObjectId) -> BuckyResult<()>;
12    async fn visit_diff_map_item(
13        &mut self,
14        key: &str,
15        item: &ObjectMapDiffMapItem,
16    ) -> BuckyResult<()>;
17    async fn visit_diff_set_item(&mut self, item: &ObjectMapDiffSetItem) -> BuckyResult<()>;
18}
19
20// objectmap loader for visitor, change the behavior for default cache(memory and noc, etc.)
21#[async_trait::async_trait]
22pub trait ObjectMapVisitLoader: Send + Sync {
23    fn into_any(self: Box<Self>) -> Box<dyn Any>;
24    async fn get_object_map(&mut self, id: &ObjectId) -> BuckyResult<Option<ObjectMapRef>>;
25}
26
27pub type ObjectMapVisitorRef = Arc<Box<dyn ObjectMapVisitor>>;
28
29pub trait ObjectMapVisitorProvider: ObjectMapVisitor + ObjectMapVisitLoader {}
30
31// visit objectmap's all leaf nodes and hub nodes
32pub struct ObjectMapFullVisitor {
33    provider: Box<dyn ObjectMapVisitorProvider>,
34    pending_items: std::collections::VecDeque<ObjectId>,
35}
36
37#[async_trait::async_trait]
38impl ObjectMapVisitor for ObjectMapFullVisitor {
39    async fn visit_hub_item(&mut self, item: &ObjectId) -> BuckyResult<()> {
40        self.pending_items.push_back(item.to_owned());
41
42        self.provider.visit_hub_item(item).await
43    }
44
45    async fn visit_map_item(&mut self, key: &str, item: &ObjectId) -> BuckyResult<()> {
46        self.provider.visit_map_item(key, item).await
47    }
48
49    async fn visit_set_item(&mut self, item: &ObjectId) -> BuckyResult<()> {
50        self.provider.visit_set_item(item).await
51    }
52
53    async fn visit_diff_map_item(
54        &mut self,
55        key: &str,
56        item: &ObjectMapDiffMapItem,
57    ) -> BuckyResult<()> {
58        self.provider.visit_diff_map_item(key, item).await
59    }
60
61    async fn visit_diff_set_item(&mut self, item: &ObjectMapDiffSetItem) -> BuckyResult<()> {
62        self.provider.visit_diff_set_item(item).await
63    }
64}
65
66#[async_trait::async_trait]
67impl ObjectMapVisitLoader for ObjectMapFullVisitor {
68    fn into_any(self: Box<Self>) -> Box<dyn Any> {
69        self
70    }
71    async fn get_object_map(&mut self, id: &ObjectId) -> BuckyResult<Option<ObjectMapRef>> {
72        self.provider.get_object_map(id).await
73    }
74}
75
76impl ObjectMapVisitorProvider for ObjectMapFullVisitor {}
77
78impl ObjectMapFullVisitor {
79    pub fn new(provider: Box<dyn ObjectMapVisitorProvider>) -> Self {
80        Self {
81            provider,
82            pending_items: std::collections::VecDeque::new(),
83        }
84    }
85
86    pub fn into_provider(self) -> Box<dyn ObjectMapVisitorProvider> {
87        self.provider
88    }
89
90    pub async fn visit(&mut self, target: &ObjectId) -> BuckyResult<()> {
91        self.pending_items.push_back(target.to_owned());
92
93        loop {
94            let cur = self.pending_items.pop_front();
95            if cur.is_none() {
96                break;
97            }
98
99            let cur = cur.unwrap();
100            let ret = self.provider.get_object_map(&cur).await?;
101            match ret {
102                Some(obj) => {
103                    let obj_item = obj.lock().await;
104                    debug!("will visit full item: {}", cur);
105                    obj_item.visit(self).await?;
106                }
107                None => {
108                    debug!("visit full item: but not found! {}", cur);
109                    continue;
110                }
111            }
112        }
113
114        Ok(())
115    }
116}
117
118pub struct ObjectMapDummyVisitor;
119
120impl ObjectMapDummyVisitor {
121    pub fn new() -> Self {
122        ObjectMapDummyVisitor {}
123    }
124}
125
126#[async_trait::async_trait]
127impl ObjectMapVisitor for ObjectMapDummyVisitor {
128    async fn visit_hub_item(&mut self, _item: &ObjectId) -> BuckyResult<()> {
129        Ok(())
130    }
131
132    async fn visit_map_item(&mut self, _key: &str, _item: &ObjectId) -> BuckyResult<()> {
133        Ok(())
134    }
135
136    async fn visit_set_item(&mut self, _item: &ObjectId) -> BuckyResult<()> {
137        Ok(())
138    }
139
140    async fn visit_diff_map_item(
141        &mut self,
142        _key: &str,
143        _item: &ObjectMapDiffMapItem,
144    ) -> BuckyResult<()> {
145        Ok(())
146    }
147
148    async fn visit_diff_set_item(&mut self, _item: &ObjectMapDiffSetItem) -> BuckyResult<()> {
149        Ok(())
150    }
151}
152
153// for objectmap path env, visitor for objectmap tree
154pub struct ObjectMapPathVisitor {
155    provider: Box<dyn ObjectMapVisitorProvider>,
156    pending_items: std::collections::VecDeque<ObjectMapRef>,
157}
158
159#[async_trait::async_trait]
160impl ObjectMapVisitor for ObjectMapPathVisitor {
161    async fn visit_hub_item(&mut self, item: &ObjectId) -> BuckyResult<()> {
162        self.pend_sub(item).await?;
163
164        self.provider.visit_hub_item(item).await
165    }
166
167    async fn visit_map_item(&mut self, key: &str, item: &ObjectId) -> BuckyResult<()> {
168        debug!(
169            "visit map item: {}={}, type={:?}",
170            key,
171            item,
172            item.obj_type_code()
173        );
174
175        if item.obj_type_code() == ObjectTypeCode::ObjectMap {
176            self.pend_sub(item).await?;
177        }
178
179        self.provider.visit_map_item(key, item).await
180    }
181
182    async fn visit_set_item(&mut self, item: &ObjectId) -> BuckyResult<()> {
183        debug!("visit set item: {}", item);
184
185        if item.obj_type_code() == ObjectTypeCode::ObjectMap {
186            self.pend_sub(item).await?;
187        }
188
189        self.provider.visit_set_item(item).await
190    }
191
192    async fn visit_diff_map_item(
193        &mut self,
194        key: &str,
195        item: &ObjectMapDiffMapItem,
196    ) -> BuckyResult<()> {
197        // expand sub diff item only
198        if let Some(id) = &item.diff {
199            self.pend_sub(id).await?;
200        }
201
202        self.provider.visit_diff_map_item(key, item).await
203    }
204
205    async fn visit_diff_set_item(&mut self, item: &ObjectMapDiffSetItem) -> BuckyResult<()> {
206        self.provider.visit_diff_set_item(item).await
207    }
208}
209
210impl ObjectMapPathVisitor {
211    pub fn new(provider: Box<dyn ObjectMapVisitorProvider>) -> Self {
212        Self {
213            provider,
214            pending_items: std::collections::VecDeque::new(),
215        }
216    }
217
218    async fn pend_sub(&mut self, id: &ObjectId) -> BuckyResult<()> {
219        assert_eq!(id.obj_type_code(), ObjectTypeCode::ObjectMap);
220
221        if let Some(item) = self.provider.get_object_map(&id).await? {
222            self.pending_items.push_back(item)
223        }
224
225        Ok(())
226    }
227
228    pub fn into_provider(self) -> Box<dyn ObjectMapVisitorProvider> {
229        self.provider
230    }
231
232    pub async fn visit(&mut self, target: &ObjectId) -> BuckyResult<()> {
233        self.pend_sub(target).await?;
234
235        loop {
236            let cur = self.pending_items.pop_front();
237            if cur.is_none() {
238                break;
239            }
240
241            let cur = cur.unwrap();
242
243            let obj_item = cur.lock().await;
244            debug!("will visit path item: {:?}", obj_item.cached_object_id());
245
246            obj_item.visit(self).await?;
247        }
248
249        Ok(())
250    }
251}
252
253#[async_trait::async_trait]
254impl ObjectMapVisitLoader for ObjectMapPathVisitor {
255    fn into_any(self: Box<Self>) -> Box<dyn Any> {
256        self
257    }
258    async fn get_object_map(&mut self, id: &ObjectId) -> BuckyResult<Option<ObjectMapRef>> {
259        self.provider.get_object_map(id).await
260    }
261}
262
263impl ObjectMapVisitorProvider for ObjectMapPathVisitor {}