Skip to content

Commit d2a9b73

Browse files
committed
feat: remove functionality for cache
1 parent 35b6dc8 commit d2a9b73

File tree

3 files changed

+77
-8
lines changed

3 files changed

+77
-8
lines changed

benches/benchmarks.rs

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,12 @@ pub fn cache_write_random_key(c: &mut Criterion) {
4040
let (db, rt) = make_executor();
4141
let value = random_bytes(VALUE_SZ);
4242

43-
b.iter_custom(|iters| {
44-
let key = random_bytes(4);
45-
let start = Instant::now();
46-
for _ in 0..iters {
43+
b.iter_with_setup(
44+
|| random_bytes(4),
45+
|key| {
4746
rt.block_on(db.write(&key, &value)).unwrap();
48-
}
49-
start.elapsed()
50-
});
47+
},
48+
);
5149
});
5250
}
5351

@@ -66,6 +64,21 @@ pub fn cache_read_const_key(c: &mut Criterion) {
6664
});
6765
}
6866

67+
pub fn cache_remove_const_key(c: &mut Criterion) {
68+
c.bench_function("cache::remove_const_key", move |b| {
69+
let (db, rt) = make_executor();
70+
const KEY: [u8; 4] = [0xDE, 0xAD, 0xBE, 0xEF];
71+
let value = random_bytes(VALUE_SZ);
72+
73+
b.iter_with_setup(
74+
|| rt.block_on(db.write(&KEY, &value)).unwrap(),
75+
|_| {
76+
rt.block_on(db.remove(&KEY)).unwrap();
77+
},
78+
);
79+
});
80+
}
81+
6982
pub fn cache_metadata_lookup(c: &mut Criterion) {
7083
c.bench_function("cache::metadata_lookup", move |b| {
7184
let (db, rt) = make_executor();
@@ -84,6 +97,7 @@ criterion_group!(
8497
cache_write_const_key,
8598
cache_write_random_key,
8699
cache_read_const_key,
100+
cache_remove_const_key,
87101
cache_metadata_lookup
88102
);
89103

src/cache.rs

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,52 @@ impl Cache {
188188
Ok(())
189189
}
190190

191+
/// Removes an entry from the cache, returning its [`Metadata`].
192+
///
193+
/// This will remove the entry from both the main cache database and the metadata database.
194+
/// Please note that this will return `Error::NotFound` if either the main database *or* the
195+
/// meta database didn't find the entry.
196+
///
197+
/// # Examples
198+
///
199+
/// ```rust
200+
/// # #[tokio::main(flavor = "current_thread")]
201+
/// # async fn main() {
202+
/// use forceps::CacheBuilder;
203+
///
204+
/// let cache = CacheBuilder::new("./cache")
205+
/// .build()
206+
/// .await
207+
/// .unwrap();
208+
///
209+
/// # cache.write(b"MY_KEY", b"Hello World").await.unwrap();
210+
/// let metadata = cache.remove(b"MY_KEY").await.unwrap();
211+
/// assert_eq!(metadata.get_size(), b"Hello World".len() as u64);
212+
/// # }
213+
/// ```
214+
pub async fn remove<K: AsRef<[u8]>>(&self, key: K) -> Result<Metadata> {
215+
let key = key.as_ref();
216+
217+
let cur_path = self.path_from_key(key);
218+
let tmp_path = crate::tmp::tmppath_in(&self.path);
219+
220+
// move then delete the file
221+
//
222+
// the purpose of moving then deleting is that file moves are much faster than file
223+
// deletes. if we were to delete in place, and another thread starts reading, it could
224+
// spell bad news.
225+
afs::rename(&cur_path, &tmp_path)
226+
.await
227+
.map_err(|e| match e.kind() {
228+
io::ErrorKind::NotFound => ForcepError::NotFound,
229+
_ => ForcepError::Io(e),
230+
})?;
231+
afs::remove_file(&tmp_path).await.map_err(ForcepError::Io)?;
232+
233+
// remove the metadata for the entry
234+
self.meta.remove_metadata_for(key)
235+
}
236+
191237
/// Queries the index database for metadata on the entry with the corresponding key.
192238
///
193239
/// This will return the metadata for the associated key. For information about what metadata
@@ -337,12 +383,13 @@ mod test {
337383
}
338384

339385
#[tokio::test]
340-
async fn basic_write_read() {
386+
async fn write_read_remove() {
341387
let cache = default_cache().await;
342388

343389
cache.write(&b"CACHE_KEY", &b"Hello World").await.unwrap();
344390
let data = cache.read(&b"CACHE_KEY").await.unwrap();
345391
assert_eq!(&data, &b"Hello World");
392+
cache.remove(&b"CACHE_KEY").await.unwrap();
346393
}
347394

348395
#[tokio::test]

src/metadata.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,14 @@ impl MetaDb {
153153
Ok(meta)
154154
}
155155

156+
pub fn remove_metadata_for(&self, key: &[u8]) -> Result<Metadata> {
157+
match self.db.remove(key) {
158+
Ok(Some(m)) => Metadata::deserialize(&m[..]),
159+
Ok(None) => Err(ForcepError::NotFound),
160+
Err(e) => Err(ForcepError::MetaDb(e)),
161+
}
162+
}
163+
156164
/// Iterator over the entire metadata database
157165
pub fn metadata_iter(&self) -> impl Iterator<Item = Result<(Vec<u8>, Metadata)>> {
158166
self.db.iter().map(|x| match x {

0 commit comments

Comments
 (0)