1use std::collections::{HashMap, HashSet};
2use xxhash_rust::xxh3::xxh3_64;
3
4pub enum Direction {
5 Forward,
6 Backward,
7}
8
9pub struct HashRing {
10 replicas: usize,
11 sorted_keys: Vec<u64>,
12 hash_map: HashMap<u64, String>,
13}
14
15impl HashRing {
16 pub fn new_with_replicas(replicas: usize) -> Self {
17 HashRing {
18 replicas,
19 sorted_keys: Vec::new(),
20 hash_map: HashMap::new(),
21 }
22 }
23
24 pub fn is_empty(&self) -> bool {
25 self.sorted_keys.is_empty()
26 }
27
28 fn generate_hash(&self, key: &str, i: usize) -> u64 {
29 let mut s = String::with_capacity(key.len() + 10);
30 s.push_str(key);
31 s.push_str(i.to_string().as_str());
32 xxh3_64(s.as_bytes())
33 }
34
35 pub fn add(&mut self, keys: &[String]) {
36 for key in keys {
37 for i in 0..self.replicas {
38 let hash = self.generate_hash(key, i);
39 self.sorted_keys.push(hash);
40 self.hash_map.insert(hash, key.clone());
41 }
42 }
43
44 self.sorted_keys.sort_unstable();
46 }
47
48 pub fn remove(&mut self, key: &str) {
49 let mut i = 0;
50 while i < self.sorted_keys.len() {
51 let hash_key = &self.hash_map[&self.sorted_keys[i]];
52 if hash_key == key {
53 let hash = self.sorted_keys.remove(i);
54 self.hash_map.remove(&hash);
55 } else {
56 i += 1;
57 }
58 }
59 }
60
61 pub fn get(&self, key: &str) -> Option<&String> {
63 if self.is_empty() {
64 return None;
65 }
66
67 let hash = xxh3_64(key.as_bytes());
68 let idx = match self.sorted_keys.binary_search(&hash) {
69 Ok(idx) => idx,
71 Err(idx) => idx % self.sorted_keys.len(),
73 };
74
75 Some(&self.hash_map[&self.sorted_keys[idx]])
76 }
77
78 pub fn get_n(&self, key: &str, n: usize, direction: Direction) -> Vec<String> {
82 let mut result: Vec<String> = Vec::new();
83 let mut _node_map:HashSet<String> = HashSet::new();
84
85 if self.is_empty() || n == 0 {
86 return result;
87 }
88
89 let hash = xxh3_64(key.as_bytes());
90 let idx = match self.sorted_keys.binary_search(&hash) {
91 Ok(idx) => idx,
93 Err(idx) => idx % self.sorted_keys.len(),
95 };
96
97 let mut current_idx = idx;
98 while result.len() < n {
99 let node = &self.hash_map[&self.sorted_keys[current_idx]];
100 if _node_map.insert(node.clone()) {
101 result.push(node.clone());
102 }
103
104 match direction {
105 Direction::Forward => {
106 current_idx = (current_idx + 1) % self.sorted_keys.len();
107 }
108 Direction::Backward => {
109 if current_idx == 0 {
110 current_idx = self.sorted_keys.len() - 1;
111 } else {
112 current_idx -= 1;
113 }
114 }
115 }
116
117 if current_idx == idx {
119 break;
120 }
121 }
122
123 result
124 }
125
126}