1use super::MemoryIO;
2use crate::{Clock, Completion, File, Instant, LimboError, OpenFlags, Result, IO};
3use std::cell::RefCell;
4use std::io::{Read, Seek, Write};
5use std::sync::Arc;
6use tracing::{debug, trace};
7
8pub struct GenericIO {}
9
10impl GenericIO {
11 pub fn new() -> Result<Self> {
12 debug!("Using IO backend 'generic'");
13 Ok(Self {})
14 }
15}
16
17unsafe impl Send for GenericIO {}
18unsafe impl Sync for GenericIO {}
19
20impl IO for GenericIO {
21 fn open_file(&self, path: &str, flags: OpenFlags, _direct: bool) -> Result<Arc<dyn File>> {
22 trace!("open_file(path = {})", path);
23 let mut file = std::fs::File::options();
24 file.read(true);
25
26 if !flags.contains(OpenFlags::ReadOnly) {
27 file.write(true);
28 file.create(flags.contains(OpenFlags::Create));
29 }
30
31 let file = file.open(path)?;
32 Ok(Arc::new(GenericFile {
33 file: RefCell::new(file),
34 }))
35 }
36
37 fn wait_for_completion(&self, c: Arc<Completion>) -> Result<()> {
38 while !c.is_completed() {
39 self.run_once()?;
40 }
41 Ok(())
42 }
43
44 fn run_once(&self) -> Result<()> {
45 Ok(())
46 }
47
48 fn generate_random_number(&self) -> i64 {
49 let mut buf = [0u8; 8];
50 getrandom::fill(&mut buf).expect("getrandom failed");
51 i64::from_ne_bytes(buf)
52 }
53
54 fn get_memory_io(&self) -> Arc<MemoryIO> {
55 Arc::new(MemoryIO::new())
56 }
57}
58
59impl Clock for GenericIO {
60 fn now(&self) -> Instant {
61 let now = chrono::Local::now();
62 Instant {
63 secs: now.timestamp(),
64 micros: now.timestamp_subsec_micros(),
65 }
66 }
67}
68
69pub struct GenericFile {
70 file: RefCell<std::fs::File>,
71}
72
73unsafe impl Send for GenericFile {}
74unsafe impl Sync for GenericFile {}
75
76impl File for GenericFile {
77 fn lock_file(&self, _exclusive: bool) -> Result<()> {
80 Ok(())
81 }
82
83 fn unlock_file(&self) -> Result<()> {
84 Ok(())
85 }
86
87 fn pread(&self, pos: usize, c: Arc<Completion>) -> Result<()> {
88 let mut file = self.file.borrow_mut();
89 file.seek(std::io::SeekFrom::Start(pos as u64))?;
90 {
91 let r = match *c {
92 Completion::Read(ref r) => r,
93 _ => unreachable!(),
94 };
95 let mut buf = r.buf_mut();
96 let buf = buf.as_mut_slice();
97 file.read_exact(buf)?;
98 }
99 c.complete(0);
100 Ok(())
101 }
102
103 fn pwrite(
104 &self,
105 pos: usize,
106 buffer: Arc<RefCell<crate::Buffer>>,
107 c: Arc<Completion>,
108 ) -> Result<()> {
109 let mut file = self.file.borrow_mut();
110 file.seek(std::io::SeekFrom::Start(pos as u64))?;
111 let buf = buffer.borrow();
112 let buf = buf.as_slice();
113 file.write_all(buf)?;
114 c.complete(buf.len() as i32);
115 Ok(())
116 }
117
118 fn sync(&self, c: Arc<Completion>) -> Result<()> {
119 let file = self.file.borrow_mut();
120 file.sync_all().map_err(LimboError::IOError)?;
121 c.complete(0);
122 Ok(())
123 }
124
125 fn size(&self) -> Result<u64> {
126 let file = self.file.borrow();
127 Ok(file.metadata()?.len())
128 }
129
130 fn truncate(&self, len: usize, c: Arc<Completion>) -> Result<()> {
131 let file = self.file.borrow_mut();
132 file.set_len(len as u64).map_err(LimboError::IOError)?;
133 c.complete(0);
134 Ok(())
135 }
136}
137
138impl Drop for GenericFile {
139 fn drop(&mut self) {
140 self.unlock_file().expect("Failed to unlock file");
141 }
142}