use crate::{io::clock::DefaultClock, Clock, Completion, File, Instant, OpenFlags, Result, IO}; use parking_lot::RwLock; use std::io::{Read, Seek, Write}; use std::sync::Arc; use tracing::{debug, instrument, trace, Level}; pub struct GenericIO {} impl GenericIO { pub fn new() -> Result { debug!("Using IO backend 'syscall'"); Ok(Self {}) } } impl IO for GenericIO { #[instrument(err, skip_all, level = Level::TRACE)] fn open_file(&self, path: &str, flags: OpenFlags, direct: bool) -> Result> { trace!("open_file(path = {})", path); let mut file = std::fs::File::options(); file.read(true); if !flags.contains(OpenFlags::ReadOnly) { file.write(true); file.create(flags.contains(OpenFlags::Create)); } let file = file.open(path)?; Ok(Arc::new(GenericFile { file: RwLock::new(file), })) } #[instrument(err, skip_all, level = Level::TRACE)] fn remove_file(&self, path: &str) -> Result<()> { trace!("remove_file(path = {})", path); Ok(std::fs::remove_file(path)?) } #[instrument(err, skip_all, level = Level::TRACE)] fn step(&self) -> Result<()> { Ok(()) } } impl Clock for GenericIO { fn now(&self) -> Instant { DefaultClock.now() } } pub struct GenericFile { file: RwLock, } impl File for GenericFile { #[instrument(err, skip_all, level = Level::TRACE)] fn lock_file(&self, exclusive: bool) -> Result<()> { Ok(()) } #[instrument(err, skip_all, level = Level::TRACE)] fn unlock_file(&self) -> Result<()> { Ok(()) } #[instrument(skip(self, c), level = Level::TRACE)] fn pread(&self, pos: u64, c: Completion) -> Result { let mut file = self.file.write(); file.seek(std::io::SeekFrom::Start(pos))?; let nr = { let r = c.as_read(); let buf = r.buf(); let buf = buf.as_mut_slice(); file.read_exact(buf)?; buf.len() as i32 }; c.complete(nr); Ok(c) } #[instrument(skip(self, c, buffer), level = Level::TRACE)] fn pwrite(&self, pos: u64, buffer: Arc, c: Completion) -> Result { let mut file = self.file.write(); file.seek(std::io::SeekFrom::Start(pos))?; let buf = buffer.as_slice(); file.write_all(buf)?; c.complete(buffer.len() as i32); Ok(c) } #[instrument(err, skip_all, level = Level::TRACE)] fn sync(&self, c: Completion) -> Result { let file = self.file.write(); file.sync_all()?; c.complete(0); Ok(c) } #[instrument(err, skip_all, level = Level::TRACE)] fn truncate(&self, len: u64, c: Completion) -> Result { let file = self.file.write(); file.set_len(len)?; c.complete(0); Ok(c) } fn size(&self) -> Result { let file = self.file.read(); Ok(file.metadata().unwrap().len()) } }