Skip to content

Commit a917d12

Browse files
committed
feat: add test
1 parent 29f00a2 commit a917d12

File tree

2 files changed

+77
-3
lines changed

2 files changed

+77
-3
lines changed

tests/basic_kv.rs

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
mod common;
22

3-
use common::{MockIndex, MockIndexWriter, NoCacher, NoCompressor};
3+
use common::{InMemCacher, MockIndex, MockIndexWriter, NoCacher, NoCompressor};
44
use test_log::test;
55
use value_log::{Config, IndexWriter, KeyRange, Slice, ValueLog};
66

@@ -72,3 +72,44 @@ fn basic_kv() -> value_log::Result<()> {
7272

7373
Ok(())
7474
}
75+
76+
#[test]
77+
fn get_with_cached_fd() -> value_log::Result<()> {
78+
let folder = tempfile::tempdir()?;
79+
let vl_path = folder.path();
80+
let items = ["a", "b", "c", "d", "e"];
81+
let index = MockIndex::default();
82+
83+
let fd_cache = InMemCacher::default();
84+
let value_log = ValueLog::open(
85+
vl_path,
86+
Config::<_, _, NoCompressor>::new(NoCacher, fd_cache.clone()),
87+
)?;
88+
89+
let mut index_writer = MockIndexWriter(index.clone());
90+
let mut writer = value_log.get_writer()?;
91+
92+
for key in items {
93+
let value = key.repeat(10_000);
94+
let value = value.as_bytes();
95+
96+
let key = key.as_bytes();
97+
98+
let vhandle = writer.get_next_value_handle();
99+
index_writer.insert_indirect(key, vhandle, value.len() as u32)?;
100+
101+
writer.write(key, value)?;
102+
}
103+
value_log.register_writer(writer)?;
104+
105+
for (key, (vhandle, _)) in index.read().unwrap().iter() {
106+
let item = value_log.get(vhandle)?.unwrap();
107+
assert_eq!(item, key.repeat(10_000));
108+
}
109+
110+
let index_len = index.read().unwrap().len() as u32;
111+
// The first item will cache the fd, subsequent accesses will all be cache hits
112+
assert_eq!(fd_cache.get_hit_count(), index_len - 1);
113+
114+
Ok(())
115+
}

tests/common.rs

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@
33
// (found in the LICENSE-* files in the repository)
44

55
use std::{
6-
collections::BTreeMap,
6+
cell::RefCell,
7+
collections::{BTreeMap, HashMap},
78
fs::File,
89
io::BufReader,
9-
sync::{Arc, RwLock},
10+
sync::{Arc, Mutex, RwLock},
1011
};
1112
use value_log::{
1213
BlobCache, BlobFileId, Compressor, FDCache, IndexReader, IndexWriter, UserKey, UserValue,
@@ -100,3 +101,35 @@ impl FDCache for NoCacher {
100101
}
101102
fn insert(&self, _: ValueLogId, _: BlobFileId, _: BufReader<File>) {}
102103
}
104+
105+
#[derive(Clone, Default)]
106+
pub struct InMemCacher {
107+
fd_cache: Arc<Mutex<HashMap<(ValueLogId, BlobFileId), File>>>,
108+
fd_hit_count: Arc<RefCell<u32>>,
109+
}
110+
impl InMemCacher {
111+
pub(crate) fn get_hit_count(&self) -> u32 {
112+
*self.fd_hit_count.borrow()
113+
}
114+
}
115+
116+
impl FDCache for InMemCacher {
117+
fn get(&self, vlog_id: ValueLogId, blob_file_id: BlobFileId) -> Option<BufReader<File>> {
118+
let lock = self.fd_cache.lock().unwrap();
119+
let fd = match lock.get(&(vlog_id, blob_file_id)) {
120+
Some(fd) => fd,
121+
None => return None,
122+
};
123+
124+
let fd_clone = fd.try_clone().unwrap();
125+
*self.fd_hit_count.borrow_mut() += 1;
126+
Some(BufReader::new(fd_clone))
127+
}
128+
129+
fn insert(&self, vlog_id: ValueLogId, blob_file_id: BlobFileId, fd: BufReader<File>) {
130+
self.fd_cache
131+
.lock()
132+
.unwrap()
133+
.insert((vlog_id, blob_file_id), fd.into_inner());
134+
}
135+
}

0 commit comments

Comments
 (0)