common_meta/
region_keeper.rs1use std::collections::HashSet;
16use std::sync::{Arc, RwLock};
17
18use store_api::storage::RegionId;
19
20use crate::DatanodeId;
21
22#[derive(Debug, Clone)]
24pub struct OperatingRegionGuard {
25 datanode_id: DatanodeId,
26 region_id: RegionId,
27 inner: Arc<RwLock<HashSet<(DatanodeId, RegionId)>>>,
28}
29
30impl Drop for OperatingRegionGuard {
31 fn drop(&mut self) {
32 let mut inner = self.inner.write().unwrap();
33 inner.remove(&(self.datanode_id, self.region_id));
34 }
35}
36
37impl OperatingRegionGuard {
38 pub fn info(&self) -> (DatanodeId, RegionId) {
40 (self.datanode_id, self.region_id)
41 }
42}
43
44pub type MemoryRegionKeeperRef = Arc<MemoryRegionKeeper>;
45
46#[derive(Debug, Clone, Default)]
52pub struct MemoryRegionKeeper {
53 inner: Arc<RwLock<HashSet<(DatanodeId, RegionId)>>>,
54}
55
56impl MemoryRegionKeeper {
57 pub fn new() -> Self {
58 Default::default()
59 }
60
61 pub fn register(
63 &self,
64 datanode_id: DatanodeId,
65 region_id: RegionId,
66 ) -> Option<OperatingRegionGuard> {
67 let mut inner = self.inner.write().unwrap();
68
69 if inner.insert((datanode_id, region_id)) {
70 Some(OperatingRegionGuard {
71 datanode_id,
72 region_id,
73 inner: self.inner.clone(),
74 })
75 } else {
76 None
77 }
78 }
79
80 pub fn contains(&self, datanode_id: DatanodeId, region_id: RegionId) -> bool {
82 let inner = self.inner.read().unwrap();
83 inner.contains(&(datanode_id, region_id))
84 }
85
86 pub fn extract_operating_regions(
88 &self,
89 datanode_id: DatanodeId,
90 region_ids: &mut HashSet<RegionId>,
91 ) -> HashSet<RegionId> {
92 let inner = self.inner.read().unwrap();
93 region_ids
94 .extract_if(|region_id| inner.contains(&(datanode_id, *region_id)))
95 .collect::<HashSet<_>>()
96 }
97
98 pub fn len(&self) -> usize {
100 let inner = self.inner.read().unwrap();
101 inner.len()
102 }
103
104 pub fn is_empty(&self) -> bool {
106 self.len() == 0
107 }
108
109 #[cfg(test)]
110 pub fn clear(&self) {
111 let mut inner = self.inner.write().unwrap();
112 inner.clear();
113 }
114}
115
116#[cfg(test)]
117mod tests {
118 use std::collections::HashSet;
119
120 use store_api::storage::RegionId;
121
122 use crate::region_keeper::MemoryRegionKeeper;
123
124 #[test]
125 fn test_opening_region_keeper() {
126 let keeper = MemoryRegionKeeper::new();
127
128 let guard = keeper.register(1, RegionId::from_u64(1)).unwrap();
129 assert!(keeper.register(1, RegionId::from_u64(1)).is_none());
130 let guard2 = keeper.register(1, RegionId::from_u64(2)).unwrap();
131
132 let mut regions = HashSet::from([
133 RegionId::from_u64(1),
134 RegionId::from_u64(2),
135 RegionId::from_u64(3),
136 ]);
137 let output = keeper.extract_operating_regions(1, &mut regions);
138 assert_eq!(output.len(), 2);
139
140 assert!(output.contains(&RegionId::from_u64(1)));
141 assert!(output.contains(&RegionId::from_u64(2)));
142 assert_eq!(keeper.len(), 2);
143
144 drop(guard);
145 assert_eq!(keeper.len(), 1);
146 assert!(keeper.contains(1, RegionId::from_u64(2)));
147
148 drop(guard2);
149 assert!(keeper.is_empty());
150 }
151}