Keep contended journal inventory reads pending

This commit is contained in:
liu weikai committed 2026-09-29 23:57:59 +08:00
1 parent 4f6240291a
commit 10ea9d2cf9
2 files changed
+30 -2

No files matched your search

@@ -6,6 +6,7 @@
std::vector<std::string> names;
bool busy_once = false;
bool fail_after_first = false;
unsigned volume_busy = 0;
namespace platform::esp::arduino_common::storage
{
class SdRuntimeDir::Impl
@@ -46,6 +47,12 @@ SdFileReadResult sd_read_file(const char*, uint8_t* buffer, size_t capacity)
{
const auto header = ::geocaching::storage::encodeVolumeHeader({});
SdFileReadResult result;
if (volume_busy)
{
--volume_busy;
result.status = SdFileReadStatus::Busy;
return result;
}
result.status = SdFileReadStatus::Ready;
result.file_size = header.size();
result.bytes_read = std::min(capacity, header.size());
@@ -71,7 +78,7 @@ int main()
names = {"0000000000000001.gcj", "0000000000000002.gcj"};
SdJournalInventory interrupted({}, 0);
busy_once = true;
if (interrupted.step() != InventoryStep::RetryLater || interrupted.range().complete ||
if (interrupted.step() != InventoryStep::Scanning || interrupted.range().complete ||
interrupted.step() != InventoryStep::Scanning) return 5;
fail_after_first = true;
if (interrupted.step() != InventoryStep::RetryLater || interrupted.range().complete) return 6;
@@ -81,5 +88,23 @@ int main()
SdJournalInventory spanning({}, 4);
if (spanning.step() != InventoryStep::Scanning || spanning.step() != InventoryStep::Scanning ||
spanning.step() != InventoryStep::Complete || spanning.range().first_start != 1 || spanning.range().last_start != 8) return 8;
names = {"0000000000000001.gcj", "0000000000000008.gcj"};
SdJournalInventory contended({}, 4);
volume_busy = 12;
for (unsigned i = 0; i < 12; ++i)
if (contended.step() != InventoryStep::Scanning || contended.range().complete) return 9;
if (contended.step() != InventoryStep::Scanning) return 10;
// Neither contention source may discard the first segment or restart the
// cursor after it has been observed.
volume_busy = 12;
for (unsigned i = 0; i < 12; ++i)
if (contended.step() != InventoryStep::Scanning || contended.range().complete) return 11;
for (unsigned i = 0; i < 12; ++i)
{
busy_once = true;
if (contended.step() != InventoryStep::Scanning || contended.range().complete) return 12;
}
if (contended.step() != InventoryStep::Scanning || contended.step() != InventoryStep::Complete ||
contended.range().first_start != 1 || contended.range().last_start != 8) return 13;
return 0;
}
@@ -38,6 +38,7 @@ class SdJournalInventory
if (state_ == InventoryStep::Complete || state_ == InventoryStep::Corrupt || state_ == InventoryStep::VolumeChanged) return state_;
::geocaching::storage::VolumeInstance current;
const auto volume = inspectSdVolume(current);
if (volume == SdVolumeResult::Busy) return state_ = InventoryStep::Scanning;
if (volume == SdVolumeResult::Missing || volume == SdVolumeResult::Unavailable || volume == SdVolumeResult::IoError)
return restart();
if (volume != SdVolumeResult::Ready) return finish(InventoryStep::Corrupt);
@@ -46,7 +47,9 @@ class SdJournalInventory
char name[128]{};
bool is_dir = false;
const auto result = directory_.read_next_status(name, sizeof(name), &is_dir);
if (result == storage::SdDirReadStatus::Busy) return InventoryStep::RetryLater;
// Contention leaves the cursor intact. Keep the caller in its current
// recovery step instead of reporting a failed inventory attempt.
if (result == storage::SdDirReadStatus::Busy) return state_ = InventoryStep::Scanning;
if (result == storage::SdDirReadStatus::IoError || result == storage::SdDirReadStatus::Unavailable) return restart();
if (result == storage::SdDirReadStatus::End)
return finish(InventoryStep::Complete);