graphforge_filesystem/
observation.rs1use std::fs::File;
3use std::io;
4use std::sync::atomic::{AtomicU64, AtomicUsize, Ordering};
5use std::time::Instant;
6
7static CAPTURES: AtomicUsize = AtomicUsize::new(0);
8static FSYNC_CALLS: AtomicU64 = AtomicU64::new(0);
9static FSYNC_NS: AtomicU64 = AtomicU64::new(0);
10
11#[derive(Debug)]
13pub struct Observation(());
14impl Observation {
15 #[must_use]
17 pub fn start() -> Self {
18 CAPTURES.fetch_add(1, Ordering::Relaxed);
19 Self(())
20 }
21}
22impl Drop for Observation {
23 fn drop(&mut self) {
24 CAPTURES.fetch_sub(1, Ordering::Relaxed);
25 }
26}
27#[must_use]
29pub fn active() -> bool {
30 CAPTURES.load(Ordering::Relaxed) != 0
31}
32#[must_use]
34pub fn fsync_totals() -> (u64, u64) {
35 (
36 FSYNC_CALLS.load(Ordering::Relaxed),
37 FSYNC_NS.load(Ordering::Relaxed),
38 )
39}
40
41pub trait ObservedSync {
43 fn observed_sync_all(&self) -> io::Result<()>;
45 fn observed_sync_data(&self) -> io::Result<()>;
47}
48impl ObservedSync for File {
49 fn observed_sync_all(&self) -> io::Result<()> {
50 observe(|| self.sync_all())
51 }
52 fn observed_sync_data(&self) -> io::Result<()> {
53 observe(|| self.sync_data())
54 }
55}
56fn observe(operation: impl FnOnce() -> io::Result<()>) -> io::Result<()> {
57 if !active() {
58 return operation();
59 }
60 let started = Instant::now();
61 let result = operation();
62 FSYNC_NS.fetch_add(
63 u64::try_from(started.elapsed().as_nanos()).unwrap_or(u64::MAX),
64 Ordering::Relaxed,
65 );
66 FSYNC_CALLS.fetch_add(1, Ordering::Relaxed);
67 result
68}