rustybit_lib/storage/
file_storage.rs1use std::fs::File;
2use std::io::ErrorKind;
3use std::os::unix::fs::FileExt;
4use std::path::PathBuf;
5
6use anyhow::Context;
7
8use super::{FileInfo, Storage};
9
10pub struct FileStorage {
11 files: Vec<(PathBuf, File)>,
12}
13
14impl FileStorage {
15 pub fn new(paths: &[FileInfo]) -> anyhow::Result<Self> {
16 let mut files = Vec::with_capacity(paths.len());
17 for file_info in paths.iter() {
18 std::fs::create_dir_all(
19 file_info
20 .path
21 .parent()
22 .with_context(|| format!("bug: a file with no parrent? {:?}", file_info.path))?,
23 )
24 .with_context(|| {
25 format!(
26 "error while creating parent directories for a file: {:?}",
27 file_info.path
28 )
29 })?;
30 let f = std::fs::OpenOptions::new()
31 .create(true)
32 .truncate(false)
33 .write(true)
34 .read(true)
35 .open(&file_info.path)
36 .with_context(|| format!("error while opening/creating a file: {:?}", file_info.path))?;
37
38 f.set_len(file_info.length).with_context(|| {
39 format!(
40 "error while setting the file's length: {:?}, {}",
41 file_info.path, file_info.length
42 )
43 })?;
44
45 files.push((file_info.path.clone(), f));
46 }
47 Ok(FileStorage { files })
48 }
49}
50
51impl Storage for FileStorage {
52 #[tracing::instrument(err, skip(self, buf))]
53 fn write_all(&mut self, file_idx: usize, offset: u64, buf: &[u8]) -> anyhow::Result<()> {
54 let file = &mut self
55 .files
56 .get(file_idx)
57 .map(|(_, file)| file)
58 .context("bug: non-existing file index?")?;
59 file.write_all_at(buf, offset)
60 .context("error while writing to the provided offset")?;
61
62 Ok(())
63 }
64
65 #[tracing::instrument(err, skip(self, buf))]
66 fn read_exact(&mut self, file_idx: usize, offset: u64, buf: &mut [u8]) -> anyhow::Result<bool> {
67 let file = &mut self
68 .files
69 .get(file_idx)
70 .map(|(_, file)| file)
71 .context("bug: non-existing file index?")?;
72 if let Err(e) = file.read_exact_at(buf, offset) {
73 match e.kind() {
74 ErrorKind::UnexpectedEof => return Ok(false),
75 _ => return Err(e).context("error while reading from file at the offset"),
76 }
77 };
78
79 Ok(true)
80 }
81}