#[cfg(feature = "metrics")]
use metrics::{Counter, Gauge, counter, gauge};
#[cfg(feature = "metrics")]
use std::sync::Arc;
#[cfg(feature = "metrics")]
use std::sync::atomic::{AtomicU64, Ordering};
use indexmap::IndexMap;
use left_right::Absorb;
use std::hash::Hash;
use crate::{ChiralMapConfig, chiral_map::Operation};
pub(crate) struct SingleMap<K, V> {
map: IndexMap<K, V>,
#[cfg(feature = "metrics")]
id: String,
#[cfg(feature = "metrics")]
instances: Arc<AtomicU64>,
#[cfg(feature = "metrics")]
met_inserts: Arc<Counter>,
#[cfg(feature = "metrics")]
met_deletions: Arc<Counter>,
#[cfg(feature = "metrics")]
met_size: Arc<Gauge>,
#[cfg(feature = "metrics")]
met_capacity: Arc<Gauge>,
}
impl<K, V> Absorb<Operation<K, V>> for SingleMap<K, V>
where
K: Hash + Eq + Clone,
V: Clone,
{
fn absorb_first(&mut self, operation: &mut Operation<K, V>, _other: &Self) {
self.step(operation.clone());
}
fn absorb_second(&mut self, operation: Operation<K, V>, _other: &Self) {
self.step(operation);
}
fn sync_with(&mut self, first: &Self) {
first.map.iter().for_each(|(k, v)| {
self.map.insert(k.clone(), v.clone());
});
}
}
impl<K, V> SingleMap<K, V>
where
K: Hash + Eq + Clone,
V: Clone,
{
pub(crate) fn step(&mut self, operation: Operation<K, V>) {
match operation {
Operation::Insert(k, v) => {
self.map.insert(k, v);
#[cfg(feature = "metrics")]
self.met_inserts.increment(1);
#[cfg(feature = "metrics")]
self.met_size.set(self.map.len() as f64);
#[cfg(feature = "metrics")]
self.met_capacity.set(self.map.capacity() as f64);
}
Operation::Delete(k) => {
self.map.swap_remove(&k);
#[cfg(feature = "metrics")]
self.met_deletions.increment(1);
#[cfg(feature = "metrics")]
self.met_size.set(self.map.len() as f64);
#[cfg(feature = "metrics")]
self.met_capacity.set(self.map.capacity() as f64);
}
};
}
}
impl<K, V> SingleMap<K, V>
where
K: Hash + Eq + Clone,
V: Clone,
{
pub(crate) fn new(config: &ChiralMapConfig) -> Self {
let map = IndexMap::<K, V>::with_capacity(config.initial_capacity);
#[cfg(feature = "metrics")]
let instances = Arc::new(AtomicU64::from(1));
#[cfg(feature = "metrics")]
let instance = 1;
#[cfg(feature = "metrics")]
let met_inserts = counter!("chiral_map_inserts", "id" => config.id.clone(), "instance" => instance.to_string());
#[cfg(feature = "metrics")]
let met_deletions = counter!("chiral_map_deletions", "id" => config.id.clone(), "instance" => instance.to_string());
#[cfg(feature = "metrics")]
let met_size = gauge!("chiral_map_size", "id" => config.id.clone(), "instance" => instance.to_string());
#[cfg(feature = "metrics")]
let met_capacity = gauge!("chiral_map_capacity", "id" => config.id.clone(), "instance" => instance.to_string());
#[cfg(feature = "metrics")]
met_capacity.set(map.capacity() as f64);
Self {
map,
#[cfg(feature = "metrics")]
id: config.id.clone(),
#[cfg(feature = "metrics")]
instances,
#[cfg(feature = "metrics")]
met_inserts: met_inserts.into(),
#[cfg(feature = "metrics")]
met_deletions: met_deletions.into(),
#[cfg(feature = "metrics")]
met_size: met_size.into(),
#[cfg(feature = "metrics")]
met_capacity: met_capacity.into(),
}
}
pub(crate) fn get(&self, k: &K) -> Option<&V> {
self.map.get(k)
}
}
impl<K, V> Clone for SingleMap<K, V>
where
K: Hash + Eq + Clone,
V: Clone,
{
fn clone(&self) -> Self {
#[cfg(feature = "metrics")]
let instance = self.instances.fetch_add(1, Ordering::Relaxed) + 1;
#[cfg(feature = "metrics")]
let met_inserts = counter!("chiral_map_inserts", "id" => self.id.clone(), "instance" => instance.to_string());
#[cfg(feature = "metrics")]
let met_deletions = counter!("chiral_map_deletions", "id" => self.id.clone(), "instance" => instance.to_string());
#[cfg(feature = "metrics")]
let met_size =
gauge!("chiral_map_size", "id" => self.id.clone(), "instance" => instance.to_string());
#[cfg(feature = "metrics")]
let met_capacity = gauge!("chiral_map_capacity", "id" => self.id.clone(), "instance" => instance.to_string());
#[cfg(feature = "metrics")]
met_capacity.set(self.map.capacity() as f64);
Self {
map: self.map.clone(),
#[cfg(feature = "metrics")]
id: self.id.clone(),
#[cfg(feature = "metrics")]
instances: self.instances.clone(),
#[cfg(feature = "metrics")]
met_inserts: met_inserts.into(),
#[cfg(feature = "metrics")]
met_deletions: met_deletions.into(),
#[cfg(feature = "metrics")]
met_size: met_size.into(),
#[cfg(feature = "metrics")]
met_capacity: met_capacity.into(),
}
}
}