Skip to content

Commit e1fb263

Browse files
committed
Merge branch 'quartiq-feature/remove-all-items'
2 parents 1b083d1 + 75c1a1e commit e1fb263

File tree

2 files changed

+107
-7
lines changed

2 files changed

+107
-7
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
## Unreleased
66

77
- Added `space_left` function for queue
8+
- Added a new `map::remove_all_items()` API to remove all stored items in flash.
89

910
# 2.0.2 07-05-24
1011

@@ -127,4 +128,4 @@
127128

128129
## 0.1.0 - 12-01-23
129130

130-
- Initial release
131+
- Initial release

src/map.rs

Lines changed: 105 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -566,21 +566,51 @@ pub async fn remove_item<K: Key, S: MultiwriteNorFlash>(
566566
flash_range.clone(),
567567
cache,
568568
data_buffer,
569-
search_key.clone()
569+
Some(search_key.clone())
570570
)
571571
.await,
572572
repair = try_repair::<K, _>(flash, flash_range.clone(), cache, data_buffer).await?
573573
)
574574
}
575575

576+
/// Fully remove all stored items. Additional calls to fetch with any key will return None until
577+
/// new items are stored again.
578+
///
579+
/// <div class="warning">
580+
/// This might be really slow!
581+
/// </div>
582+
///
583+
/// <div class="warning">
584+
///
585+
/// *You are required to, on a given flash range, use the same [Key] type every time. You are allowed to use*
586+
/// *multiple [Value] types. See the module-level docs for more information about this.*
587+
///
588+
/// </div>
589+
pub async fn remove_all_items<K: Key, S: MultiwriteNorFlash>(
590+
flash: &mut S,
591+
flash_range: Range<u32>,
592+
cache: &mut impl KeyCacheImpl<K>,
593+
data_buffer: &mut [u8],
594+
) -> Result<(), Error<S::Error>> {
595+
run_with_auto_repair!(
596+
function =
597+
remove_item_inner::<K, _>(flash, flash_range.clone(), cache, data_buffer, None).await,
598+
repair = try_repair::<K, _>(flash, flash_range.clone(), cache, data_buffer).await?
599+
)
600+
}
601+
576602
async fn remove_item_inner<K: Key, S: MultiwriteNorFlash>(
577603
flash: &mut S,
578604
flash_range: Range<u32>,
579605
cache: &mut impl KeyCacheImpl<K>,
580606
data_buffer: &mut [u8],
581-
search_key: K,
607+
search_key: Option<K>,
582608
) -> Result<(), Error<S::Error>> {
583-
cache.notice_key_erased(&search_key);
609+
if let Some(key) = &search_key {
610+
cache.notice_key_erased(key);
611+
} else {
612+
cache.invalidate_cache_state();
613+
}
584614

585615
// Search for the last used page. We're gonna erase from the one after this first.
586616
// If we get an early shutoff or cancellation, this will make it so that we don't return
@@ -620,11 +650,15 @@ async fn remove_item_inner<K: Key, S: MultiwriteNorFlash>(
620650
item::MaybeItem::Corrupted(_, _) => continue,
621651
item::MaybeItem::Erased(_, _) => continue,
622652
item::MaybeItem::Present(item) => {
623-
let (item_key, _) = K::deserialize_from(item.data())?;
624-
653+
let item_match = if let Some(search_key) = &search_key {
654+
let (item_key, _) = K::deserialize_from(item.data())?;
655+
&item_key == search_key
656+
} else {
657+
false
658+
};
625659
// If this item has the same key as the key we're trying to erase, then erase the item.
626660
// But keep going! We need to erase everything.
627-
if item_key == search_key {
661+
if search_key.is_none() || item_match {
628662
item.header
629663
.erase_data(flash, flash_range.clone(), cache, item_address)
630664
.await?;
@@ -1357,6 +1391,71 @@ mod tests {
13571391
}
13581392
}
13591393

1394+
#[test]
1395+
async fn remove_all() {
1396+
let mut flash = mock_flash::MockFlashBase::<4, 1, 4096>::new(
1397+
mock_flash::WriteCountCheck::Twice,
1398+
None,
1399+
true,
1400+
);
1401+
let mut data_buffer = AlignedBuf([0; 128]);
1402+
const FLASH_RANGE: Range<u32> = 0x0000..0x4000;
1403+
1404+
// Add some data to flash
1405+
for value in 0..10 {
1406+
for key in 0..24 {
1407+
store_item(
1408+
&mut flash,
1409+
FLASH_RANGE,
1410+
&mut cache::NoCache::new(),
1411+
&mut data_buffer,
1412+
key as u8,
1413+
&vec![key as u8; value + 2].as_slice(),
1414+
)
1415+
.await
1416+
.unwrap();
1417+
}
1418+
}
1419+
1420+
// Sanity check that we can find all the keys we just added.
1421+
for key in 0..24 {
1422+
assert!(fetch_item::<u8, &[u8], _>(
1423+
&mut flash,
1424+
FLASH_RANGE,
1425+
&mut cache::NoCache::new(),
1426+
&mut data_buffer,
1427+
key
1428+
)
1429+
.await
1430+
.unwrap()
1431+
.is_some());
1432+
}
1433+
1434+
// Remove all the items
1435+
remove_all_items::<u8, _>(
1436+
&mut flash,
1437+
FLASH_RANGE,
1438+
&mut cache::NoCache::new(),
1439+
&mut data_buffer,
1440+
)
1441+
.await
1442+
.unwrap();
1443+
1444+
// Verify that none of the keys are present in flash.
1445+
for key in 0..24 {
1446+
assert!(fetch_item::<u8, &[u8], _>(
1447+
&mut flash,
1448+
FLASH_RANGE,
1449+
&mut cache::NoCache::new(),
1450+
&mut data_buffer,
1451+
key
1452+
)
1453+
.await
1454+
.unwrap()
1455+
.is_none());
1456+
}
1457+
}
1458+
13601459
#[test]
13611460
async fn store_too_big_item() {
13621461
let mut flash = MockFlashBig::new(mock_flash::WriteCountCheck::Twice, None, true);

0 commit comments

Comments
 (0)