1#![cfg(target_os = "linux")]
19#![doc = include_str!("../README.md")]
20#![cfg_attr(docsrs, feature(doc_cfg))]
21#![cfg_attr(docsrs, doc(auto_cfg))]
22#![deny(missing_docs)]
23use std::ffi::CString;
24use std::sync::Arc;
25
26use bytes::Buf;
27use opendal_core::raw::*;
28use opendal_core::*;
29use probe::probe_lazy;
30
31#[derive(Clone, Debug, Default)]
128#[non_exhaustive]
129pub struct DtraceLayer {}
130
131impl DtraceLayer {
132 pub fn new() -> Self {
134 Self::default()
135 }
136}
137
138impl Layer for DtraceLayer {
139 fn apply_service(&self, inner: Servicer) -> Servicer {
140 Arc::new(self.layer(inner))
141 }
142}
143
144impl DtraceLayer {
145 fn layer(&self, inner: Servicer) -> DTraceService {
146 DTraceService { inner }
147 }
148}
149
150#[doc(hidden)]
151#[derive(Debug)]
152pub struct DTraceService {
153 inner: Servicer,
154}
155
156impl Service for DTraceService {
157 type Reader = DtraceLayerWrapper<oio::Reader>;
158 type Writer = DtraceLayerWrapper<oio::Writer>;
159 type Lister = oio::Lister;
160 type Deleter = oio::Deleter;
161 type Copier = oio::Copier;
162
163 fn info(&self) -> ServiceInfo {
164 self.inner.info()
165 }
166
167 fn capability(&self) -> Capability {
168 self.inner.capability()
169 }
170
171 async fn create_dir(
172 &self,
173 ctx: &OperationContext,
174 path: &str,
175 args: OpCreateDir,
176 ) -> Result<RpCreateDir> {
177 let c_path = CString::new(path).unwrap();
178 probe_lazy!(opendal, create_dir_start, c_path.as_ptr());
179 let result = self.inner.create_dir(ctx, path, args).await;
180 probe_lazy!(opendal, create_dir_end, c_path.as_ptr());
181 result
182 }
183
184 fn read(&self, ctx: &OperationContext, path: &str, args: OpRead) -> Result<Self::Reader> {
185 let c_path = CString::new(path).unwrap();
186 probe_lazy!(opendal, read_start, c_path.as_ptr());
187 let result = self
188 .inner
189 .read(ctx, path, args)
190 .map(|r| DtraceLayerWrapper::new(r, path));
191 probe_lazy!(opendal, read_end, c_path.as_ptr());
192 result
193 }
194
195 fn write(&self, ctx: &OperationContext, path: &str, args: OpWrite) -> Result<Self::Writer> {
196 let c_path = CString::new(path).unwrap();
197 probe_lazy!(opendal, write_start, c_path.as_ptr());
198 let result = self
199 .inner
200 .write(ctx, path, args)
201 .map(|r| DtraceLayerWrapper::new(r, path));
202
203 probe_lazy!(opendal, write_end, c_path.as_ptr());
204 result
205 }
206
207 fn copy(
208 &self,
209 ctx: &OperationContext,
210 from: &str,
211 to: &str,
212 args: OpCopy,
213 opts: OpCopier,
214 ) -> Result<Self::Copier> {
215 let c_from = CString::new(from).unwrap();
216 probe_lazy!(opendal, copy_start, c_from.as_ptr());
217 let result = self.inner.copy(ctx, from, to, args, opts);
218 probe_lazy!(opendal, copy_end, c_from.as_ptr());
219 result
220 }
221
222 async fn rename(
223 &self,
224 ctx: &OperationContext,
225 from: &str,
226 to: &str,
227 args: OpRename,
228 ) -> Result<RpRename> {
229 self.inner.rename(ctx, from, to, args).await
230 }
231
232 async fn stat(&self, ctx: &OperationContext, path: &str, args: OpStat) -> Result<RpStat> {
233 let c_path = CString::new(path).unwrap();
234 probe_lazy!(opendal, stat_start, c_path.as_ptr());
235 let result = self.inner.stat(ctx, path, args).await;
236 probe_lazy!(opendal, stat_end, c_path.as_ptr());
237 result
238 }
239
240 fn delete(&self, ctx: &OperationContext) -> Result<Self::Deleter> {
241 self.inner.delete(ctx)
242 }
243
244 fn list(&self, ctx: &OperationContext, path: &str, args: OpList) -> Result<Self::Lister> {
245 let c_path = CString::new(path).unwrap();
246 probe_lazy!(opendal, list_start, c_path.as_ptr());
247 let result = self.inner.list(ctx, path, args);
248 probe_lazy!(opendal, list_end, c_path.as_ptr());
249 result
250 }
251
252 async fn presign(
253 &self,
254 ctx: &OperationContext,
255 path: &str,
256 args: OpPresign,
257 ) -> Result<RpPresign> {
258 let c_path = CString::new(path).unwrap();
259 probe_lazy!(opendal, presign_start, c_path.as_ptr());
260 let result = self.inner.presign(ctx, path, args).await;
261 probe_lazy!(opendal, presign_end, c_path.as_ptr());
262 result
263 }
264}
265
266#[doc(hidden)]
267pub struct DtraceLayerWrapper<R> {
268 inner: R,
269 path: String,
270 range: Option<BytesRange>,
271}
272
273impl<R> DtraceLayerWrapper<R> {
274 fn new(inner: R, path: &str) -> Self {
275 Self::with_range(inner, path, None)
276 }
277
278 fn with_range(inner: R, path: &str, range: Option<BytesRange>) -> Self {
279 Self {
280 inner,
281 path: path.to_string(),
282 range,
283 }
284 }
285
286 fn range_label(&self) -> String {
287 self.range
288 .map(|range| range.to_string())
289 .unwrap_or_default()
290 }
291}
292
293impl<R: oio::ReadStream> oio::ReadStream for DtraceLayerWrapper<R> {
294 async fn read(&mut self) -> Result<Buffer> {
295 let c_path = CString::new(self.path.clone()).unwrap();
296 let c_range = CString::new(self.range_label()).unwrap();
297 probe_lazy!(
298 opendal,
299 reader_read_start,
300 c_path.as_ptr(),
301 c_range.as_ptr()
302 );
303 match self.inner.read().await {
304 Ok(bs) => {
305 probe_lazy!(
306 opendal,
307 reader_read_ok,
308 c_path.as_ptr(),
309 c_range.as_ptr(),
310 bs.remaining()
311 );
312 Ok(bs)
313 }
314 Err(e) => {
315 probe_lazy!(
316 opendal,
317 reader_read_error,
318 c_path.as_ptr(),
319 c_range.as_ptr()
320 );
321 Err(e)
322 }
323 }
324 }
325}
326
327impl<R: oio::Read> oio::Read for DtraceLayerWrapper<R> {
328 async fn open(&self, range: BytesRange) -> Result<(RpRead, Box<dyn oio::ReadStreamDyn>)> {
329 let c_path = CString::new(self.path.clone()).unwrap();
330 let c_range = CString::new(range.to_string()).unwrap();
331 probe_lazy!(
332 opendal,
333 reader_read_start,
334 c_path.as_ptr(),
335 c_range.as_ptr()
336 );
337 match self.inner.open(range).await {
338 Ok((rp, stream)) => {
339 probe_lazy!(
340 opendal,
341 reader_read_ok,
342 c_path.as_ptr(),
343 c_range.as_ptr(),
344 0
345 );
346 Ok((
347 rp,
348 Box::new(DtraceLayerWrapper::with_range(
349 stream,
350 &self.path,
351 Some(range),
352 )) as Box<dyn oio::ReadStreamDyn>,
353 ))
354 }
355 Err(e) => {
356 probe_lazy!(
357 opendal,
358 reader_read_error,
359 c_path.as_ptr(),
360 c_range.as_ptr()
361 );
362 Err(e)
363 }
364 }
365 }
366
367 async fn read(&self, range: BytesRange) -> Result<(RpRead, Buffer)> {
368 let c_path = CString::new(self.path.clone()).unwrap();
369 let c_range = CString::new(range.to_string()).unwrap();
370 probe_lazy!(
371 opendal,
372 reader_read_start,
373 c_path.as_ptr(),
374 c_range.as_ptr()
375 );
376 match self.inner.read(range).await {
377 Ok((rp, buffer)) => {
378 probe_lazy!(
379 opendal,
380 reader_read_ok,
381 c_path.as_ptr(),
382 c_range.as_ptr(),
383 buffer.len()
384 );
385 Ok((rp, buffer))
386 }
387 Err(e) => {
388 probe_lazy!(
389 opendal,
390 reader_read_error,
391 c_path.as_ptr(),
392 c_range.as_ptr()
393 );
394 Err(e)
395 }
396 }
397 }
398}
399
400impl<R: oio::Write> oio::Write for DtraceLayerWrapper<R> {
401 async fn write(&mut self, bs: Buffer) -> Result<()> {
402 let c_path = CString::new(self.path.clone()).unwrap();
403 probe_lazy!(opendal, writer_write_start, c_path.as_ptr());
404 self.inner
405 .write(bs)
406 .await
407 .map(|_| {
408 probe_lazy!(opendal, writer_write_ok, c_path.as_ptr());
409 })
410 .inspect_err(|_| {
411 probe_lazy!(opendal, writer_write_error, c_path.as_ptr());
412 })
413 }
414
415 async fn abort(&mut self) -> Result<()> {
416 let c_path = CString::new(self.path.clone()).unwrap();
417 probe_lazy!(opendal, writer_poll_abort_start, c_path.as_ptr());
418 self.inner
419 .abort()
420 .await
421 .map(|_| {
422 probe_lazy!(opendal, writer_poll_abort_ok, c_path.as_ptr());
423 })
424 .inspect_err(|_| {
425 probe_lazy!(opendal, writer_poll_abort_error, c_path.as_ptr());
426 })
427 }
428
429 async fn close(&mut self) -> Result<Metadata> {
430 let c_path = CString::new(self.path.clone()).unwrap();
431 probe_lazy!(opendal, writer_close_start, c_path.as_ptr());
432 self.inner
433 .close()
434 .await
435 .inspect(|_| {
436 probe_lazy!(opendal, writer_close_ok, c_path.as_ptr());
437 })
438 .inspect_err(|_| {
439 probe_lazy!(opendal, writer_close_error, c_path.as_ptr());
440 })
441 }
442}