kernel/hil/kv.rs
1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2023.
4
5//! Interface for Key-Value (KV) Stores
6//!
7//! The KV store implementation in Tock has two levels:
8//!
9//! 1. **KV Level**: This level provides a standard key-value interface with
10//! common get/set/add/update/delete operations.
11//!
12//! 2. **KV Permissions Level**: This level mirrors the `KV` interface, but each
13//! call requires storage permissions. This permits implementing access
14//! control permissions with key-value stores in Tock.
15//!
16//! The expected setup inside Tock will look like this:
17//!
18//! ```text
19//! +-----------------------+
20//! | Capsule using K-V |
21//! +-----------------------+
22//!
23//! hil::kv::KVPermissions (this file)
24//!
25//! +-----------------------+
26//! | K-V in Tock |
27//! +-----------------------+
28//!
29//! hil::kv::KV (this file)
30//!
31//! +-----------------------+
32//! | K-V library |
33//! +-----------------------+
34//!
35//! hil::flash
36//! ```
37
38use crate::storage_permissions::StoragePermissions;
39use crate::utilities::leasable_buffer::SubSliceMut;
40use crate::ErrorCode;
41
42/// Callback trait for KV stores.
43///
44/// Implement this trait and use `set_client()` to receive callbacks.
45pub trait KVClient {
46 /// This callback is called when the get operation completes.
47 ///
48 /// If there wasn't enough room to store the entire buffer `SIZE` will be
49 /// returned in `result` and the bytes that did fit will be copied into the
50 /// buffer.
51 ///
52 /// ### Return Values
53 ///
54 /// - `result`: `Ok(())` on success
55 /// - `Err(ErrorCode)` on error. Valid `ErrorCode`s:
56 /// - `SIZE`: The value is longer than the provided buffer. The amount of
57 /// the value that fits in the buffer is provided.
58 /// - `NOSUPPORT`: The key could not be found or the caller does not have
59 /// permission to read this key. The data in the `value` buffer is
60 /// meaningless.
61 /// - `FAIL`: An internal error occurred and the operation cannot be
62 /// completed.
63 /// - `key`: The key buffer.
64 /// - `value`: The value buffer.
65 fn get_complete(
66 &self,
67 result: Result<(), ErrorCode>,
68 key: SubSliceMut<'static, u8>,
69 value: SubSliceMut<'static, u8>,
70 );
71
72 /// This callback is called when the set operation completes.
73 ///
74 /// ### Return Values
75 ///
76 /// - `result`: `Ok(())` on success, `Err(ErrorCode)` on error. Valid
77 /// `ErrorCode`s:
78 /// - `NOSUPPORT`: The caller does not have permission to store this key.
79 /// - `NOMEM`: The key could not be set because the KV store is full.
80 /// - `SIZE`: The key could not be set because the key or value is too
81 /// many bytes.
82 /// - `FAIL`: An internal error occurred and the operation cannot be
83 /// completed.
84 /// - `key`: The key buffer.
85 /// - `value`: The value buffer.
86 fn set_complete(
87 &self,
88 result: Result<(), ErrorCode>,
89 key: SubSliceMut<'static, u8>,
90 value: SubSliceMut<'static, u8>,
91 );
92
93 /// This callback is called when the add operation completes.
94 ///
95 /// ### Return Values
96 ///
97 /// - `result`: `Ok(())` on success, `Err(ErrorCode)` on error. Valid
98 /// `ErrorCode`s:
99 /// - `NOSUPPORT`: The key already exists and cannot be added.
100 /// - `NOMEM`: The key could not be added because the KV store is full.
101 /// - `SIZE`: The key could not be set because the key or value is too
102 /// many bytes.
103 /// - `FAIL`: An internal error occurred and the operation cannot be
104 /// completed.
105 /// - `key`: The key buffer.
106 /// - `value`: The value buffer.
107 fn add_complete(
108 &self,
109 result: Result<(), ErrorCode>,
110 key: SubSliceMut<'static, u8>,
111 value: SubSliceMut<'static, u8>,
112 );
113
114 /// This callback is called when the update operation completes.
115 ///
116 /// ### Return Values
117 ///
118 /// - `result`: `Ok(())` on success, `Err(ErrorCode)` on error. Valid
119 /// `ErrorCode`s:
120 /// - `NOSUPPORT`: The key does not already exist and cannot be modified
121 /// or the caller does not have permission to modify this key.
122 /// - `NOMEM`: The key could not be updated because the KV store is full.
123 /// - `SIZE`: The key could not be set because the key or value is too
124 /// many bytes.
125 /// - `FAIL`: An internal error occurred and the operation cannot be
126 /// completed.
127 /// - `key`: The key buffer.
128 /// - `value`: The value buffer.
129 fn update_complete(
130 &self,
131 result: Result<(), ErrorCode>,
132 key: SubSliceMut<'static, u8>,
133 value: SubSliceMut<'static, u8>,
134 );
135
136 /// This callback is called when the delete operation completes.
137 ///
138 /// ### Return Values
139 ///
140 /// - `result`: `Ok(())` on success, `Err(ErrorCode)` on error. Valid
141 /// `ErrorCode`s:
142 /// - `NOSUPPORT`: The key does not exist or the caller does not have
143 /// permission to delete this key.
144 /// - `FAIL`: An internal error occurred and the operation cannot be
145 /// completed.
146 /// - `key`: The key buffer.
147 fn delete_complete(&self, result: Result<(), ErrorCode>, key: SubSliceMut<'static, u8>);
148
149 /// This callback is called when the garbage collection operation completes.
150 ///
151 /// ### Return Values
152 ///
153 /// - `result`: `Ok(())` on success, `Err(ErrorCode)` on error. Valid
154 /// `ErrorCode`s:
155 /// - `FAIL`: An internal error occurred and the operation cannot be
156 /// completed.
157 fn garbage_collection_complete(&self, result: Result<(), ErrorCode>);
158}
159
160/// Key-Value interface with permissions.
161///
162/// This interface provides access to key-value storage with access control.
163/// Each object is marked with a `write_id` (based on the `StoragePermissions`
164/// used to create it), and all further accesses and modifications to that
165/// object require suitable permissions.
166pub trait KVPermissions<'a> {
167 /// Configure the client for operation callbacks.
168 fn set_client(&self, client: &'a dyn KVClient);
169
170 /// Retrieve a value based on the given key.
171 ///
172 /// ### Arguments
173 ///
174 /// - `key`: The key to identify the k-v pair.
175 /// - `value`: Where the returned value buffer will be stored.
176 /// - `permissions`: The read/write/modify permissions for this access.
177 ///
178 /// ### Return
179 ///
180 /// - On success returns `Ok(())`. A callback will be issued.
181 /// - On error, returns the buffers and:
182 /// - `BUSY`: An operation is already in progress.
183 /// - `FAIL`: An internal error occurred and the operation cannot be
184 /// completed.
185 fn get(
186 &self,
187 key: SubSliceMut<'static, u8>,
188 value: SubSliceMut<'static, u8>,
189 permissions: StoragePermissions,
190 ) -> Result<
191 (),
192 (
193 SubSliceMut<'static, u8>,
194 SubSliceMut<'static, u8>,
195 ErrorCode,
196 ),
197 >;
198
199 /// Store a value based on the given key. If the key does not exist it will
200 /// be added. If the key already exists the value will be updated.
201 ///
202 /// The `value` buffer must have room for a header.
203 ///
204 /// ### Arguments
205 ///
206 /// - `key`: The key to identify the k-v pair.
207 /// - `value`: The value to store. The provided buffer MUST start
208 /// `KVPermissions.header_size()` bytes after the beginning of the buffer
209 /// to enable the implementation to insert a header.
210 /// - `permissions`: The read/write/modify permissions for this access.
211 ///
212 /// ### Return
213 ///
214 /// - On success returns `Ok(())`. A callback will be issued.
215 /// - On error, returns the buffers and:
216 /// - `BUSY`: An operation is already in progress.
217 /// - `SIZE`: There is insufficient room to include the permission header
218 /// in the `value` buffer or the key/value is too large to store.
219 /// - `INVAL`: The caller does not have write permissions.
220 /// - `FAIL`: An internal error occurred and the operation cannot be
221 /// completed.
222 fn set(
223 &self,
224 key: SubSliceMut<'static, u8>,
225 value: SubSliceMut<'static, u8>,
226 permissions: StoragePermissions,
227 ) -> Result<
228 (),
229 (
230 SubSliceMut<'static, u8>,
231 SubSliceMut<'static, u8>,
232 ErrorCode,
233 ),
234 >;
235
236 /// Store a new value based on the given key. If the key does not exist it
237 /// will be added. If the key already exists an error callback will be
238 /// provided.
239 ///
240 /// The `value` buffer must have room for a header.
241 ///
242 /// ### Arguments
243 ///
244 /// - `key`: The key to identify the k-v pair.
245 /// - `value`: The value to store. The provided buffer MUST start
246 /// `KVPermissions.header_size()` bytes after the beginning of the buffer
247 /// to enable the implementation to insert a header.
248 /// - `permissions`: The read/write/modify permissions for this access.
249 ///
250 /// ### Return
251 ///
252 /// - On success returns `Ok(())`. A callback will be issued.
253 /// - On error, returns the buffers and:
254 /// - `BUSY`: An operation is already in progress.
255 /// - `SIZE`: There is insufficient room to include the permission header
256 /// in the `value` buffer or the key/value is too large to store.
257 /// - `INVAL`: The caller does not have write permissions.
258 /// - `FAIL`: An internal error occurred and the operation cannot be
259 /// completed.
260 fn add(
261 &self,
262 key: SubSliceMut<'static, u8>,
263 value: SubSliceMut<'static, u8>,
264 permissions: StoragePermissions,
265 ) -> Result<
266 (),
267 (
268 SubSliceMut<'static, u8>,
269 SubSliceMut<'static, u8>,
270 ErrorCode,
271 ),
272 >;
273
274 /// Modify a value based on the given key. If the key does not exist it an
275 /// error callback will be provided.
276 ///
277 /// The `value` buffer must have room for a header.
278 ///
279 /// ### Arguments
280 ///
281 /// - `key`: The key to identify the k-v pair.
282 /// - `value`: The value to store. The provided buffer MUST start
283 /// `KVPermissions.header_size()` bytes after the beginning of the buffer
284 /// to enable the implementation to insert a header.
285 /// - `permissions`: The read/write/modify permissions for this access.
286 ///
287 /// ### Return
288 ///
289 /// - On success returns `Ok(())`. A callback will be issued.
290 /// - On error, returns the buffers and:
291 /// - `BUSY`: An operation is already in progress.
292 /// - `SIZE`: There is insufficient room to include the permission header
293 /// in the `value` buffer or the key/value is too large to store.
294 /// - `INVAL`: The caller does not have write permissions.
295 /// - `FAIL`: An internal error occurred and the operation cannot be
296 /// completed.
297 fn update(
298 &self,
299 key: SubSliceMut<'static, u8>,
300 value: SubSliceMut<'static, u8>,
301 permissions: StoragePermissions,
302 ) -> Result<
303 (),
304 (
305 SubSliceMut<'static, u8>,
306 SubSliceMut<'static, u8>,
307 ErrorCode,
308 ),
309 >;
310
311 /// Delete a key-value object based on the given key.
312 ///
313 /// ### Arguments
314 ///
315 /// - `key`: The key to identify the k-v pair.
316 /// - `permissions`: The read/write/modify permissions for this access.
317 ///
318 /// ### Return
319 ///
320 /// - On success returns `Ok(())`. A callback will be issued.
321 /// - On error, returns the buffers and:
322 /// - `BUSY`: An operation is already in progress.
323 /// - `INVAL`: The caller does not have modify permissions.
324 /// - `FAIL`: An internal error occurred and the operation cannot be
325 /// completed.
326 fn delete(
327 &self,
328 key: SubSliceMut<'static, u8>,
329 permissions: StoragePermissions,
330 ) -> Result<(), (SubSliceMut<'static, u8>, ErrorCode)>;
331
332 /// Run garbage collection on the underlying Key/Value store.
333 ///
334 /// This is generally used to reclaim keys that have been removed with
335 /// the `delete()` call.
336 ///
337 /// ### Return
338 ///
339 /// - On success returns `Ok(())`. A callback will be issued.
340 /// - On error, returns the buffers and:
341 /// - `BUSY`: An operation is already in progress.
342 /// - `FAIL`: An internal error occurred and the operation cannot be
343 /// completed.
344 fn garbage_collect(&self) -> Result<(), ErrorCode>;
345
346 /// Returns the length of the key-value store's header in bytes.
347 ///
348 /// Room for this header must be accommodated in a `set`, `add`, or `update`
349 /// operation.
350 fn header_size(&self) -> usize;
351}
352
353/// Key-Value interface.
354///
355/// This interface provides access to key-value storage.
356///
357/// `KV` includes five typical commands:
358/// - `get(key) -> value`
359/// - `set(key, value)`
360/// - `add(key, value)`
361/// - `update(key, value)`
362/// - `delete(key)`
363pub trait KV<'a> {
364 /// Configure the client for operation callbacks.
365 fn set_client(&self, client: &'a dyn KVClient);
366
367 /// Retrieve a value based on the given key.
368 ///
369 /// ### Arguments
370 ///
371 /// - `key`: The key to identify the k-v pair.
372 /// - `value`: Where the returned value buffer will be stored.
373 ///
374 /// ### Return
375 ///
376 /// - On success returns `Ok(())`. A callback will be issued.
377 /// - On error, returns the buffers and:
378 /// - `BUSY`: An operation is already in progress.
379 /// - `FAIL`: An internal error occurred and the operation cannot be
380 /// completed.
381 fn get(
382 &self,
383 key: SubSliceMut<'static, u8>,
384 value: SubSliceMut<'static, u8>,
385 ) -> Result<
386 (),
387 (
388 SubSliceMut<'static, u8>,
389 SubSliceMut<'static, u8>,
390 ErrorCode,
391 ),
392 >;
393
394 /// Store a value based on the given key. If the key does not exist it will
395 /// be added. If the key already exists the value will be updated.
396 ///
397 /// The `value` buffer must have room for a header.
398 ///
399 /// ### Arguments
400 ///
401 /// - `key`: The key to identify the k-v pair.
402 /// - `value`: The value to store.
403 ///
404 /// ### Return
405 ///
406 /// - On success returns `Ok(())`. A callback will be issued.
407 /// - On error, returns the buffers and:
408 /// - `BUSY`: An operation is already in progress.
409 /// - `SIZE`: The key/value is too large to store.
410 /// - `FAIL`: An internal error occurred and the operation cannot be
411 /// completed.
412 fn set(
413 &self,
414 key: SubSliceMut<'static, u8>,
415 value: SubSliceMut<'static, u8>,
416 ) -> Result<
417 (),
418 (
419 SubSliceMut<'static, u8>,
420 SubSliceMut<'static, u8>,
421 ErrorCode,
422 ),
423 >;
424
425 /// Store a new value based on the given key. If the key does not exist it
426 /// will be added. If the key already exists an error callback will be
427 /// provided.
428 ///
429 /// The `value` buffer must have room for a header.
430 ///
431 /// ### Arguments
432 ///
433 /// - `key`: The key to identify the k-v pair.
434 /// - `value`: The value to store.
435 ///
436 /// ### Return
437 ///
438 /// - On success returns `Ok(())`. A callback will be issued.
439 /// - On error, returns the buffers and:
440 /// - `BUSY`: An operation is already in progress.
441 /// - `SIZE`: The key/value is too large to store.
442 /// - `FAIL`: An internal error occurred and the operation cannot be
443 /// completed.
444 fn add(
445 &self,
446 key: SubSliceMut<'static, u8>,
447 value: SubSliceMut<'static, u8>,
448 ) -> Result<
449 (),
450 (
451 SubSliceMut<'static, u8>,
452 SubSliceMut<'static, u8>,
453 ErrorCode,
454 ),
455 >;
456
457 /// Modify a value based on the given key. If the key does not exist it an
458 /// error callback will be provided.
459 ///
460 /// The `value` buffer must have room for a header.
461 ///
462 /// ### Arguments
463 ///
464 /// - `key`: The key to identify the k-v pair.
465 /// - `value`: The value to store.
466 ///
467 /// ### Return
468 ///
469 /// - On success returns `Ok(())`. A callback will be issued.
470 /// - On error, returns the buffers and:
471 /// - `BUSY`: An operation is already in progress.
472 /// - `SIZE`: The key/value is too large to store.
473 /// - `FAIL`: An internal error occurred and the operation cannot be
474 /// completed.
475 fn update(
476 &self,
477 key: SubSliceMut<'static, u8>,
478 value: SubSliceMut<'static, u8>,
479 ) -> Result<
480 (),
481 (
482 SubSliceMut<'static, u8>,
483 SubSliceMut<'static, u8>,
484 ErrorCode,
485 ),
486 >;
487
488 /// Delete a key-value object based on the given key.
489 ///
490 /// ### Arguments
491 ///
492 /// - `key`: The key to identify the k-v pair.
493 ///
494 /// ### Return
495 ///
496 /// - On success returns `Ok(())`. A callback will be issued.
497 /// - On error, returns the buffers and:
498 /// - `BUSY`: An operation is already in progress.
499 /// - `FAIL`: An internal error occurred and the operation cannot be
500 /// completed.
501 fn delete(
502 &self,
503 key: SubSliceMut<'static, u8>,
504 ) -> Result<(), (SubSliceMut<'static, u8>, ErrorCode)>;
505
506 /// Run garbage collection on the underlying Key/Value store.
507 ///
508 /// This is generally used to reclaim keys that have been removed with
509 /// the `delete()` call.
510 ///
511 /// ### Return
512 ///
513 /// - On success returns `Ok(())`. A callback will be issued.
514 /// - On error, returns the buffers and:
515 /// - `BUSY`: An operation is already in progress.
516 /// - `FAIL`: An internal error occurred and the operation cannot be
517 /// completed.
518 fn garbage_collect(&self) -> Result<(), ErrorCode>;
519}