2022-09-14 01:32:31 +08:00
|
|
|
use std::fs::File as StdFile;
|
2022-09-13 21:35:57 +08:00
|
|
|
use std::ops::{Deref, DerefMut};
|
|
|
|
use std::path::{Path, PathBuf};
|
|
|
|
|
|
|
|
use tempfile::NamedTempFile;
|
|
|
|
use uuid::Uuid;
|
|
|
|
|
|
|
|
const UPDATE_FILES_PATH: &str = "updates/updates_files";
|
|
|
|
|
|
|
|
#[derive(Debug, thiserror::Error)]
|
2022-09-13 21:54:35 +08:00
|
|
|
pub enum Error {
|
2022-09-13 21:35:57 +08:00
|
|
|
#[error(transparent)]
|
|
|
|
IoError(#[from] std::io::Error),
|
|
|
|
#[error(transparent)]
|
|
|
|
PersistError(#[from] tempfile::PersistError),
|
|
|
|
}
|
|
|
|
|
2022-09-13 21:54:35 +08:00
|
|
|
pub type Result<T> = std::result::Result<T, Error>;
|
2022-09-13 21:35:57 +08:00
|
|
|
|
2022-09-14 01:32:31 +08:00
|
|
|
impl Deref for File {
|
2022-09-13 21:35:57 +08:00
|
|
|
type Target = NamedTempFile;
|
|
|
|
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
|
|
&self.file
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-14 01:32:31 +08:00
|
|
|
impl DerefMut for File {
|
2022-09-13 21:35:57 +08:00
|
|
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
|
|
&mut self.file
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-15 19:34:02 +08:00
|
|
|
#[cfg_attr(test, faux::create)]
|
2022-09-13 21:54:35 +08:00
|
|
|
#[derive(Clone, Debug)]
|
2022-09-14 01:32:31 +08:00
|
|
|
pub struct FileStore {
|
2022-09-13 21:54:35 +08:00
|
|
|
path: PathBuf,
|
|
|
|
}
|
2022-09-13 21:35:57 +08:00
|
|
|
|
2022-09-15 19:34:02 +08:00
|
|
|
#[cfg(not(test))]
|
2022-09-14 01:32:31 +08:00
|
|
|
impl FileStore {
|
|
|
|
pub fn new(path: impl AsRef<Path>) -> Result<FileStore> {
|
2022-09-21 18:01:46 +08:00
|
|
|
let path = path.as_ref().to_path_buf();
|
2022-09-13 21:54:35 +08:00
|
|
|
std::fs::create_dir_all(&path)?;
|
2022-09-14 01:32:31 +08:00
|
|
|
Ok(FileStore { path })
|
2022-09-13 21:35:57 +08:00
|
|
|
}
|
2022-09-15 19:34:02 +08:00
|
|
|
}
|
2022-09-13 21:35:57 +08:00
|
|
|
|
2022-09-15 19:34:02 +08:00
|
|
|
#[cfg_attr(test, faux::methods)]
|
|
|
|
impl FileStore {
|
2022-09-13 21:54:35 +08:00
|
|
|
/// Creates a new temporary update file.
|
|
|
|
/// A call to `persist` is needed to persist the file in the database.
|
2022-09-14 01:32:31 +08:00
|
|
|
pub fn new_update(&self) -> Result<(Uuid, File)> {
|
2022-09-13 21:54:35 +08:00
|
|
|
let file = NamedTempFile::new_in(&self.path)?;
|
|
|
|
let uuid = Uuid::new_v4();
|
|
|
|
let path = self.path.join(uuid.to_string());
|
2022-09-14 01:32:31 +08:00
|
|
|
let update_file = File { file, path };
|
2022-09-13 21:54:35 +08:00
|
|
|
|
|
|
|
Ok((uuid, update_file))
|
2022-09-13 21:35:57 +08:00
|
|
|
}
|
2022-10-11 15:53:08 +08:00
|
|
|
|
2022-10-10 21:51:28 +08:00
|
|
|
/// Creates a new temporary update file with the given Uuid.
|
|
|
|
/// A call to `persist` is needed to persist the file in the database.
|
2022-10-11 15:55:03 +08:00
|
|
|
pub fn new_update_with_uuid(&self, uuid: u128) -> Result<(Uuid, File)> {
|
2022-10-10 21:51:28 +08:00
|
|
|
let file = NamedTempFile::new_in(&self.path)?;
|
|
|
|
let uuid = Uuid::from_u128(uuid);
|
|
|
|
let path = self.path.join(uuid.to_string());
|
|
|
|
let update_file = File { file, path };
|
|
|
|
|
|
|
|
Ok((uuid, update_file))
|
|
|
|
}
|
2022-09-13 21:35:57 +08:00
|
|
|
|
2022-09-13 21:54:35 +08:00
|
|
|
/// Returns the file corresponding to the requested uuid.
|
2022-09-14 01:32:31 +08:00
|
|
|
pub fn get_update(&self, uuid: Uuid) -> Result<StdFile> {
|
2022-09-13 21:54:35 +08:00
|
|
|
let path = self.path.join(uuid.to_string());
|
2022-09-14 01:32:31 +08:00
|
|
|
let file = StdFile::open(path)?;
|
2022-09-13 21:54:35 +08:00
|
|
|
Ok(file)
|
|
|
|
}
|
2022-09-13 21:35:57 +08:00
|
|
|
|
2022-09-13 21:54:35 +08:00
|
|
|
/// Copies the content of the update file pointed to by `uuid` to the `dst` directory.
|
|
|
|
pub fn snapshot(&self, uuid: Uuid, dst: impl AsRef<Path>) -> Result<()> {
|
|
|
|
let src = self.path.join(uuid.to_string());
|
|
|
|
let mut dst = dst.as_ref().join(UPDATE_FILES_PATH);
|
|
|
|
std::fs::create_dir_all(&dst)?;
|
|
|
|
dst.push(uuid.to_string());
|
|
|
|
std::fs::copy(src, dst)?;
|
|
|
|
Ok(())
|
|
|
|
}
|
2022-09-13 21:35:57 +08:00
|
|
|
|
2022-09-13 21:54:35 +08:00
|
|
|
pub fn get_size(&self, uuid: Uuid) -> Result<u64> {
|
|
|
|
Ok(self.get_update(uuid)?.metadata()?.len())
|
|
|
|
}
|
2022-09-13 21:35:57 +08:00
|
|
|
|
2022-09-13 21:54:35 +08:00
|
|
|
pub fn delete(&self, uuid: Uuid) -> Result<()> {
|
|
|
|
let path = self.path.join(uuid.to_string());
|
|
|
|
std::fs::remove_file(path)?;
|
|
|
|
Ok(())
|
2022-09-13 21:35:57 +08:00
|
|
|
}
|
2022-09-13 21:54:35 +08:00
|
|
|
}
|
|
|
|
|
2022-09-14 01:32:31 +08:00
|
|
|
pub struct File {
|
2022-09-13 21:54:35 +08:00
|
|
|
path: PathBuf,
|
|
|
|
file: NamedTempFile,
|
|
|
|
}
|
2022-09-13 21:35:57 +08:00
|
|
|
|
2022-09-14 01:32:31 +08:00
|
|
|
impl File {
|
2022-09-13 21:54:35 +08:00
|
|
|
pub fn persist(self) -> Result<()> {
|
|
|
|
self.file.persist(&self.path)?;
|
|
|
|
Ok(())
|
2022-09-13 21:35:57 +08:00
|
|
|
}
|
|
|
|
}
|