use crate::bloom_filter::BloomFilter;
use skiplist::SkipList;
mod arena_allocator;
mod skiplist;
#[cfg(test)]
mod tests;
pub struct MemTable {
entries: SkipList<Vec<u8>, Vec<u8>>,
capacity_bytes: usize,
size_bytes: usize,
bloom_filter: BloomFilter,
false_positive_rate: f64,
}
impl MemTable {
pub fn new(capacity_bytes: usize, false_positive_rate: f64) -> Self {
assert!(capacity_bytes > 0, "Capacity must be greater than zero");
let avg_entry_size = 100;
let num_elements = capacity_bytes / avg_entry_size;
Self {
entries: SkipList::new(),
capacity_bytes,
size_bytes: 0,
bloom_filter: BloomFilter::new(num_elements, false_positive_rate),
false_positive_rate,
}
}
pub fn set(&mut self, key: Vec<u8>, value: Vec<u8>) {
self.bloom_filter.set(&key);
self.size_bytes += key.len() + value.len();
self.entries.insert(key, value);
}
pub fn get(&self, key: &[u8]) -> Option<&Vec<u8>> {
if !self.bloom_filter.contains(key) {
return None;
}
let search_key = key.to_vec();
self.entries.get(&search_key)
}
pub fn needs_flush(&self) -> bool {
self.approximate_memory_usage() >= self.capacity_bytes
}
pub fn approximate_memory_usage(&self) -> usize {
self.entries.memory_usage() + self.size_bytes
}
pub fn clear(&mut self) {
self.entries = SkipList::new();
let num_elements = self.capacity_bytes / 100;
self.bloom_filter = BloomFilter::new(num_elements, self.false_positive_rate);
self.size_bytes = 0;
}
pub fn entries(&self) -> Vec<(&Vec<u8>, &Vec<u8>)> {
self.entries.iter().collect()
}
}