mirror of
https://gitee.com/openharmony/request_request
synced 2024-11-27 00:50:56 +00:00
add queuemap
Signed-off-by: Tiga Ultraman <liaoxude@huawei.com>
This commit is contained in:
parent
fa4d544de9
commit
36638d28c3
12
preload/native/src/cache/manage.rs
vendored
12
preload/native/src/cache/manage.rs
vendored
@ -15,7 +15,7 @@ use std::collections::HashMap;
|
||||
use std::io;
|
||||
use std::sync::{Arc, LazyLock, Mutex, OnceLock, Weak};
|
||||
|
||||
use request_utils::queue_map::QueueMap;
|
||||
use request_utils::lru::LRUCache;
|
||||
|
||||
use super::data::{self, FileCache, RamCache};
|
||||
use crate::agent::TaskId;
|
||||
@ -32,9 +32,9 @@ cfg_test! {
|
||||
}
|
||||
|
||||
pub(crate) struct CacheManager {
|
||||
pub(super) rams: Mutex<QueueMap<TaskId, Arc<RamCache>>>,
|
||||
pub(super) rams: Mutex<LRUCache<TaskId, Arc<RamCache>>>,
|
||||
pub(super) backup_rams: Mutex<HashMap<TaskId, Arc<RamCache>>>,
|
||||
pub(super) files: Mutex<QueueMap<TaskId, FileCache>>,
|
||||
pub(super) files: Mutex<LRUCache<TaskId, FileCache>>,
|
||||
|
||||
pub(super) update_from_file_once:
|
||||
Mutex<HashMap<TaskId, Arc<OnceLock<io::Result<Weak<RamCache>>>>>>,
|
||||
@ -45,8 +45,8 @@ pub(crate) struct CacheManager {
|
||||
impl CacheManager {
|
||||
pub(super) fn new() -> Self {
|
||||
Self {
|
||||
rams: Mutex::new(QueueMap::new()),
|
||||
files: Mutex::new(QueueMap::new()),
|
||||
rams: Mutex::new(LRUCache::new()),
|
||||
files: Mutex::new(LRUCache::new()),
|
||||
backup_rams: Mutex::new(HashMap::new()),
|
||||
update_from_file_once: Mutex::new(HashMap::new()),
|
||||
|
||||
@ -85,7 +85,7 @@ impl CacheManager {
|
||||
|
||||
pub(super) fn apply_cache<T>(
|
||||
handle: &Mutex<data::Handle>,
|
||||
caches: &Mutex<QueueMap<TaskId, T>>,
|
||||
caches: &Mutex<LRUCache<TaskId, T>>,
|
||||
task_id: fn(&T) -> &TaskId,
|
||||
size: usize,
|
||||
) -> bool {
|
||||
|
@ -22,7 +22,7 @@
|
||||
mod macros;
|
||||
|
||||
pub mod fastrand;
|
||||
pub mod queue_map;
|
||||
pub mod lru;
|
||||
|
||||
cfg_not_ohos! {
|
||||
#[macro_use]
|
||||
|
348
request_utils/src/lru.rs
Normal file
348
request_utils/src/lru.rs
Normal file
@ -0,0 +1,348 @@
|
||||
// Copyright (C) 2024 Huawei Device Co., Ltd.
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use std::collections::hash_map::Entry;
|
||||
use std::collections::HashMap;
|
||||
use std::hash::Hash;
|
||||
use std::ptr;
|
||||
|
||||
struct Node<K, V> {
|
||||
key: K,
|
||||
value: V,
|
||||
prev: *mut Node<K, V>,
|
||||
next: *mut Node<K, V>,
|
||||
}
|
||||
|
||||
struct LinkedList<K, V> {
|
||||
head: *mut Node<K, V>,
|
||||
tail: *mut Node<K, V>,
|
||||
}
|
||||
|
||||
impl<K, V> LinkedList<K, V> {
|
||||
fn new() -> Self {
|
||||
LinkedList {
|
||||
head: ptr::null_mut(),
|
||||
tail: ptr::null_mut(),
|
||||
}
|
||||
}
|
||||
|
||||
fn push_front(&mut self, node: *mut Node<K, V>) {
|
||||
unsafe {
|
||||
(*node).prev = ptr::null_mut();
|
||||
(*node).next = self.head;
|
||||
|
||||
if !self.head.is_null() {
|
||||
(*self.head).prev = node;
|
||||
}
|
||||
self.head = node;
|
||||
|
||||
if self.tail.is_null() {
|
||||
self.tail = node;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn remove(&mut self, node: *mut Node<K, V>) {
|
||||
unsafe {
|
||||
if !(*node).prev.is_null() {
|
||||
(*(*node).prev).next = (*node).next;
|
||||
} else {
|
||||
self.head = (*node).next;
|
||||
}
|
||||
|
||||
if !(*node).next.is_null() {
|
||||
(*(*node).next).prev = (*node).prev;
|
||||
} else {
|
||||
self.tail = (*node).prev;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn pop_back(&mut self) -> *mut Node<K, V> {
|
||||
if self.tail.is_null() {
|
||||
return ptr::null_mut();
|
||||
}
|
||||
let node = self.tail;
|
||||
self.remove(node);
|
||||
node
|
||||
}
|
||||
}
|
||||
|
||||
impl<K, V> Drop for LinkedList<K, V> {
|
||||
fn drop(&mut self) {
|
||||
let mut current = self.head;
|
||||
while !current.is_null() {
|
||||
unsafe {
|
||||
let next = (*current).next;
|
||||
let _ = Box::from_raw(current);
|
||||
current = next;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct LRUCache<K, V> {
|
||||
map: HashMap<K, *mut Node<K, V>>,
|
||||
list: LinkedList<K, V>,
|
||||
}
|
||||
|
||||
impl<K: Hash + Eq + Clone, V> LRUCache<K, V> {
|
||||
pub fn new() -> Self {
|
||||
LRUCache {
|
||||
map: HashMap::new(),
|
||||
list: LinkedList::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get(&mut self, key: &K) -> Option<&V> {
|
||||
if let Some(&node) = self.map.get(key) {
|
||||
self.list.remove(node);
|
||||
self.list.push_front(node);
|
||||
unsafe {
|
||||
return Some(&(*node).value);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn get_mut(&mut self, key: &K) -> Option<&mut V> {
|
||||
if let Some(&mut node) = self.map.get_mut(key) {
|
||||
self.list.remove(node);
|
||||
self.list.push_front(node);
|
||||
unsafe {
|
||||
return Some(&mut (*node).value);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, key: K, value: V) -> Option<V> {
|
||||
match self.map.entry(key) {
|
||||
Entry::Occupied(addr) => {
|
||||
self.list.remove(*addr.get());
|
||||
self.list.push_front(*addr.get());
|
||||
unsafe {
|
||||
let old = std::mem::replace(&mut (*(*addr.get())).value, value);
|
||||
Some(old)
|
||||
}
|
||||
}
|
||||
Entry::Vacant(addr) => {
|
||||
let new_node = Box::into_raw(Box::new(Node {
|
||||
key: addr.key().clone(),
|
||||
value,
|
||||
prev: ptr::null_mut(),
|
||||
next: ptr::null_mut(),
|
||||
}));
|
||||
self.list.push_front(new_node);
|
||||
addr.insert(new_node);
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pop(&mut self) -> Option<V> {
|
||||
let old_node = self.list.pop_back();
|
||||
if !old_node.is_null() {
|
||||
unsafe {
|
||||
let old_key = (*old_node).key.clone();
|
||||
self.map.remove(&old_key);
|
||||
let node = Box::from_raw(old_node);
|
||||
Some(node.value)
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn remove(&mut self, key: &K) -> Option<V> {
|
||||
if let Some(node) = self.map.remove(key) {
|
||||
self.list.remove(node);
|
||||
unsafe {
|
||||
let node = Box::from_raw(node);
|
||||
return Some(node.value);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn contains_key(&self, k: &K) -> bool {
|
||||
self.map.contains_key(k)
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.map.is_empty()
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.map.len()
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: Eq + Hash + Clone, V> Default for LRUCache<K, V> {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<K, V> Send for LRUCache<K, V> {}
|
||||
|
||||
#[cfg(test)]
|
||||
mod ut_test {
|
||||
use super::LRUCache;
|
||||
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
struct Cache {
|
||||
data_count: usize,
|
||||
}
|
||||
|
||||
impl Cache {
|
||||
pub(crate) fn from_u(init: usize) -> Self {
|
||||
Cache { data_count: init }
|
||||
}
|
||||
|
||||
pub(crate) fn add(&mut self, num: usize) {
|
||||
self.data_count += num
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ut_test_empty() {
|
||||
let mut cache = LRUCache::<&str, Cache>::new();
|
||||
assert_eq!(None, cache.get(&"key1"));
|
||||
assert_eq!(None, cache.get_mut(&"key1"));
|
||||
assert_eq!(0, cache.len());
|
||||
assert!(!cache.contains_key(&"key1"));
|
||||
assert!(cache.is_empty());
|
||||
assert_eq!(None, cache.pop());
|
||||
assert_eq!(None, cache.remove(&"key1"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ut_test_insert() {
|
||||
let mut cache = LRUCache::new();
|
||||
assert_eq!(None, cache.insert("key1", Cache::from_u(0)));
|
||||
assert_eq!(Some(&Cache::from_u(0)), cache.get(&"key1"));
|
||||
assert_eq!(Some(&mut Cache::from_u(0)), cache.get_mut(&"key1"));
|
||||
assert_eq!(
|
||||
Some(&mut Cache::from_u(1)),
|
||||
cache.get_mut(&"key1").map(|cache| {
|
||||
cache.add(1);
|
||||
cache
|
||||
})
|
||||
);
|
||||
assert_eq!(1, cache.len());
|
||||
assert!(cache.contains_key(&"key1"));
|
||||
assert!(!cache.is_empty());
|
||||
assert_eq!(Some(Cache::from_u(1)), cache.pop());
|
||||
assert_eq!(None, cache.remove(&"key1"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ut_test_insert_dump() {
|
||||
let mut cache = LRUCache::new();
|
||||
cache.insert("key0", Cache::from_u(0));
|
||||
cache.insert("key1", Cache::from_u(1));
|
||||
cache.insert("key2", Cache::from_u(2));
|
||||
cache.insert("key3", Cache::from_u(3));
|
||||
assert_eq!(
|
||||
Some(Cache::from_u(0)),
|
||||
cache.insert("key0", Cache::from_u(4))
|
||||
);
|
||||
assert_eq!(4, cache.len());
|
||||
assert_eq!(Some(Cache::from_u(1)), cache.pop());
|
||||
assert_eq!(None, cache.get(&"key1"));
|
||||
assert_eq!(Some(&Cache::from_u(4)), cache.get(&"key0"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ut_test_pop() {
|
||||
let mut cache = LRUCache::new();
|
||||
cache.insert("key1", Cache::from_u(1));
|
||||
assert_eq!(Some(Cache::from_u(1)), cache.pop());
|
||||
assert_eq!(None, cache.get(&"key1"));
|
||||
assert_eq!(None, cache.get_mut(&"key1"));
|
||||
assert_eq!(0, cache.len());
|
||||
assert!(!cache.contains_key(&"key1"));
|
||||
assert!(cache.is_empty());
|
||||
assert_eq!(None, cache.pop());
|
||||
assert_eq!(None, cache.remove(&"key1"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ut_test_pop_remaining() {
|
||||
let mut cache = LRUCache::new();
|
||||
cache.insert("key0", Cache::from_u(0));
|
||||
cache.insert("key1", Cache::from_u(1));
|
||||
cache.insert("key2", Cache::from_u(2));
|
||||
cache.insert("key3", Cache::from_u(3));
|
||||
assert_eq!(Some(Cache::from_u(0)), cache.pop());
|
||||
assert_eq!(None, cache.get(&"key0"));
|
||||
assert_eq!(None, cache.get_mut(&"key0"));
|
||||
assert_eq!(3, cache.len());
|
||||
assert!(!cache.contains_key(&"key0"));
|
||||
assert!(!cache.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ut_test_remove() {
|
||||
let mut cache = LRUCache::new();
|
||||
cache.insert("key1", Cache::from_u(1));
|
||||
assert_eq!(Some(Cache::from_u(1)), cache.remove(&"key1"));
|
||||
assert_eq!(None, cache.get(&"key1"));
|
||||
assert_eq!(None, cache.get_mut(&"key1"));
|
||||
assert_eq!(0, cache.len());
|
||||
assert!(!cache.contains_key(&"key1"));
|
||||
assert!(cache.is_empty());
|
||||
assert_eq!(None, cache.pop());
|
||||
assert_eq!(None, cache.remove(&"key1"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ut_test_remove_remaining() {
|
||||
let mut cache = LRUCache::new();
|
||||
cache.insert("key0", Cache::from_u(0));
|
||||
cache.insert("key1", Cache::from_u(1));
|
||||
cache.insert("key2", Cache::from_u(2));
|
||||
cache.insert("key3", Cache::from_u(3));
|
||||
assert_eq!(Some(Cache::from_u(1)), cache.remove(&"key1"));
|
||||
assert_eq!(None, cache.get(&"key1"));
|
||||
assert_eq!(None, cache.get_mut(&"key1"));
|
||||
assert_eq!(3, cache.len());
|
||||
assert!(!cache.contains_key(&"key1"));
|
||||
assert!(!cache.is_empty());
|
||||
assert_eq!(None, cache.remove(&"key1"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ut_test_insert_after_pop() {
|
||||
let mut cache = LRUCache::new();
|
||||
cache.insert("key0", Cache::from_u(0));
|
||||
cache.insert("key1", Cache::from_u(1));
|
||||
assert_eq!(Some(Cache::from_u(0)), cache.pop());
|
||||
cache.insert("key0", Cache::from_u(0));
|
||||
assert_eq!(Some(&Cache::from_u(0)), cache.get(&"key0"));
|
||||
assert_eq!(Some(&mut Cache::from_u(0)), cache.get_mut(&"key0"));
|
||||
assert_eq!(
|
||||
Some(&mut Cache::from_u(4)),
|
||||
cache.get_mut(&"key0").map(|cache| {
|
||||
cache.add(4);
|
||||
cache
|
||||
})
|
||||
);
|
||||
assert_eq!(Some(&Cache::from_u(4)), cache.get(&"key0"));
|
||||
assert_eq!(2, cache.len());
|
||||
assert!(cache.contains_key(&"key0"));
|
||||
assert!(!cache.is_empty());
|
||||
assert_eq!(Some(Cache::from_u(1)), cache.pop());
|
||||
}
|
||||
}
|
@ -1,132 +0,0 @@
|
||||
// Copyright (C) 2024 Huawei Device Co., Ltd.
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use std::collections::{HashMap, HashSet, VecDeque};
|
||||
use std::hash::Hash;
|
||||
pub struct QueueMap<K, V> {
|
||||
map: HashMap<K, V>,
|
||||
v: VecDeque<K>,
|
||||
removed: HashSet<K>,
|
||||
}
|
||||
|
||||
impl<K: Eq + Hash + Clone, V> QueueMap<K, V> {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
map: HashMap::new(),
|
||||
v: VecDeque::new(),
|
||||
removed: HashSet::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pop(&mut self) -> Option<V> {
|
||||
while let Some(n) = self.v.pop_front() {
|
||||
if !self.removed.remove(&n) {
|
||||
let ret = self.map.remove(&n);
|
||||
self.removed.insert(n);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, k: K, v: V) -> Option<V> {
|
||||
self.removed.remove(&k);
|
||||
self.v.push_back(k.clone());
|
||||
self.map.insert(k, v)
|
||||
}
|
||||
|
||||
pub fn get(&self, k: &K) -> Option<&V> {
|
||||
self.map.get(k)
|
||||
}
|
||||
|
||||
pub fn contains_key(&self, k: &K) -> bool {
|
||||
self.map.contains_key(k)
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.map.is_empty()
|
||||
}
|
||||
|
||||
pub fn remove(&mut self, k: &K) -> Option<V> {
|
||||
if let Some(t) = self.map.remove(k) {
|
||||
self.removed.insert(k.clone());
|
||||
Some(t)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.map.len()
|
||||
}
|
||||
|
||||
pub fn get_mut(&mut self, k: &K) -> Option<&mut V> {
|
||||
self.map.get_mut(k)
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: Eq + Hash + Clone, V> Default for QueueMap<K, V> {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::QueueMap;
|
||||
|
||||
#[test]
|
||||
fn ut_queue_map_fifo() {
|
||||
let mut map = QueueMap::new();
|
||||
map.insert(1, 1);
|
||||
map.insert(2, 2);
|
||||
assert!(map.contains_key(&1));
|
||||
assert_eq!(map.pop().unwrap(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ut_queue_map_remove() {
|
||||
let mut map = QueueMap::new();
|
||||
map.insert(1, 1);
|
||||
map.insert(2, 2);
|
||||
map.insert(3, 3);
|
||||
map.insert(4, 4);
|
||||
map.remove(&1);
|
||||
map.remove(&2);
|
||||
map.remove(&3);
|
||||
map.insert(3, 3);
|
||||
assert_eq!(map.pop().unwrap(), 3);
|
||||
assert_eq!(map.pop().unwrap(), 4);
|
||||
map.insert(1, 1);
|
||||
map.insert(2, 2);
|
||||
assert_eq!(map.pop().unwrap(), 1);
|
||||
assert_eq!(map.pop().unwrap(), 2);
|
||||
assert!(map.pop().is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ut_queue_map_same_key() {
|
||||
let mut map = QueueMap::new();
|
||||
map.insert(1, 1);
|
||||
map.insert(1, 2);
|
||||
assert_eq!(map.pop().unwrap(), 2);
|
||||
assert!(map.pop().is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ut_queue_map_insert_get() {
|
||||
let mut map = QueueMap::new();
|
||||
map.insert(1, 1);
|
||||
assert_eq!(1, *map.get(&1).unwrap());
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user