libblobd_direct/backing_store/
file.rs

1use super::BackingStore;
2use crate::pages::Pages;
3use async_trait::async_trait;
4use bufpool::buf::Buf;
5use off64::usz;
6use std::fs::File;
7use std::os::unix::prelude::FileExt;
8use std::sync::Arc;
9use tokio::task::spawn_blocking;
10
11#[derive(Clone)]
12pub(crate) struct FileBackingStore {
13  file: Arc<File>,
14  pages: Pages,
15}
16
17impl FileBackingStore {
18  /// `offset` must be a multiple of the underlying device's sector size.
19  pub fn new(file: File, pages: Pages) -> Self {
20    Self {
21      file: Arc::new(file),
22      pages,
23    }
24  }
25}
26
27#[async_trait]
28impl BackingStore for FileBackingStore {
29  async fn read_at(&self, offset: u64, len: u64) -> Buf {
30    let mut buf = self.pages.allocate_uninitialised(len);
31    spawn_blocking({
32      let file = self.file.clone();
33      move || {
34        let n = file.read_at(&mut buf, offset).unwrap();
35        assert_eq!(n, usz!(len));
36        buf
37      }
38    })
39    .await
40    .unwrap()
41  }
42
43  async fn write_at(&self, offset: u64, data: Buf) -> Buf {
44    spawn_blocking({
45      let file = self.file.clone();
46      move || {
47        let n = file.write_at(&data, offset).unwrap();
48        assert_eq!(n, data.len());
49        data
50      }
51    })
52    .await
53    .unwrap()
54  }
55
56  async fn sync(&self) {
57    spawn_blocking({
58      let file = self.file.clone();
59      move || {
60        file.sync_data().unwrap();
61      }
62    })
63    .await
64    .unwrap();
65  }
66}