From 4c9d6c5ee7aebb2f39367ae7689408a7fa862235 Mon Sep 17 00:00:00 2001 From: Paul Hollinsky Date: Mon, 28 Feb 2022 01:55:31 -0500 Subject: [PATCH] Disk: NeoMemory: Cache last read sector for one second This prevents constant re-reads if reading in small chunks --- disk/neomemorydiskreaddriver.cpp | 49 +++++++++++-------- include/icsneo/disk/neomemorydiskreaddriver.h | 6 +++ 2 files changed, 34 insertions(+), 21 deletions(-) diff --git a/disk/neomemorydiskreaddriver.cpp b/disk/neomemorydiskreaddriver.cpp index 22bb748..ef0d87d 100644 --- a/disk/neomemorydiskreaddriver.cpp +++ b/disk/neomemorydiskreaddriver.cpp @@ -12,30 +12,37 @@ optional NeoMemoryDiskReadDriver::readLogicalDiskAligned(Communication if(amount != SectorSize) return 0; - const uint64_t currentSector = pos / SectorSize; - auto msg = com.waitForMessageSync([¤tSector, &com] { - return com.sendCommand(Command::NeoReadMemory, { - MemoryTypeSD, - uint8_t(currentSector & 0xFF), - uint8_t((currentSector >> 8) & 0xFF), - uint8_t((currentSector >> 16) & 0xFF), - uint8_t((currentSector >> 24) & 0xFF), - uint8_t(SectorSize & 0xFF), - uint8_t((SectorSize >> 8) & 0xFF), - uint8_t((SectorSize >> 16) & 0xFF), - uint8_t((SectorSize >> 24) & 0xFF) - }); - }, NeoMemorySDRead, timeout); + if(cachePos != pos || std::chrono::steady_clock::now() > cachedAt + CacheTime) { + // The cache does not have this data, go get it + const uint64_t currentSector = pos / SectorSize; + auto msg = com.waitForMessageSync([¤tSector, &com] { + return com.sendCommand(Command::NeoReadMemory, { + MemoryTypeSD, + uint8_t(currentSector & 0xFF), + uint8_t((currentSector >> 8) & 0xFF), + uint8_t((currentSector >> 16) & 0xFF), + uint8_t((currentSector >> 24) & 0xFF), + uint8_t(SectorSize & 0xFF), + uint8_t((SectorSize >> 8) & 0xFF), + uint8_t((SectorSize >> 16) & 0xFF), + uint8_t((SectorSize >> 24) & 0xFF) + }); + }, NeoMemorySDRead, timeout); - if(!msg) - return 0; + if(!msg) + return 0; - const auto sdmsg = std::dynamic_pointer_cast(msg); - if(!sdmsg || sdmsg->data.size() != SectorSize) { - report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error); - return nullopt; + const auto sdmsg = std::dynamic_pointer_cast(msg); + if(!sdmsg || sdmsg->data.size() != SectorSize) { + report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error); + return nullopt; + } + + memcpy(cache.data(), sdmsg->data.data(), SectorSize); + cachedAt = std::chrono::steady_clock::now(); + cachePos = pos; } - memcpy(into, sdmsg->data.data(), SectorSize); + memcpy(into, cache.data(), SectorSize); return SectorSize; } \ No newline at end of file diff --git a/include/icsneo/disk/neomemorydiskreaddriver.h b/include/icsneo/disk/neomemorydiskreaddriver.h index 208b69d..2694a8f 100644 --- a/include/icsneo/disk/neomemorydiskreaddriver.h +++ b/include/icsneo/disk/neomemorydiskreaddriver.h @@ -5,6 +5,7 @@ #include "icsneo/disk/diskreaddriver.h" #include +#include namespace icsneo { @@ -26,6 +27,11 @@ public: private: static constexpr const uint8_t MemoryTypeSD = 0x01; // Logical Disk + static constexpr const std::chrono::duration CacheTime = std::chrono::seconds(1); + + std::array cache; + uint64_t cachePos = 0; + std::chrono::time_point cachedAt; optional readLogicalDiskAligned(Communication& com, device_eventhandler_t report, uint64_t pos, uint8_t* into, uint64_t amount, std::chrono::milliseconds timeout) override;