1use kernel::collections::list::{List, ListLink, ListNode};
36
37use kernel::hil::kv;
38use kernel::hil::kv::KVPermissions;
39use kernel::storage_permissions::StoragePermissions;
40use kernel::utilities::cells::{MapCell, OptionalCell};
41use kernel::utilities::leasable_buffer::SubSliceMut;
42use kernel::ErrorCode;
43
44#[derive(Clone, Copy, PartialEq, Debug)]
45enum Operation {
46 Get,
47 Set,
48 Delete,
49 Add,
50 Update,
51 GarbageCollect,
52}
53
54pub struct VirtualKVPermissions<'a, V: kv::KVPermissions<'a>> {
55 mux_kv: &'a MuxKVPermissions<'a, V>,
56 next: ListLink<'a, VirtualKVPermissions<'a, V>>,
57
58 client: OptionalCell<&'a dyn kv::KVClient>,
59 operation: OptionalCell<Operation>,
60
61 key: MapCell<SubSliceMut<'static, u8>>,
62 value: MapCell<SubSliceMut<'static, u8>>,
63 valid_ids: OptionalCell<StoragePermissions>,
64}
65
66impl<'a, V: kv::KVPermissions<'a>> ListNode<'a, VirtualKVPermissions<'a, V>>
67 for VirtualKVPermissions<'a, V>
68{
69 fn next(&self) -> &'a ListLink<VirtualKVPermissions<'a, V>> {
70 &self.next
71 }
72}
73
74impl<'a, V: kv::KVPermissions<'a>> VirtualKVPermissions<'a, V> {
75 pub fn new(mux_kv: &'a MuxKVPermissions<'a, V>) -> VirtualKVPermissions<'a, V> {
76 Self {
77 mux_kv,
78 next: ListLink::empty(),
79 client: OptionalCell::empty(),
80 operation: OptionalCell::empty(),
81 key: MapCell::empty(),
82 value: MapCell::empty(),
83 valid_ids: OptionalCell::empty(),
84 }
85 }
86
87 pub fn setup(&'a self) {
88 self.mux_kv.users.push_head(self);
89 }
90
91 fn insert(
92 &self,
93 key: SubSliceMut<'static, u8>,
94 value: SubSliceMut<'static, u8>,
95 permissions: StoragePermissions,
96 operation: Operation,
97 ) -> Result<
98 (),
99 (
100 SubSliceMut<'static, u8>,
101 SubSliceMut<'static, u8>,
102 ErrorCode,
103 ),
104 > {
105 match permissions.get_write_id() {
106 Some(_write_id) => {}
107 None => return Err((key, value, ErrorCode::INVAL)),
108 }
109
110 if self.operation.is_some() {
111 return Err((key, value, ErrorCode::BUSY));
112 }
113
114 if value.len() < self.header_size() {
116 return Err((key, value, ErrorCode::SIZE));
117 }
118
119 self.operation.set(operation);
120 self.valid_ids.set(permissions);
121 self.key.replace(key);
122 self.value.replace(value);
123
124 self.mux_kv
125 .do_next_op(false)
126 .map_err(|e| (self.key.take().unwrap(), self.value.take().unwrap(), e))
127 }
128}
129
130impl<'a, V: kv::KVPermissions<'a>> kv::KVPermissions<'a> for VirtualKVPermissions<'a, V> {
131 fn set_client(&self, client: &'a dyn kv::KVClient) {
132 self.client.set(client);
133 }
134
135 fn get(
136 &self,
137 key: SubSliceMut<'static, u8>,
138 value: SubSliceMut<'static, u8>,
139 permissions: StoragePermissions,
140 ) -> Result<
141 (),
142 (
143 SubSliceMut<'static, u8>,
144 SubSliceMut<'static, u8>,
145 ErrorCode,
146 ),
147 > {
148 if self.operation.is_some() {
149 return Err((key, value, ErrorCode::BUSY));
150 }
151
152 self.operation.set(Operation::Get);
153 self.valid_ids.set(permissions);
154 self.key.replace(key);
155 self.value.replace(value);
156
157 self.mux_kv
158 .do_next_op(false)
159 .map_err(|e| (self.key.take().unwrap(), self.value.take().unwrap(), e))
160 }
161
162 fn set(
163 &self,
164 key: SubSliceMut<'static, u8>,
165 value: SubSliceMut<'static, u8>,
166 permissions: StoragePermissions,
167 ) -> Result<
168 (),
169 (
170 SubSliceMut<'static, u8>,
171 SubSliceMut<'static, u8>,
172 ErrorCode,
173 ),
174 > {
175 self.insert(key, value, permissions, Operation::Set)
176 }
177
178 fn add(
179 &self,
180 key: SubSliceMut<'static, u8>,
181 value: SubSliceMut<'static, u8>,
182 permissions: StoragePermissions,
183 ) -> Result<
184 (),
185 (
186 SubSliceMut<'static, u8>,
187 SubSliceMut<'static, u8>,
188 ErrorCode,
189 ),
190 > {
191 self.insert(key, value, permissions, Operation::Add)
192 }
193
194 fn update(
195 &self,
196 key: SubSliceMut<'static, u8>,
197 value: SubSliceMut<'static, u8>,
198 permissions: StoragePermissions,
199 ) -> Result<
200 (),
201 (
202 SubSliceMut<'static, u8>,
203 SubSliceMut<'static, u8>,
204 ErrorCode,
205 ),
206 > {
207 self.insert(key, value, permissions, Operation::Update)
208 }
209
210 fn delete(
211 &self,
212 key: SubSliceMut<'static, u8>,
213 permissions: StoragePermissions,
214 ) -> Result<(), (SubSliceMut<'static, u8>, ErrorCode)> {
215 if self.operation.is_some() {
216 return Err((key, ErrorCode::BUSY));
217 }
218
219 self.operation.set(Operation::Delete);
220 self.valid_ids.set(permissions);
221 self.key.replace(key);
222
223 self.mux_kv
224 .do_next_op(false)
225 .map_err(|e| (self.key.take().unwrap(), e))
226 }
227
228 fn garbage_collect(&self) -> Result<(), ErrorCode> {
229 if self.operation.is_some() {
230 return Err(ErrorCode::BUSY);
231 }
232
233 self.operation.set(Operation::GarbageCollect);
234
235 self.mux_kv.do_next_op(false)
236 }
237
238 fn header_size(&self) -> usize {
239 self.mux_kv.kv.header_size()
240 }
241}
242
243pub struct MuxKVPermissions<'a, V: kv::KVPermissions<'a>> {
244 kv: &'a V,
245 users: List<'a, VirtualKVPermissions<'a, V>>,
246 inflight: OptionalCell<&'a VirtualKVPermissions<'a, V>>,
247}
248
249impl<'a, V: kv::KVPermissions<'a>> MuxKVPermissions<'a, V> {
250 pub fn new(kv: &'a V) -> MuxKVPermissions<'a, V> {
251 Self {
252 kv,
253 inflight: OptionalCell::empty(),
254 users: List::new(),
255 }
256 }
257
258 fn do_next_op(&self, async_op: bool) -> Result<(), ErrorCode> {
259 let mnode = self.users.iter().find(|node| node.operation.is_some());
261
262 mnode.map_or(Ok(()), |node| {
263 node.operation.map_or(Ok(()), |op| {
264 if op == Operation::GarbageCollect {
267 return match self.kv.garbage_collect() {
268 Ok(()) => {
269 self.inflight.set(node);
270 Ok(())
271 }
272 Err(e) => {
273 node.operation.clear();
274 if async_op {
275 node.client.map(move |cb| {
276 cb.garbage_collection_complete(Err(e));
277 });
278 Ok(())
279 } else {
280 Err(e)
281 }
282 }
283 };
284 }
285
286 node.key.take().map_or(Ok(()), |key| match op {
287 Operation::Get => node.value.take().map_or(Ok(()), |value| {
288 node.valid_ids.map_or(Ok(()), |perms| {
289 match self.kv.get(key, value, perms) {
290 Ok(()) => {
291 self.inflight.set(node);
292 Ok(())
293 }
294 Err((key, value, e)) => {
295 node.operation.clear();
296 if async_op {
297 node.client.map(move |cb| {
298 cb.get_complete(Err(e), key, value);
299 });
300 Ok(())
301 } else {
302 node.key.replace(key);
303 node.value.replace(value);
304 Err(e)
305 }
306 }
307 }
308 })
309 }),
310 Operation::Set => node.value.take().map_or(Ok(()), |value| {
311 node.valid_ids.map_or(Ok(()), |perms| {
312 match self.kv.set(key, value, perms) {
313 Ok(()) => {
314 self.inflight.set(node);
315 Ok(())
316 }
317 Err((key, value, e)) => {
318 node.operation.clear();
319 if async_op {
320 node.client.map(move |cb| {
321 cb.set_complete(Err(e), key, value);
322 });
323 Ok(())
324 } else {
325 node.key.replace(key);
326 node.value.replace(value);
327 Err(e)
328 }
329 }
330 }
331 })
332 }),
333 Operation::Add => node.value.take().map_or(Ok(()), |value| {
334 node.valid_ids.map_or(Ok(()), |perms| {
335 match self.kv.add(key, value, perms) {
336 Ok(()) => {
337 self.inflight.set(node);
338 Ok(())
339 }
340 Err((key, value, e)) => {
341 node.operation.clear();
342 if async_op {
343 node.client.map(move |cb| {
344 cb.add_complete(Err(e), key, value);
345 });
346 Ok(())
347 } else {
348 node.key.replace(key);
349 node.value.replace(value);
350 Err(e)
351 }
352 }
353 }
354 })
355 }),
356 Operation::Update => node.value.take().map_or(Ok(()), |value| {
357 node.valid_ids.map_or(Ok(()), |perms| {
358 match self.kv.update(key, value, perms) {
359 Ok(()) => {
360 self.inflight.set(node);
361 Ok(())
362 }
363 Err((key, value, e)) => {
364 node.operation.clear();
365 if async_op {
366 node.client.map(move |cb| {
367 cb.update_complete(Err(e), key, value);
368 });
369 Ok(())
370 } else {
371 node.key.replace(key);
372 node.value.replace(value);
373 Err(e)
374 }
375 }
376 }
377 })
378 }),
379 Operation::Delete => {
380 node.valid_ids
381 .map_or(Ok(()), |perms| match self.kv.delete(key, perms) {
382 Ok(()) => {
383 self.inflight.set(node);
384 Ok(())
385 }
386 Err((key, e)) => {
387 node.operation.clear();
388 if async_op {
389 node.client.map(move |cb| {
390 cb.delete_complete(Err(e), key);
391 });
392 Ok(())
393 } else {
394 node.key.replace(key);
395 Err(e)
396 }
397 }
398 })
399 }
400 Operation::GarbageCollect => Err(ErrorCode::NOSUPPORT),
401 })
402 })
403 })
404 }
405}
406
407impl<'a, V: kv::KVPermissions<'a>> kv::KVClient for MuxKVPermissions<'a, V> {
408 fn get_complete(
409 &self,
410 result: Result<(), ErrorCode>,
411 key: SubSliceMut<'static, u8>,
412 value: SubSliceMut<'static, u8>,
413 ) {
414 self.inflight.take().map(|node| {
415 node.operation.clear();
416 node.client.map(move |cb| {
417 cb.get_complete(result, key, value);
418 });
419 });
420
421 let _ = self.do_next_op(true);
422 }
423
424 fn set_complete(
425 &self,
426 result: Result<(), ErrorCode>,
427 key: SubSliceMut<'static, u8>,
428 value: SubSliceMut<'static, u8>,
429 ) {
430 self.inflight.take().map(|node| {
431 node.operation.clear();
432 node.client.map(move |cb| {
433 cb.set_complete(result, key, value);
434 });
435 });
436
437 let _ = self.do_next_op(true);
438 }
439
440 fn add_complete(
441 &self,
442 result: Result<(), ErrorCode>,
443 key: SubSliceMut<'static, u8>,
444 value: SubSliceMut<'static, u8>,
445 ) {
446 self.inflight.take().map(|node| {
447 node.operation.clear();
448 node.client.map(move |cb| {
449 cb.add_complete(result, key, value);
450 });
451 });
452
453 let _ = self.do_next_op(true);
454 }
455
456 fn update_complete(
457 &self,
458 result: Result<(), ErrorCode>,
459 key: SubSliceMut<'static, u8>,
460 value: SubSliceMut<'static, u8>,
461 ) {
462 self.inflight.take().map(|node| {
463 node.operation.clear();
464 node.client.map(move |cb| {
465 cb.update_complete(result, key, value);
466 });
467 });
468
469 let _ = self.do_next_op(true);
470 }
471
472 fn delete_complete(&self, result: Result<(), ErrorCode>, key: SubSliceMut<'static, u8>) {
473 self.inflight.take().map(|node| {
474 node.operation.clear();
475 node.client.map(move |cb| {
476 cb.delete_complete(result, key);
477 });
478 });
479
480 let _ = self.do_next_op(true);
481 }
482
483 fn garbage_collection_complete(&self, result: Result<(), ErrorCode>) {
484 self.inflight.take().map(|node| {
485 node.operation.clear();
486 node.client.map(move |cb| {
487 cb.garbage_collection_complete(result);
488 });
489 });
490
491 let _ = self.do_next_op(true);
492 }
493}