#[derive(Clone, Copy, Debug)]
pub struct Entry {
pub key: [u8; 32],
pub offset: u64,
pub write_count: u32,
pub log_id: u64,
pub deleted: bool,
pub value_hash: [u8; 32],
}
pub struct Shard {
pub entries: dashmap::DashMap<[u8; 32], Entry>,
}
impl Shard {
pub fn new() -> Self {
Self { entries: dashmap::DashMap::with_capacity(64) }
}
#[inline(always)]
pub(crate) fn get(&self, key: &[u8; 32]) -> Option<u64> {
self.entries.get(key).map(|e| e.offset)
}
#[inline(always)]
pub(crate) fn get_entry(&self, key: &[u8; 32]) -> Option<Entry> {
self.entries.get(key).map(|e| *e.value())
}
#[inline(always)]
pub(crate) fn get_count(&self, key: &[u8; 32]) -> u32 {
self.entries.get(key).map(|e| e.write_count).unwrap_or(0)
}
#[inline(always)]
pub fn upsert(&self, key: [u8; 32], offset: u64, write_count: u32, log_id: u64, deleted: bool, value_hash: [u8; 32]) {
self.entries.insert(key, Entry { key, offset, write_count, log_id, deleted, value_hash });
}
#[inline(always)]
#[allow(dead_code)]
pub(crate) fn remove(&self, key: &[u8; 32]) {
self.entries.remove(key);
}
pub fn len(&self) -> usize {
self.entries.len()
}
pub fn is_empty(&self) -> bool {
self.entries.is_empty()
}
pub fn iter_all(&self) -> Vec<Entry> {
self.entries.iter().map(|e| *e.value()).collect()
}
}
impl Default for Shard {
fn default() -> Self { Self::new() }
}
pub struct ShardIndex {
pub shards: Box<[Shard; 256]>,
}
impl ShardIndex {
pub fn new() -> Self {
let shards: Box<[Shard; 256]> = (0..256)
.map(|_| Shard::new())
.collect::<Vec<_>>()
.try_into()
.ok()
.unwrap();
Self { shards }
}
#[inline(always)]
pub(crate) fn shard(&self, key: &[u8; 32]) -> &Shard {
&self.shards[key[0] as usize]
}
#[inline(always)]
pub fn get(&self, k: &[u8; 32]) -> Option<u64> {
self.shard(k).get(k)
}
#[inline(always)]
pub fn get_entry(&self, k: &[u8; 32]) -> Option<Entry> {
self.shard(k).get_entry(k)
}
#[inline(always)]
pub fn count(&self, k: &[u8; 32]) -> u32 {
self.shard(k).get_count(k)
}
#[inline(always)]
pub fn upsert(&self, k: [u8; 32], off: u64, wc: u32, log_id: u64) {
self.shard(&k).upsert(k, off, wc, log_id, false, [0u8; 32]);
}
#[inline(always)]
pub fn upsert_with_deleted(&self, k: [u8; 32], off: u64, wc: u32, log_id: u64, deleted: bool) {
self.shard(&k).upsert(k, off, wc, log_id, deleted, [0u8; 32]);
}
#[inline(always)]
pub fn upsert_full(&self, k: [u8; 32], off: u64, wc: u32, log_id: u64, deleted: bool, vh: [u8; 32]) {
self.shard(&k).upsert(k, off, wc, log_id, deleted, vh);
}
pub fn len(&self) -> usize {
self.shards.iter().map(|s| s.len()).sum()
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn clear(&self) {
for s in self.shards.iter() {
s.entries.clear();
}
}
pub fn all_entries(&self) -> Vec<Entry> {
let mut v = Vec::new();
for s in self.shards.iter() {
v.extend(s.iter_all());
}
v
}
}
impl Default for ShardIndex {
fn default() -> Self { Self::new() }
}