bucky_objects/objects/object_map/
visitor.rs1use 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#[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
31pub 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
153pub 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 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 {}