forked from faasten/faasten
-
Notifications
You must be signed in to change notification settings - Fork 1
/
mod.rs
132 lines (112 loc) · 3.11 KB
/
mod.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
use std::io::{Read, Result, Seek, Write};
use std::os::unix::prelude::FileExt;
use std::path::PathBuf;
use std::{ffi::OsString, fs::File, marker::PhantomData};
use sha2::{Digest, Sha256};
use tempfile::NamedTempFile;
#[derive(Debug)]
pub struct Blobstore<D = Sha256> {
base_dir: OsString,
tmp_dir: OsString,
digest: PhantomData<D>,
}
impl<D> Default for Blobstore<D> {
fn default() -> Self {
Blobstore {
base_dir: OsString::from("blobs"),
tmp_dir: OsString::from("tmp"),
digest: PhantomData,
}
}
}
impl<D> Blobstore<D> {
pub const fn new(base_dir: OsString, tmp_dir: OsString) -> Self {
Blobstore { base_dir, tmp_dir, digest: PhantomData }
}
}
impl<D: Digest> Blobstore<D> {
pub fn create(&mut self) -> Result<NewBlob<D>> {
Ok(NewBlob {
digest: D::new(),
len: 0,
file: NamedTempFile::new_in(&self.tmp_dir)?,
})
}
pub fn open(&self, name: String) -> Result<Blob> {
let blob_path = {
let (d, n) = name.split_at(2);
PathBuf::from(&self.base_dir).join(d).join(n)
};
Ok(Blob {
name,
file: File::open(blob_path)?
})
}
// a hack, see the place that calls vm.launch in worker.rs
pub fn local_path_string(&self, name: &String) -> Option<String> {
let (d, n) = name.split_at(2);
PathBuf::from(&self.base_dir).join(d).join(n).into_os_string().into_string().ok()
}
pub fn save(&mut self, new_blob: NewBlob<D>) -> Result<Blob> {
let name = hex::encode(new_blob.digest.finalize());
let mut hpath = std::path::PathBuf::new();
hpath.push(&self.base_dir);
let (dir, fname) = name.split_at(2);
hpath.push(dir);
let _ = std::fs::create_dir_all(hpath.clone());
hpath.push(fname);
let file = new_blob.file.persist(hpath)?;
let mut perms = file.metadata()?.permissions();
perms.set_readonly(true);
file.set_permissions(perms)?;
Ok(Blob {
name,
file
})
}
}
#[derive(Debug)]
pub struct Blob {
pub name: String,
file: File,
}
impl Blob {
pub fn read_at(&self, buf: &mut [u8], offset: u64) -> Result<usize> {
self.file.read_at(buf, offset)
}
pub fn len(&self) -> Result<u64> {
self.file.metadata().map(|m| m.len())
}
}
impl Seek for Blob {
fn seek(&mut self, pos: std::io::SeekFrom) -> Result<u64> {
self.file.seek(pos)
}
}
impl Read for Blob {
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
self.file.read(buf)
}
}
#[derive(Debug)]
pub struct NewBlob<D: Digest = Sha256> {
digest: D,
len: usize,
file: NamedTempFile,
}
impl<D: Digest> NewBlob<D> {
pub fn len(&self) -> usize {
self.len
}
}
impl<D: Digest> Write for NewBlob<D> {
fn write(&mut self, bytes: &[u8]) -> Result<usize> {
let n = self.file.write(bytes)?;
self.digest.update(&bytes[..n]);
self.len += n;
Ok(n)
}
fn flush(&mut self) -> Result<()> {
self.file.flush()
}
}