1use std::ffi::CString;
19use std::fmt::Debug;
20use std::fmt::Formatter;
21
22use bytes::Buf;
23use probe::probe_lazy;
24
25use crate::raw::Access;
26use crate::raw::*;
27use crate::*;
28
29#[derive(Default, Debug, Clone)]
126pub struct DtraceLayer {}
127
128impl<A: Access> Layer<A> for DtraceLayer {
129 type LayeredAccess = DTraceAccessor<A>;
130 fn layer(&self, inner: A) -> Self::LayeredAccess {
131 DTraceAccessor { inner }
132 }
133}
134
135#[derive(Clone)]
136pub struct DTraceAccessor<A: Access> {
137 inner: A,
138}
139
140impl<A: Access> Debug for DTraceAccessor<A> {
141 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
142 f.debug_struct("DTraceAccessor")
143 .field("inner", &self.inner)
144 .finish_non_exhaustive()
145 }
146}
147
148impl<A: Access> LayeredAccess for DTraceAccessor<A> {
149 type Inner = A;
150 type Reader = DtraceLayerWrapper<A::Reader>;
151 type Writer = DtraceLayerWrapper<A::Writer>;
152 type Lister = A::Lister;
153 type Deleter = A::Deleter;
154
155 fn inner(&self) -> &Self::Inner {
156 &self.inner
157 }
158
159 async fn create_dir(&self, path: &str, args: OpCreateDir) -> Result<RpCreateDir> {
160 let c_path = CString::new(path).unwrap();
161 probe_lazy!(opendal, create_dir_start, c_path.as_ptr());
162 let result = self.inner.create_dir(path, args).await;
163 probe_lazy!(opendal, create_dir_end, c_path.as_ptr());
164 result
165 }
166
167 async fn read(&self, path: &str, args: OpRead) -> Result<(RpRead, Self::Reader)> {
168 let c_path = CString::new(path).unwrap();
169 probe_lazy!(opendal, read_start, c_path.as_ptr());
170 let result = self
171 .inner
172 .read(path, args)
173 .await
174 .map(|(rp, r)| (rp, DtraceLayerWrapper::new(r, &path.to_string())));
175 probe_lazy!(opendal, read_end, c_path.as_ptr());
176 result
177 }
178
179 async fn write(&self, path: &str, args: OpWrite) -> Result<(RpWrite, Self::Writer)> {
180 let c_path = CString::new(path).unwrap();
181 probe_lazy!(opendal, write_start, c_path.as_ptr());
182 let result = self
183 .inner
184 .write(path, args)
185 .await
186 .map(|(rp, r)| (rp, DtraceLayerWrapper::new(r, &path.to_string())));
187
188 probe_lazy!(opendal, write_end, c_path.as_ptr());
189 result
190 }
191
192 async fn stat(&self, path: &str, args: OpStat) -> Result<RpStat> {
193 let c_path = CString::new(path).unwrap();
194 probe_lazy!(opendal, stat_start, c_path.as_ptr());
195 let result = self.inner.stat(path, args).await;
196 probe_lazy!(opendal, stat_end, c_path.as_ptr());
197 result
198 }
199
200 async fn delete(&self) -> Result<(RpDelete, Self::Deleter)> {
201 self.inner.delete().await
202 }
203
204 async fn list(&self, path: &str, args: OpList) -> Result<(RpList, Self::Lister)> {
205 let c_path = CString::new(path).unwrap();
206 probe_lazy!(opendal, list_start, c_path.as_ptr());
207 let result = self.inner.list(path, args).await;
208 probe_lazy!(opendal, list_end, c_path.as_ptr());
209 result
210 }
211
212 async fn presign(&self, path: &str, args: OpPresign) -> Result<RpPresign> {
213 let c_path = CString::new(path).unwrap();
214 probe_lazy!(opendal, presign_start, c_path.as_ptr());
215 let result = self.inner.presign(path, args).await;
216 probe_lazy!(opendal, presign_end, c_path.as_ptr());
217 result
218 }
219}
220
221pub struct DtraceLayerWrapper<R> {
222 inner: R,
223 path: String,
224}
225
226impl<R> DtraceLayerWrapper<R> {
227 pub fn new(inner: R, path: &String) -> Self {
228 Self {
229 inner,
230 path: path.to_string(),
231 }
232 }
233}
234
235impl<R: oio::Read> oio::Read for DtraceLayerWrapper<R> {
236 async fn read(&mut self) -> Result<Buffer> {
237 let c_path = CString::new(self.path.clone()).unwrap();
238 probe_lazy!(opendal, reader_read_start, c_path.as_ptr());
239 match self.inner.read().await {
240 Ok(bs) => {
241 probe_lazy!(opendal, reader_read_ok, c_path.as_ptr(), bs.remaining());
242 Ok(bs)
243 }
244 Err(e) => {
245 probe_lazy!(opendal, reader_read_error, c_path.as_ptr());
246 Err(e)
247 }
248 }
249 }
250}
251
252impl<R: oio::Write> oio::Write for DtraceLayerWrapper<R> {
253 async fn write(&mut self, bs: Buffer) -> Result<()> {
254 let c_path = CString::new(self.path.clone()).unwrap();
255 probe_lazy!(opendal, writer_write_start, c_path.as_ptr());
256 self.inner
257 .write(bs)
258 .await
259 .map(|_| {
260 probe_lazy!(opendal, writer_write_ok, c_path.as_ptr());
261 })
262 .inspect_err(|_| {
263 probe_lazy!(opendal, writer_write_error, c_path.as_ptr());
264 })
265 }
266
267 async fn abort(&mut self) -> Result<()> {
268 let c_path = CString::new(self.path.clone()).unwrap();
269 probe_lazy!(opendal, writer_poll_abort_start, c_path.as_ptr());
270 self.inner
271 .abort()
272 .await
273 .map(|_| {
274 probe_lazy!(opendal, writer_poll_abort_ok, c_path.as_ptr());
275 })
276 .inspect_err(|_| {
277 probe_lazy!(opendal, writer_poll_abort_error, c_path.as_ptr());
278 })
279 }
280
281 async fn close(&mut self) -> Result<Metadata> {
282 let c_path = CString::new(self.path.clone()).unwrap();
283 probe_lazy!(opendal, writer_close_start, c_path.as_ptr());
284 self.inner
285 .close()
286 .await
287 .inspect(|_| {
288 probe_lazy!(opendal, writer_close_ok, c_path.as_ptr());
289 })
290 .inspect_err(|_| {
291 probe_lazy!(opendal, writer_close_error, c_path.as_ptr());
292 })
293 }
294}