Skip to main content

fast_cache/storage/embedded_store_shared/
point.rs

1use super::*;
2
3impl<const SHARDS: usize> SharedEmbeddedStore<SHARDS> {
4    /// Returns a borrowed value guard for `key`.
5    #[inline(always)]
6    pub fn get(&self, key: &[u8]) -> Option<Ref<'_>> {
7        let route = self.route_key(key);
8        let guard = self.stripe(route.shard_id).read();
9        let value = if guard.has_no_ttl_entries() {
10            guard.get_ref_hashed_shared_no_ttl(route.key_hash, key)?
11        } else {
12            guard.get_ref_hashed_shared(route.key_hash, key, ttl_now_millis())?
13        } as *const [u8];
14        Some(Ref {
15            guard,
16            value,
17            _not_send: PhantomData,
18        })
19    }
20
21    /// Returns a mutable guard for `key`.
22    #[inline(always)]
23    pub fn get_mut(&self, key: &[u8]) -> Option<RefMut<'_>> {
24        let route = self.route_key(key);
25        let guard = self.stripe(route.shard_id).write();
26        let contains = if guard.has_no_ttl_entries() {
27            guard.contains_key_hashed_no_ttl(route.key_hash, key)
28        } else {
29            guard.contains_key_hashed(route.key_hash, key, ttl_now_millis())
30        };
31        if !contains {
32            return None;
33        }
34        Some(RefMut {
35            guard,
36            route_mode: self.inner.route_mode,
37            key: SharedBytes::copy_from_slice(key),
38            key_hash: route.key_hash,
39            _not_send: PhantomData,
40        })
41    }
42
43    /// Returns true when `key` is present in point-key storage.
44    #[inline(always)]
45    pub fn contains_key(&self, key: &[u8]) -> bool {
46        let route = self.route_key(key);
47        let guard = self.stripe(route.shard_id).read();
48        if guard.has_no_ttl_entries() {
49            guard.contains_key_hashed_no_ttl(route.key_hash, key)
50        } else {
51            guard.contains_key_hashed(route.key_hash, key, ttl_now_millis())
52        }
53    }
54
55    /// Inserts or replaces a point-key value without a TTL.
56    #[inline(always)]
57    pub fn insert(&self, key: SharedBytes, value: SharedBytes) {
58        let route = self.route_key(key.as_ref());
59        self.stripe(route.shard_id)
60            .write()
61            .set_value_bytes_hashed_no_ttl(
62                self.inner.route_mode,
63                route.key_hash,
64                key.as_ref(),
65                value,
66            );
67    }
68
69    /// Inserts or replaces a point-key value with an optional relative TTL.
70    ///
71    /// `ttl_ms` is measured from the current Unix time in milliseconds. Passing
72    /// `None` keeps the no-TTL hot path.
73    #[inline(always)]
74    pub fn insert_with_ttl(&self, key: SharedBytes, value: SharedBytes, ttl_ms: Option<u64>) {
75        let Some(ttl_ms) = ttl_ms else {
76            self.insert(key, value);
77            return;
78        };
79        let now_ms = ttl_now_millis();
80        let expire_at_ms = Some(now_ms.saturating_add(ttl_ms));
81        let route = self.route_key(key.as_ref());
82        self.stripe(route.shard_id).write().set_value_bytes_hashed(
83            self.inner.route_mode,
84            route.key_hash,
85            key.as_ref(),
86            value,
87            expire_at_ms,
88            now_ms,
89        );
90    }
91
92    /// Inserts or replaces a point-key value from borrowed byte slices.
93    #[inline(always)]
94    pub fn insert_slice(&self, key: &[u8], value: &[u8]) {
95        let route = self.route_key(key);
96        self.stripe(route.shard_id).write().set_slice_hashed_no_ttl(
97            self.inner.route_mode,
98            route.key_hash,
99            key,
100            value,
101        );
102    }
103
104    /// Inserts or replaces a point-key value from borrowed bytes with an
105    /// optional relative TTL.
106    ///
107    /// `ttl_ms` is measured from the current Unix time in milliseconds. Passing
108    /// `None` keeps the no-TTL hot path.
109    #[inline(always)]
110    pub fn insert_slice_with_ttl(&self, key: &[u8], value: &[u8], ttl_ms: Option<u64>) {
111        let Some(ttl_ms) = ttl_ms else {
112            self.insert_slice(key, value);
113            return;
114        };
115        let now_ms = ttl_now_millis();
116        let expire_at_ms = Some(now_ms.saturating_add(ttl_ms));
117        let route = self.route_key(key);
118        self.stripe(route.shard_id).write().set_slice_hashed(
119            self.inner.route_mode,
120            route.key_hash,
121            key,
122            value,
123            expire_at_ms,
124            now_ms,
125        );
126    }
127
128    /// Removes a point-key value and returns the stored bytes when present.
129    #[inline(always)]
130    pub fn remove(&self, key: &[u8]) -> Option<SharedBytes> {
131        let route = self.route_key(key);
132        self.stripe(route.shard_id)
133            .write()
134            .remove_value_hashed_no_ttl(route.key_hash, key)
135    }
136
137    /// Locks the routed stripe and returns an occupied or vacant entry.
138    #[inline(always)]
139    pub fn entry(&self, key: SharedBytes) -> Entry<'_> {
140        let route = self.route_key(key.as_ref());
141        let guard = self.stripe(route.shard_id).write();
142        if guard.contains_key_hashed_no_ttl(route.key_hash, key.as_ref()) {
143            Entry::Occupied(RefMut {
144                guard,
145                route_mode: self.inner.route_mode,
146                key,
147                key_hash: route.key_hash,
148                _not_send: PhantomData,
149            })
150        } else {
151            Entry::Vacant(VacantEntry {
152                guard,
153                route_mode: self.inner.route_mode,
154                key,
155                key_hash: route.key_hash,
156                _not_send: PhantomData,
157            })
158        }
159    }
160}