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
use crate::{blockcfg::HeaderHash, blockchain::Ref};
use lru::LruCache;
use std::sync::Arc;
use tokio::sync::Mutex;

/// object that store the [`Ref`] in a cache. Every time a [`Ref`]
/// is accessed its TTL will be reset. Once the TTL of [`Ref`] has
/// expired it may be removed from the cache.
///
/// The cache expired [`Ref`] will be removed only if the [`Ref`]'s
/// TTL has expired and [`purge`] has been called and has completed.
///
/// [`Ref`]: ./struct.Ref.html
/// [`purge`]: ./struct.Ref.html#method.purge
#[derive(Clone)]
pub struct RefCache {
    inner: Arc<Mutex<LruCache<HeaderHash, Arc<Ref>>>>,
}

impl RefCache {
    /// create a new `RefCache`.
    ///
    pub fn new(cap: usize) -> Self {
        RefCache {
            inner: Arc::new(Mutex::new(LruCache::new(cap))),
        }
    }

    /// return a future that will attempt to insert the given [`Ref`]
    /// in the cache.
    ///
    /// # Errors
    ///
    /// there is no error possible yet.
    ///
    pub async fn insert(&self, key: HeaderHash, value: Arc<Ref>) {
        let mut guard = self.inner.lock().await;
        guard.put(key, value);
    }

    /// return a future to get a [`Ref`] from the cache
    ///
    /// The future returns `None` if the `Ref` was not found in the
    /// cache. This does not mean the associated block is not in the
    /// blockchain storage. It only means it is not in the cache:
    /// it has not been seen _recently_.
    ///
    /// # Errors
    ///
    /// No error possible yet
    ///
    pub async fn get(&self, key: HeaderHash) -> Option<Arc<Ref>> {
        let mut guard = self.inner.lock().await;
        guard.get(&key).map(Arc::clone)
    }
}