use fsys::observer::{
FsysObserver, HandleReadEvent, HandleWriteEvent, JournalAppendEvent, JournalSyncEvent,
};
use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::Arc;
#[derive(Debug, Default)]
struct CountingObserver {
appends: AtomicU64,
syncs: AtomicU64,
writes: AtomicU64,
reads: AtomicU64,
total_sync_nanos: AtomicU64,
}
impl FsysObserver for CountingObserver {
fn on_journal_append(&self, _: JournalAppendEvent) {
self.appends.fetch_add(1, Ordering::Relaxed);
}
fn on_journal_sync(&self, event: JournalSyncEvent) {
self.syncs.fetch_add(1, Ordering::Relaxed);
self.total_sync_nanos
.fetch_add(event.duration.as_nanos() as u64, Ordering::Relaxed);
}
fn on_handle_write(&self, _: HandleWriteEvent) {
self.writes.fetch_add(1, Ordering::Relaxed);
}
fn on_handle_read(&self, _: HandleReadEvent) {
self.reads.fetch_add(1, Ordering::Relaxed);
}
}
fn main() -> fsys::Result<()> {
let observer = Arc::new(CountingObserver::default());
let dyn_obs: Arc<dyn FsysObserver> = observer.clone();
let fs = Arc::new(fsys::builder().observer(dyn_obs).build()?);
println!("handle built with observer registered");
let path = std::env::temp_dir().join("fsys_example_observer_basics");
let _ = std::fs::remove_file(&path);
for i in 0..5 {
fs.write(&path, format!("content {i}").as_bytes())?;
}
for _ in 0..3 {
let _ = fs.read(&path)?;
}
let journal_path = std::env::temp_dir().join("fsys_example_observer_journal.wal");
let _ = std::fs::remove_file(&journal_path);
let log = fs.journal(&journal_path)?;
for i in 0..50 {
log.append(format!("entry {i}").as_bytes())?;
}
log.sync_through(log.next_lsn())?;
log.close()?;
println!();
println!("observer counters after activity:");
println!(
" journal appends: {} (expected 50)",
observer.appends.load(Ordering::Relaxed)
);
println!(
" journal syncs: {} (expected 1)",
observer.syncs.load(Ordering::Relaxed)
);
let total_sync = observer.total_sync_nanos.load(Ordering::Relaxed);
let sync_count = observer.syncs.load(Ordering::Relaxed).max(1);
println!(" avg sync latency: {} µs", total_sync / sync_count / 1000);
println!();
println!(
" handle writes: {} (Handle::write is not currently",
observer.writes.load(Ordering::Relaxed)
);
println!(
" handle reads: {} instrumented; the trait methods",
observer.reads.load(Ordering::Relaxed)
);
println!(" are reserved for a future release)");
let _ = std::fs::remove_file(&path);
let _ = std::fs::remove_file(&journal_path);
Ok(())
}