Skip to content

Commit 51dae34

Browse files
committed
Allow overriding tmpdir
1 parent 9919db9 commit 51dae34

File tree

2 files changed

+61
-9
lines changed

2 files changed

+61
-9
lines changed

src/fs_store.rs

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,19 +66,43 @@ use error::ErrorKind;
6666
/// half finished snapshot file. Deleting the inputs after the rename means that
6767
/// the worst case is that we have some leftover incremental files which will
6868
/// be deleted on the next compaction.
69+
#[derive(Debug)]
6970
pub struct FsStore {
7071
root: std::path::PathBuf,
72+
tmpdir: std::path::PathBuf,
7173
}
7274

7375
impl FsStore {
74-
/// Create an [`FsStore`] from a [`std::path::PathBuf`]
76+
/// Creates a new [`FsStore`] from a [`Path`].
7577
///
7678
/// This will attempt to create the root directory and throw an error if
7779
/// it does not exist.
7880
pub fn open<P: AsRef<Path>>(root: P) -> Result<Self, std::io::Error> {
79-
std::fs::create_dir_all(root.as_ref())?;
81+
let root = root.as_ref();
82+
std::fs::create_dir_all(root)?;
8083
Ok(Self {
81-
root: root.as_ref().into(),
84+
root: root.into(),
85+
tmpdir: root.into(),
86+
})
87+
}
88+
89+
/// Overrides the tmpdir directory used for temporary files.
90+
///
91+
/// The default is to use the root directory passed to [`FsStore::open`].
92+
///
93+
/// The tmpdir used must be on the same mount point as the root directory,
94+
/// otherwise the store will throw an error on writing data.
95+
///
96+
/// # Errors
97+
///
98+
/// This will attempt to create the tmpdir directory and throw an error if
99+
/// it does not exist.
100+
pub fn with_tmpdir<P: AsRef<Path>>(self, tmpdir: P) -> Result<Self, std::io::Error> {
101+
let tmpdir = tmpdir.as_ref();
102+
std::fs::create_dir_all(tmpdir)?;
103+
Ok(Self {
104+
tmpdir: tmpdir.into(),
105+
..self
82106
})
83107
}
84108

@@ -151,7 +175,7 @@ impl FsStore {
151175
})?;
152176

153177
let chunk_name = SavedChunkName::new_incremental(changes);
154-
write_chunk(&self.root, &paths, changes, chunk_name)?;
178+
write_chunk(&self.root, &paths, changes, chunk_name, &self.tmpdir)?;
155179

156180
Ok(())
157181
}
@@ -171,7 +195,7 @@ impl FsStore {
171195
// Write the snapshot
172196
let output_chunk_name = SavedChunkName::new_snapshot(doc.get_heads());
173197
let chunk = doc.save();
174-
write_chunk(&self.root, &paths, &chunk, output_chunk_name)?;
198+
write_chunk(&self.root, &paths, &chunk, output_chunk_name, &self.tmpdir)?;
175199

176200
// Remove all the old data
177201
for incremental in chunks.incrementals.keys() {
@@ -191,10 +215,11 @@ fn write_chunk(
191215
paths: &DocIdPaths,
192216
chunk: &[u8],
193217
name: SavedChunkName,
218+
tmpdir: &Path,
194219
) -> Result<(), Error> {
195220
// Write to a temp file and then rename to avoid partial writes
196221
let temp_dir =
197-
tempfile::TempDir::new_in(root).map_err(|e| Error(ErrorKind::CreateTempFile(e)))?;
222+
tempfile::TempDir::new_in(tmpdir).map_err(|e| Error(ErrorKind::CreateTempFile(e)))?;
198223
let temp_save_path = temp_dir.path().join(name.filename());
199224
let mut temp_save_file =
200225
File::create(&temp_save_path).map_err(|e| Error(ErrorKind::CreateTempFile(e)))?;

src/tokio/fs_storage.rs

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
1-
use std::sync::{Arc, Mutex};
1+
use std::{
2+
path::Path,
3+
sync::{Arc, Mutex},
4+
};
25

36
use futures::{future::BoxFuture, FutureExt, TryFutureExt};
47

58
use crate::{DocumentId, Storage, StorageError};
69

710
/// A wrapper around [`crate::fs_store::FsStore`] that implements [`crate::Storage`]
11+
#[derive(Debug)]
812
pub struct FsStorage {
913
inner: Arc<Mutex<crate::fs_store::FsStore>>,
1014
handle: tokio::runtime::Handle,
1115
}
1216

1317
impl FsStorage {
14-
/// Create a new [`FsStorage`] from a [`std::path::PathBuf`]
18+
/// Creates a new [`FsStorage`] from a [`Path`].
1519
///
1620
/// # Errors
1721
///
@@ -21,11 +25,34 @@ impl FsStorage {
2125
/// # Panics
2226
///
2327
/// If there is not a tokio runtime available
24-
pub fn open(root: std::path::PathBuf) -> Result<Self, std::io::Error> {
28+
pub fn open<P: AsRef<Path>>(root: P) -> Result<Self, std::io::Error> {
2529
let handle = tokio::runtime::Handle::current();
2630
let inner = Arc::new(Mutex::new(crate::fs_store::FsStore::open(root)?));
2731
Ok(Self { inner, handle })
2832
}
33+
34+
/// Overrides the tmpdir directory used for temporary files.
35+
///
36+
/// The default is to use the root directory passed to [`FsStorage::open`].
37+
///
38+
/// The tmpdir used must be on the same mount point as the root directory,
39+
/// otherwise the storage will throw an error on writing data.
40+
///
41+
/// # Errors
42+
///
43+
/// This will attempt to create the tmpdir directory and throw an error if
44+
/// it does not exist.
45+
pub fn with_tmpdir<P: AsRef<Path>>(self, tmpdir: P) -> Option<Result<Self, std::io::Error>> {
46+
let Self { inner, handle } = self;
47+
let inner = Arc::into_inner(inner)?.into_inner().ok()?;
48+
let inner = inner.with_tmpdir(tmpdir);
49+
let Ok(inner) = inner else {
50+
let e = inner.unwrap_err();
51+
return Some(Err(e));
52+
};
53+
let inner = Arc::new(Mutex::new(inner));
54+
Some(Ok(Self { inner, handle }))
55+
}
2956
}
3057

3158
impl Storage for FsStorage {

0 commit comments

Comments
 (0)