common_meta/
region_keeper.rsuse std::collections::HashSet;
use std::sync::{Arc, RwLock};
use store_api::storage::RegionId;
use crate::DatanodeId;
#[derive(Debug, Clone)]
pub struct OperatingRegionGuard {
datanode_id: DatanodeId,
region_id: RegionId,
inner: Arc<RwLock<HashSet<(DatanodeId, RegionId)>>>,
}
impl Drop for OperatingRegionGuard {
fn drop(&mut self) {
let mut inner = self.inner.write().unwrap();
inner.remove(&(self.datanode_id, self.region_id));
}
}
impl OperatingRegionGuard {
pub fn info(&self) -> (DatanodeId, RegionId) {
(self.datanode_id, self.region_id)
}
}
pub type MemoryRegionKeeperRef = Arc<MemoryRegionKeeper>;
#[derive(Debug, Clone, Default)]
pub struct MemoryRegionKeeper {
inner: Arc<RwLock<HashSet<(DatanodeId, RegionId)>>>,
}
impl MemoryRegionKeeper {
pub fn new() -> Self {
Default::default()
}
pub fn register(
&self,
datanode_id: DatanodeId,
region_id: RegionId,
) -> Option<OperatingRegionGuard> {
let mut inner = self.inner.write().unwrap();
if inner.insert((datanode_id, region_id)) {
Some(OperatingRegionGuard {
datanode_id,
region_id,
inner: self.inner.clone(),
})
} else {
None
}
}
pub fn contains(&self, datanode_id: DatanodeId, region_id: RegionId) -> bool {
let inner = self.inner.read().unwrap();
inner.contains(&(datanode_id, region_id))
}
pub fn extract_operating_regions(
&self,
datanode_id: DatanodeId,
region_ids: &mut HashSet<RegionId>,
) -> HashSet<RegionId> {
let inner = self.inner.read().unwrap();
let operating_regions = region_ids
.extract_if(|region_id| inner.contains(&(datanode_id, *region_id)))
.collect::<HashSet<_>>();
operating_regions
}
pub fn len(&self) -> usize {
let inner = self.inner.read().unwrap();
inner.len()
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
#[cfg(test)]
pub fn clear(&self) {
let mut inner = self.inner.write().unwrap();
inner.clear();
}
}
#[cfg(test)]
mod tests {
use std::collections::HashSet;
use store_api::storage::RegionId;
use crate::region_keeper::MemoryRegionKeeper;
#[test]
fn test_opening_region_keeper() {
let keeper = MemoryRegionKeeper::new();
let guard = keeper.register(1, RegionId::from_u64(1)).unwrap();
assert!(keeper.register(1, RegionId::from_u64(1)).is_none());
let guard2 = keeper.register(1, RegionId::from_u64(2)).unwrap();
let mut regions = HashSet::from([
RegionId::from_u64(1),
RegionId::from_u64(2),
RegionId::from_u64(3),
]);
let output = keeper.extract_operating_regions(1, &mut regions);
assert_eq!(output.len(), 2);
assert!(output.contains(&RegionId::from_u64(1)));
assert!(output.contains(&RegionId::from_u64(2)));
assert_eq!(keeper.len(), 2);
drop(guard);
assert_eq!(keeper.len(), 1);
assert!(keeper.contains(1, RegionId::from_u64(2)));
drop(guard2);
assert!(keeper.is_empty());
}
}