use std::collections::HashMap;
use std::collections::hash_map::Entry;
use dynamo_kv_router::protocols::{
ExternalSequenceBlockHash, KvCacheRemoveData, KvCacheStoreData, StorageTier,
};
pub(super) struct EventDedupFilter {
per_rank_tier: HashMap<(u32, StorageTier), HashMap<ExternalSequenceBlockHash, usize>>,
}
impl EventDedupFilter {
pub(super) fn new() -> Self {
Self {
per_rank_tier: HashMap::new(),
}
}
pub(super) fn track_store(
&mut self,
dp_rank: u32,
storage_tier: StorageTier,
data: &KvCacheStoreData,
) {
let refcounts = self
.per_rank_tier
.entry((dp_rank, storage_tier))
.or_default();
for block in &data.blocks {
*refcounts.entry(block.block_hash).or_insert(0) += 1;
}
}
pub(super) fn filter_remove(
&mut self,
dp_rank: u32,
storage_tier: StorageTier,
mut data: KvCacheRemoveData,
) -> Option<KvCacheRemoveData> {
let refcounts = self
.per_rank_tier
.entry((dp_rank, storage_tier))
.or_default();
data.block_hashes.retain(|hash| {
match refcounts.entry(*hash) {
Entry::Occupied(mut entry) => {
*entry.get_mut() -= 1;
if *entry.get() == 0 {
entry.remove();
true } else {
false }
}
Entry::Vacant(_) => {
true }
}
});
if data.block_hashes.is_empty() {
None
} else {
Some(data)
}
}
pub(super) fn clear(&mut self) {
self.per_rank_tier.clear();
}
}