ndn_store/
content_store.rs1use std::future::Future;
2use std::pin::Pin;
3use std::sync::Arc;
4
5use bytes::Bytes;
6
7use ndn_packet::{Interest, Name};
8
9#[derive(Clone, Debug)]
14pub struct CsEntry {
15 pub data: Bytes,
17 pub stale_at: u64,
19 pub name: Arc<Name>,
21}
22
23impl CsEntry {
24 pub fn is_fresh(&self, now_ns: u64) -> bool {
25 self.stale_at > now_ns
26 }
27}
28
29pub struct CsMeta {
31 pub stale_at: u64,
33}
34
35#[derive(Debug, Clone, Copy, PartialEq, Eq)]
37pub enum InsertResult {
38 Inserted,
40 Replaced,
42 Skipped,
44}
45
46#[derive(Debug, Clone, Copy)]
48pub struct CsCapacity {
49 pub max_bytes: usize,
51}
52
53impl CsCapacity {
54 pub fn zero() -> Self {
55 Self { max_bytes: 0 }
56 }
57 pub fn bytes(n: usize) -> Self {
58 Self { max_bytes: n }
59 }
60}
61
62#[derive(Debug, Clone, Copy, Default)]
64pub struct CsStats {
65 pub hits: u64,
66 pub misses: u64,
67 pub inserts: u64,
68 pub evictions: u64,
69}
70
71pub trait ContentStore: Send + Sync + 'static {
77 fn get(&self, interest: &Interest) -> impl Future<Output = Option<CsEntry>> + Send;
80
81 fn insert(
83 &self,
84 data: Bytes,
85 name: Arc<Name>,
86 meta: CsMeta,
87 ) -> impl Future<Output = InsertResult> + Send;
88
89 fn evict(&self, name: &Name) -> impl Future<Output = bool> + Send;
91
92 fn capacity(&self) -> CsCapacity;
94
95 fn len(&self) -> usize {
97 0
98 }
99
100 fn is_empty(&self) -> bool {
102 self.len() == 0
103 }
104
105 fn current_bytes(&self) -> usize {
107 0
108 }
109
110 fn set_capacity(&self, _max_bytes: usize) {}
112
113 fn variant_name(&self) -> &str {
115 "unknown"
116 }
117
118 fn evict_prefix(
121 &self,
122 _prefix: &Name,
123 _limit: Option<usize>,
124 ) -> impl Future<Output = usize> + Send {
125 async { 0 }
126 }
127
128 fn stats(&self) -> CsStats {
130 CsStats::default()
131 }
132}
133
134pub trait ErasedContentStore: Send + Sync + 'static {
142 fn get_erased<'a>(
143 &'a self,
144 interest: &'a Interest,
145 ) -> Pin<Box<dyn Future<Output = Option<CsEntry>> + Send + 'a>>;
146
147 fn insert_erased(
148 &self,
149 data: Bytes,
150 name: Arc<Name>,
151 meta: CsMeta,
152 ) -> Pin<Box<dyn Future<Output = InsertResult> + Send + '_>>;
153
154 fn evict_erased<'a>(
155 &'a self,
156 name: &'a Name,
157 ) -> Pin<Box<dyn Future<Output = bool> + Send + 'a>>;
158
159 fn evict_prefix_erased<'a>(
160 &'a self,
161 prefix: &'a Name,
162 limit: Option<usize>,
163 ) -> Pin<Box<dyn Future<Output = usize> + Send + 'a>>;
164
165 fn capacity(&self) -> CsCapacity;
166 fn set_capacity(&self, max_bytes: usize);
167 fn len(&self) -> usize;
168 fn is_empty(&self) -> bool;
169 fn current_bytes(&self) -> usize;
170 fn variant_name(&self) -> &str;
171 fn stats(&self) -> CsStats;
172}
173
174impl<T: ContentStore> ErasedContentStore for T {
175 fn get_erased<'a>(
176 &'a self,
177 interest: &'a Interest,
178 ) -> Pin<Box<dyn Future<Output = Option<CsEntry>> + Send + 'a>> {
179 Box::pin(self.get(interest))
180 }
181
182 fn insert_erased(
183 &self,
184 data: Bytes,
185 name: Arc<Name>,
186 meta: CsMeta,
187 ) -> Pin<Box<dyn Future<Output = InsertResult> + Send + '_>> {
188 Box::pin(self.insert(data, name, meta))
189 }
190
191 fn evict_erased<'a>(
192 &'a self,
193 name: &'a Name,
194 ) -> Pin<Box<dyn Future<Output = bool> + Send + 'a>> {
195 Box::pin(self.evict(name))
196 }
197
198 fn evict_prefix_erased<'a>(
199 &'a self,
200 prefix: &'a Name,
201 limit: Option<usize>,
202 ) -> Pin<Box<dyn Future<Output = usize> + Send + 'a>> {
203 Box::pin(self.evict_prefix(prefix, limit))
204 }
205
206 fn capacity(&self) -> CsCapacity {
207 ContentStore::capacity(self)
208 }
209
210 fn set_capacity(&self, max_bytes: usize) {
211 ContentStore::set_capacity(self, max_bytes)
212 }
213
214 fn len(&self) -> usize {
215 ContentStore::len(self)
216 }
217
218 fn is_empty(&self) -> bool {
219 ContentStore::is_empty(self)
220 }
221
222 fn current_bytes(&self) -> usize {
223 ContentStore::current_bytes(self)
224 }
225
226 fn variant_name(&self) -> &str {
227 ContentStore::variant_name(self)
228 }
229
230 fn stats(&self) -> CsStats {
231 ContentStore::stats(self)
232 }
233}
234
235pub trait CsAdmissionPolicy: Send + Sync + 'static {
242 fn should_admit(&self, data: &ndn_packet::Data) -> bool;
244}
245
246pub struct DefaultAdmissionPolicy;
253
254impl CsAdmissionPolicy for DefaultAdmissionPolicy {
255 fn should_admit(&self, data: &ndn_packet::Data) -> bool {
256 matches!(
257 data.meta_info().and_then(|m| m.freshness_period),
258 Some(d) if !d.is_zero()
259 )
260 }
261}
262
263pub struct AdmitAllPolicy;
266
267impl CsAdmissionPolicy for AdmitAllPolicy {
268 fn should_admit(&self, _: &ndn_packet::Data) -> bool {
269 true
270 }
271}
272
273pub struct NullCs;
275
276impl ContentStore for NullCs {
277 async fn get(&self, _: &Interest) -> Option<CsEntry> {
278 None
279 }
280 async fn insert(&self, _: Bytes, _: Arc<Name>, _: CsMeta) -> InsertResult {
281 InsertResult::Skipped
282 }
283 async fn evict(&self, _: &Name) -> bool {
284 false
285 }
286 fn capacity(&self) -> CsCapacity {
287 CsCapacity::zero()
288 }
289 fn variant_name(&self) -> &str {
290 "null"
291 }
292}