Skip to main content

wp_knowledge/
cache.rs

1use std::collections::HashMap;
2use std::net::IpAddr;
3use std::num::NonZeroUsize;
4
5use lru::LruCache;
6use wp_model_core::model::{DataField, FValueStr, Value};
7
8#[derive(Debug, Clone)]
9pub struct FieldQueryCache {
10    str_idx: HashMap<FValueStr, usize>,
11    i64_idx: HashMap<i64, usize>,
12    ip_idx: HashMap<IpAddr, usize>,
13    cache_data: LruCache<LocalCacheKey, Vec<DataField>>,
14    idx_num: usize,
15    generation: Option<u64>,
16}
17
18pub type QueryLocalCache = FieldQueryCache;
19
20impl Default for FieldQueryCache {
21    fn default() -> Self {
22        Self::with_capacity(100)
23    }
24}
25
26impl FieldQueryCache {
27    pub fn with_capacity(size: usize) -> Self {
28        let size = size.max(1);
29        Self {
30            str_idx: HashMap::new(),
31            i64_idx: HashMap::new(),
32            ip_idx: HashMap::new(),
33            cache_data: LruCache::new(NonZeroUsize::new(size).expect("non-zero cache size")),
34            idx_num: 0,
35            generation: None,
36        }
37    }
38
39    fn get_idx(&self, param: &DataField) -> Option<usize> {
40        match param.get_value() {
41            Value::Chars(v) => self.str_idx.get(v).copied(),
42            Value::Digit(v) => self.i64_idx.get(v).copied(),
43            Value::IpAddr(v) => self.ip_idx.get(v).copied(),
44            _ => None,
45        }
46    }
47
48    fn try_up_idx(&mut self, param: &DataField) -> Option<usize> {
49        match param.get_value() {
50            Value::Chars(v) => {
51                if let Some(idx) = self.str_idx.get(v) {
52                    Some(*idx)
53                } else {
54                    self.idx_num += 1;
55                    self.str_idx.insert(v.clone(), self.idx_num);
56                    Some(self.idx_num)
57                }
58            }
59            Value::Digit(v) => {
60                if let Some(idx) = self.i64_idx.get(v) {
61                    Some(*idx)
62                } else {
63                    self.idx_num += 1;
64                    self.i64_idx.insert(*v, self.idx_num);
65                    Some(self.idx_num)
66                }
67            }
68            Value::IpAddr(v) => {
69                if let Some(idx) = self.ip_idx.get(v) {
70                    Some(*idx)
71                } else {
72                    self.idx_num += 1;
73                    self.ip_idx.insert(*v, self.idx_num);
74                    Some(self.idx_num)
75                }
76            }
77            _ => None,
78        }
79    }
80
81    fn reset(&mut self) {
82        self.str_idx.clear();
83        self.i64_idx.clear();
84        self.ip_idx.clear();
85        self.cache_data.clear();
86        self.idx_num = 0;
87    }
88}
89
90#[derive(PartialEq, Eq, Hash, Debug, Clone)]
91pub enum EnumSizeIndex {
92    Idx1(usize),
93    Idx2(usize, usize),
94    Idx3(usize, usize, usize),
95    Idx4(usize, usize, usize, usize),
96    Idx5(usize, usize, usize, usize, usize),
97    Idx6(usize, usize, usize, usize, usize, usize),
98}
99
100#[derive(PartialEq, Eq, Hash, Debug, Clone)]
101struct LocalCacheKey {
102    scope_hash: u64,
103    idxs: EnumSizeIndex,
104}
105
106pub trait CacheAble<P, T, const N: usize> {
107    fn prepare_generation(&mut self, _generation: u64) {}
108    fn save_scoped(&mut self, _scope_hash: u64, params: &[P; N], result: T) {
109        self.save(params, result);
110    }
111    fn fetch_scoped(&self, _scope_hash: u64, params: &[P; N]) -> Option<&T> {
112        self.fetch(params)
113    }
114    fn save(&mut self, params: &[P; N], result: T);
115    fn fetch(&self, params: &[P; N]) -> Option<&T>;
116}
117
118impl CacheAble<DataField, Vec<DataField>, 1> for FieldQueryCache {
119    fn prepare_generation(&mut self, generation: u64) {
120        if self.generation != Some(generation) {
121            self.reset();
122            self.generation = Some(generation);
123        }
124    }
125    fn save_scoped(&mut self, scope_hash: u64, params: &[DataField; 1], result: Vec<DataField>) {
126        if let Some(i0) = self.try_up_idx(&params[0]) {
127            self.cache_data.put(
128                LocalCacheKey {
129                    scope_hash,
130                    idxs: EnumSizeIndex::Idx1(i0),
131                },
132                result,
133            );
134        }
135    }
136
137    fn fetch_scoped(&self, scope_hash: u64, params: &[DataField; 1]) -> Option<&Vec<DataField>> {
138        if let Some(i0) = self.get_idx(&params[0]) {
139            return self.cache_data.peek(&LocalCacheKey {
140                scope_hash,
141                idxs: EnumSizeIndex::Idx1(i0),
142            });
143        }
144        None
145    }
146
147    fn save(&mut self, params: &[DataField; 1], result: Vec<DataField>) {
148        self.save_scoped(0, params, result);
149    }
150
151    fn fetch(&self, params: &[DataField; 1]) -> Option<&Vec<DataField>> {
152        self.fetch_scoped(0, params)
153    }
154}
155
156impl CacheAble<DataField, Vec<DataField>, 2> for FieldQueryCache {
157    fn prepare_generation(&mut self, generation: u64) {
158        if self.generation != Some(generation) {
159            self.reset();
160            self.generation = Some(generation);
161        }
162    }
163
164    fn save_scoped(&mut self, scope_hash: u64, params: &[DataField; 2], result: Vec<DataField>) {
165        if let (Some(i0), Some(i1)) = (self.try_up_idx(&params[0]), self.try_up_idx(&params[1])) {
166            self.cache_data.put(
167                LocalCacheKey {
168                    scope_hash,
169                    idxs: EnumSizeIndex::Idx2(i0, i1),
170                },
171                result,
172            );
173        }
174    }
175
176    fn fetch_scoped(&self, scope_hash: u64, params: &[DataField; 2]) -> Option<&Vec<DataField>> {
177        if let (Some(i0), Some(i1)) = (self.get_idx(&params[0]), self.get_idx(&params[1])) {
178            return self.cache_data.peek(&LocalCacheKey {
179                scope_hash,
180                idxs: EnumSizeIndex::Idx2(i0, i1),
181            });
182        }
183        None
184    }
185
186    fn save(&mut self, params: &[DataField; 2], result: Vec<DataField>) {
187        self.save_scoped(0, params, result);
188    }
189
190    fn fetch(&self, params: &[DataField; 2]) -> Option<&Vec<DataField>> {
191        self.fetch_scoped(0, params)
192    }
193}
194
195impl CacheAble<DataField, Vec<DataField>, 3> for FieldQueryCache {
196    fn prepare_generation(&mut self, generation: u64) {
197        if self.generation != Some(generation) {
198            self.reset();
199            self.generation = Some(generation);
200        }
201    }
202
203    fn save_scoped(&mut self, scope_hash: u64, params: &[DataField; 3], result: Vec<DataField>) {
204        if let (Some(i0), Some(i1), Some(i2)) = (
205            self.try_up_idx(&params[0]),
206            self.try_up_idx(&params[1]),
207            self.try_up_idx(&params[2]),
208        ) {
209            self.cache_data.put(
210                LocalCacheKey {
211                    scope_hash,
212                    idxs: EnumSizeIndex::Idx3(i0, i1, i2),
213                },
214                result,
215            );
216        }
217    }
218
219    fn fetch_scoped(&self, scope_hash: u64, params: &[DataField; 3]) -> Option<&Vec<DataField>> {
220        if let (Some(i0), Some(i1), Some(i2)) = (
221            self.get_idx(&params[0]),
222            self.get_idx(&params[1]),
223            self.get_idx(&params[2]),
224        ) {
225            return self.cache_data.peek(&LocalCacheKey {
226                scope_hash,
227                idxs: EnumSizeIndex::Idx3(i0, i1, i2),
228            });
229        }
230        None
231    }
232
233    fn save(&mut self, params: &[DataField; 3], result: Vec<DataField>) {
234        self.save_scoped(0, params, result);
235    }
236
237    fn fetch(&self, params: &[DataField; 3]) -> Option<&Vec<DataField>> {
238        self.fetch_scoped(0, params)
239    }
240}
241
242impl CacheAble<DataField, Vec<DataField>, 4> for FieldQueryCache {
243    fn prepare_generation(&mut self, generation: u64) {
244        if self.generation != Some(generation) {
245            self.reset();
246            self.generation = Some(generation);
247        }
248    }
249
250    fn save_scoped(&mut self, scope_hash: u64, params: &[DataField; 4], result: Vec<DataField>) {
251        if let (Some(i0), Some(i1), Some(i2), Some(i3)) = (
252            self.try_up_idx(&params[0]),
253            self.try_up_idx(&params[1]),
254            self.try_up_idx(&params[2]),
255            self.try_up_idx(&params[3]),
256        ) {
257            self.cache_data.put(
258                LocalCacheKey {
259                    scope_hash,
260                    idxs: EnumSizeIndex::Idx4(i0, i1, i2, i3),
261                },
262                result,
263            );
264        }
265    }
266
267    fn fetch_scoped(&self, scope_hash: u64, params: &[DataField; 4]) -> Option<&Vec<DataField>> {
268        if let (Some(i0), Some(i1), Some(i2), Some(i3)) = (
269            self.get_idx(&params[0]),
270            self.get_idx(&params[1]),
271            self.get_idx(&params[2]),
272            self.get_idx(&params[3]),
273        ) {
274            return self.cache_data.peek(&LocalCacheKey {
275                scope_hash,
276                idxs: EnumSizeIndex::Idx4(i0, i1, i2, i3),
277            });
278        }
279        None
280    }
281
282    fn save(&mut self, params: &[DataField; 4], result: Vec<DataField>) {
283        self.save_scoped(0, params, result);
284    }
285
286    fn fetch(&self, params: &[DataField; 4]) -> Option<&Vec<DataField>> {
287        self.fetch_scoped(0, params)
288    }
289}
290
291impl CacheAble<DataField, Vec<DataField>, 5> for FieldQueryCache {
292    fn prepare_generation(&mut self, generation: u64) {
293        if self.generation != Some(generation) {
294            self.reset();
295            self.generation = Some(generation);
296        }
297    }
298
299    fn save_scoped(&mut self, scope_hash: u64, params: &[DataField; 5], result: Vec<DataField>) {
300        if let (Some(i0), Some(i1), Some(i2), Some(i3), Some(i4)) = (
301            self.try_up_idx(&params[0]),
302            self.try_up_idx(&params[1]),
303            self.try_up_idx(&params[2]),
304            self.try_up_idx(&params[3]),
305            self.try_up_idx(&params[4]),
306        ) {
307            self.cache_data.put(
308                LocalCacheKey {
309                    scope_hash,
310                    idxs: EnumSizeIndex::Idx5(i0, i1, i2, i3, i4),
311                },
312                result,
313            );
314        }
315    }
316
317    fn fetch_scoped(&self, scope_hash: u64, params: &[DataField; 5]) -> Option<&Vec<DataField>> {
318        if let (Some(i0), Some(i1), Some(i2), Some(i3), Some(i4)) = (
319            self.get_idx(&params[0]),
320            self.get_idx(&params[1]),
321            self.get_idx(&params[2]),
322            self.get_idx(&params[3]),
323            self.get_idx(&params[4]),
324        ) {
325            return self.cache_data.peek(&LocalCacheKey {
326                scope_hash,
327                idxs: EnumSizeIndex::Idx5(i0, i1, i2, i3, i4),
328            });
329        }
330        None
331    }
332
333    fn save(&mut self, params: &[DataField; 5], result: Vec<DataField>) {
334        self.save_scoped(0, params, result);
335    }
336
337    fn fetch(&self, params: &[DataField; 5]) -> Option<&Vec<DataField>> {
338        self.fetch_scoped(0, params)
339    }
340}
341
342impl CacheAble<DataField, Vec<DataField>, 6> for FieldQueryCache {
343    fn prepare_generation(&mut self, generation: u64) {
344        if self.generation != Some(generation) {
345            self.reset();
346            self.generation = Some(generation);
347        }
348    }
349
350    fn save_scoped(&mut self, scope_hash: u64, params: &[DataField; 6], result: Vec<DataField>) {
351        if let (Some(i0), Some(i1), Some(i2), Some(i3), Some(i4), Some(i5)) = (
352            self.try_up_idx(&params[0]),
353            self.try_up_idx(&params[1]),
354            self.try_up_idx(&params[2]),
355            self.try_up_idx(&params[3]),
356            self.try_up_idx(&params[4]),
357            self.try_up_idx(&params[5]),
358        ) {
359            self.cache_data.put(
360                LocalCacheKey {
361                    scope_hash,
362                    idxs: EnumSizeIndex::Idx6(i0, i1, i2, i3, i4, i5),
363                },
364                result,
365            );
366        }
367    }
368
369    fn fetch_scoped(&self, scope_hash: u64, params: &[DataField; 6]) -> Option<&Vec<DataField>> {
370        if let (Some(i0), Some(i1), Some(i2), Some(i3), Some(i4), Some(i5)) = (
371            self.get_idx(&params[0]),
372            self.get_idx(&params[1]),
373            self.get_idx(&params[2]),
374            self.get_idx(&params[3]),
375            self.get_idx(&params[4]),
376            self.get_idx(&params[5]),
377        ) {
378            return self.cache_data.peek(&LocalCacheKey {
379                scope_hash,
380                idxs: EnumSizeIndex::Idx6(i0, i1, i2, i3, i4, i5),
381            });
382        }
383        None
384    }
385
386    fn save(&mut self, params: &[DataField; 6], result: Vec<DataField>) {
387        self.save_scoped(0, params, result);
388    }
389
390    fn fetch(&self, params: &[DataField; 6]) -> Option<&Vec<DataField>> {
391        self.fetch_scoped(0, params)
392    }
393}