1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
use std::{collections::BTreeMap, sync::Arc};
use tokio::sync::Mutex;
use crate::fnv1a_64;
use super::action::Data;
/// Data caching module.
///
/// # Values
///
/// * `data: BTreeMap<u64, Data>` - Cache data;
/// * `keys: Vec<String>` - Stored keys.
///
/// # Notice
///
/// All `Keys` encode in fnv1a_64.
///
/// A cache is a simple set of `Key`=`Value`.
/// A `key` is a unique string, but can be grouped by pattern.
/// To do this, you need to insert the symbol `:` into the line.
/// This does not change the logic of the cache in any way, other than removing data from it.
///
/// If `key` ends with a `:`, all data beginning with that key is deleted.
///
/// # Security
///
/// With a large cache, the `del` operation can block it for a long time.
#[derive(Debug)]
pub struct Cache {
/// Cache data.
data: BTreeMap<i64, Data>,
/// Stored keys.
keys: Vec<String>,
}
impl Cache {
/// Initializes data caching module
pub async fn new() -> Arc<Mutex<Cache>> {
Arc::new(Mutex::new(Cache {
data: BTreeMap::new(),
keys: Vec::new(),
}))
}
/// Returns cloned data
pub async fn get(cache: Arc<Mutex<Cache>>, key: &str) -> Option<Data> {
let key = fnv1a_64(key);
let c = cache.lock().await;
let d = c.data.get(&key);
d.cloned()
}
/// Inserts a data
pub async fn set(cache: Arc<Mutex<Cache>>, key: String, data: Data) {
let key_u64 = fnv1a_64(&key);
let mut c = cache.lock().await;
if c.data.insert(key_u64, data).is_none() {
c.keys.push(key);
}
}
/// Removes a key.
///
/// If `key` ends with a `:` character, all data beginning with that `key` is deleted.
///
/// # Safety
///
/// With a large cache, this operation can block it for a long time.
pub async fn del(cache: Arc<Mutex<Cache>>, key: &str) {
if key.ends_with(':') {
let mut c = cache.lock().await;
let mut vec = Vec::with_capacity(c.keys.len());
c.keys.retain(|v| {
if v.starts_with(key) {
vec.push(fnv1a_64(v));
false
} else {
true
}
});
for key in vec {
c.data.remove(&key);
}
} else {
let key_u64 = fnv1a_64(key);
let mut c = cache.lock().await;
if c.data.remove(&key_u64).is_some() {
c.keys.retain(|v| v != key);
}
}
}
/// Clear all cache
pub async fn clear(cache: Arc<Mutex<Cache>>) {
let mut c = cache.lock().await;
c.data.clear();
c.keys.clear();
}
}