1use crate::Result;
7use async_trait::async_trait;
8use bytes::Bytes;
9use futures::stream::BoxStream;
10use futures::{StreamExt, TryStreamExt};
11use object_store::path::Path;
12use object_store::{
13 CopyOptions, Error as OSError, GetOptions, GetResult, ListResult, MultipartUpload, ObjectMeta,
14 ObjectStore, PutMultipartOptions, PutOptions, PutPayload, PutResult, RenameOptions,
15 Result as OSResult,
16};
17use std::collections::HashMap;
18use std::fmt::Debug;
19use std::future;
20use std::ops::Range;
21use std::pin::Pin;
22use std::sync::{
23 Arc, Mutex,
24 atomic::{AtomicUsize, Ordering},
25};
26
27pub trait PolicyFnT: Fn(&str, &Path) -> Result<()> + Send + Sync {}
30impl<F> PolicyFnT for F where F: Fn(&str, &Path) -> Result<()> + Send + Sync {}
31impl Debug for dyn PolicyFnT {
32 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
33 write!(f, "PolicyFn")
34 }
35}
36type PolicyFn = Arc<dyn PolicyFnT>;
37
38pub trait ObjectMetaPolicyFnT: Fn(&str, ObjectMeta) -> Result<ObjectMeta> + Send + Sync {}
41impl<F> ObjectMetaPolicyFnT for F where F: Fn(&str, ObjectMeta) -> Result<ObjectMeta> + Send + Sync {}
42impl Debug for dyn ObjectMetaPolicyFnT {
43 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
44 write!(f, "PolicyFn")
45 }
46}
47type ObjectMetaPolicyFn = Arc<dyn ObjectMetaPolicyFnT>;
48
49#[derive(Debug, Default)]
58pub struct ProxyObjectStorePolicy {
59 before_policies: HashMap<String, PolicyFn>,
63 object_meta_policies: HashMap<String, ObjectMetaPolicyFn>,
66}
67
68impl ProxyObjectStorePolicy {
69 pub fn new() -> Self {
70 Default::default()
71 }
72
73 pub fn set_before_policy(&mut self, name: &str, policy: PolicyFn) {
77 self.before_policies.insert(name.to_string(), policy);
78 }
79
80 pub fn clear_before_policy(&mut self, name: &str) {
81 self.before_policies.remove(name);
82 }
83
84 pub fn set_obj_meta_policy(&mut self, name: &str, policy: ObjectMetaPolicyFn) {
85 self.object_meta_policies.insert(name.to_string(), policy);
86 }
87}
88
89#[derive(Debug)]
95pub struct ProxyObjectStore {
96 target: Arc<dyn ObjectStore>,
97 policy: Arc<Mutex<ProxyObjectStorePolicy>>,
98}
99
100impl ProxyObjectStore {
101 pub fn new(target: Arc<dyn ObjectStore>, policy: Arc<Mutex<ProxyObjectStorePolicy>>) -> Self {
102 Self { target, policy }
103 }
104
105 fn before_method(&self, method: &str, location: &Path) -> OSResult<()> {
106 let policy = self.policy.lock().unwrap();
107 for policy in policy.before_policies.values() {
108 policy(method, location).map_err(OSError::from)?;
109 }
110 Ok(())
111 }
112
113 fn transform_meta(&self, method: &str, meta: ObjectMeta) -> OSResult<ObjectMeta> {
114 let policy = self.policy.lock().unwrap();
115 let mut meta = meta;
116 for policy in policy.object_meta_policies.values() {
117 meta = policy(method, meta).map_err(OSError::from)?;
118 }
119 Ok(meta)
120 }
121}
122
123impl std::fmt::Display for ProxyObjectStore {
124 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
125 write!(f, "ProxyObjectStore({})", self.target)
126 }
127}
128
129#[derive(Debug)]
134pub struct CountingObjectStore {
135 target: Arc<dyn ObjectStore>,
136 listing_count: Arc<AtomicUsize>,
137}
138
139impl CountingObjectStore {
140 pub fn new(target: Arc<dyn ObjectStore>, listing_count: Arc<AtomicUsize>) -> Self {
141 Self {
142 target,
143 listing_count,
144 }
145 }
146
147 fn record_listing(&self) {
148 self.listing_count.fetch_add(1, Ordering::SeqCst);
149 }
150
151 fn delegate_list(
152 &self,
153 prefix: Option<&Path>,
154 ) -> Pin<Box<dyn futures::Stream<Item = OSResult<ObjectMeta>> + Send>> {
155 self.target.list(prefix)
156 }
157}
158
159impl std::fmt::Display for CountingObjectStore {
160 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
161 write!(f, "CountingObjectStore({})", self.target)
162 }
163}
164
165#[async_trait]
166impl ObjectStore for ProxyObjectStore {
167 async fn put_opts(
168 &self,
169 location: &Path,
170 bytes: PutPayload,
171 opts: PutOptions,
172 ) -> OSResult<PutResult> {
173 self.before_method("put", location)?;
174 self.target.put_opts(location, bytes, opts).await
175 }
176
177 async fn put_multipart_opts(
178 &self,
179 location: &Path,
180 opts: PutMultipartOptions,
181 ) -> OSResult<Box<dyn MultipartUpload>> {
182 self.before_method("put_multipart", location)?;
183 self.target.put_multipart_opts(location, opts).await
184 }
185
186 async fn get_opts(&self, location: &Path, options: GetOptions) -> OSResult<GetResult> {
187 self.before_method("get_opts", location)?;
188 let is_head = options.head;
189 let mut result = self.target.get_opts(location, options).await?;
190 if is_head {
191 result.meta = self.transform_meta("head", result.meta)?;
192 }
193 Ok(result)
194 }
195
196 async fn get_ranges(&self, location: &Path, ranges: &[Range<u64>]) -> OSResult<Vec<Bytes>> {
197 self.before_method("get_ranges", location)?;
198 self.target.get_ranges(location, ranges).await
199 }
200
201 fn delete_stream(
202 &self,
203 locations: BoxStream<'static, OSResult<Path>>,
204 ) -> BoxStream<'static, OSResult<Path>> {
205 let policy = Arc::clone(&self.policy);
206 let checked = locations
207 .and_then(move |location| {
208 let result = {
209 let policy = policy.lock().unwrap();
210 policy
211 .before_policies
212 .values()
213 .try_for_each(|policy| policy("delete", &location).map_err(OSError::from))
214 };
215 future::ready(result.map(|_| location))
216 })
217 .boxed();
218 self.target.delete_stream(checked)
219 }
220
221 fn list(&self, prefix: Option<&Path>) -> BoxStream<'static, OSResult<ObjectMeta>> {
222 if let Err(error) = self.before_method("list", prefix.unwrap_or(&Path::default())) {
223 return futures::stream::once(future::ready(Err(error))).boxed();
224 }
225 let target = self.target.clone();
226 let policy = Arc::clone(&self.policy);
227
228 target
229 .list(prefix)
230 .and_then(move |meta| {
231 let policy = policy.lock().unwrap();
232 let mut meta = meta;
233 for p in policy.object_meta_policies.values() {
234 meta = p("list", meta).map_err(OSError::from).unwrap();
235 }
236 future::ready(Ok(meta))
237 })
238 .boxed()
239 }
240
241 async fn list_with_delimiter(&self, prefix: Option<&Path>) -> OSResult<ListResult> {
242 self.target.list_with_delimiter(prefix).await
243 }
244
245 async fn copy_opts(&self, from: &Path, to: &Path, opts: CopyOptions) -> OSResult<()> {
246 self.before_method("copy", from)?;
247 self.target.copy_opts(from, to, opts).await
248 }
249
250 async fn rename_opts(&self, from: &Path, to: &Path, opts: RenameOptions) -> OSResult<()> {
251 self.before_method("rename", from)?;
252 self.target.rename_opts(from, to, opts).await
253 }
254}
255
256#[async_trait]
257impl ObjectStore for CountingObjectStore {
258 async fn put_opts(
259 &self,
260 location: &Path,
261 bytes: PutPayload,
262 opts: PutOptions,
263 ) -> OSResult<PutResult> {
264 self.target.put_opts(location, bytes, opts).await
265 }
266
267 async fn put_multipart_opts(
268 &self,
269 location: &Path,
270 opts: PutMultipartOptions,
271 ) -> OSResult<Box<dyn MultipartUpload>> {
272 self.target.put_multipart_opts(location, opts).await
273 }
274
275 async fn get_opts(&self, location: &Path, options: GetOptions) -> OSResult<GetResult> {
276 self.target.get_opts(location, options).await
277 }
278
279 async fn get_ranges(&self, location: &Path, ranges: &[Range<u64>]) -> OSResult<Vec<Bytes>> {
280 self.target.get_ranges(location, ranges).await
281 }
282
283 fn delete_stream(
284 &self,
285 locations: BoxStream<'static, OSResult<Path>>,
286 ) -> BoxStream<'static, OSResult<Path>> {
287 self.target.delete_stream(locations)
288 }
289
290 fn list(&self, prefix: Option<&Path>) -> BoxStream<'static, OSResult<ObjectMeta>> {
291 self.record_listing();
292 self.delegate_list(prefix).boxed()
293 }
294
295 async fn list_with_delimiter(&self, prefix: Option<&Path>) -> OSResult<ListResult> {
296 self.record_listing();
297 self.target.list_with_delimiter(prefix).await
298 }
299
300 async fn copy_opts(&self, from: &Path, to: &Path, opts: CopyOptions) -> OSResult<()> {
301 self.target.copy_opts(from, to, opts).await
302 }
303}