| 2005 | } |
| 2006 | |
| 2007 | void RcxController::onReadComplete() { |
| 2008 | m_readInFlight = false; |
| 2009 | |
| 2010 | if (m_readGen != m_refreshGen) return; |
| 2011 | |
| 2012 | PageMap newPages; |
| 2013 | try { |
| 2014 | newPages = m_refreshWatcher->result(); |
| 2015 | } catch (const std::exception& e) { |
| 2016 | qWarning() << "[Refresh] async read threw:" << e.what(); |
| 2017 | return; |
| 2018 | } catch (...) { |
| 2019 | qWarning() << "[Refresh] async read threw unknown exception"; |
| 2020 | return; |
| 2021 | } |
| 2022 | |
| 2023 | // All-zero guard: if page 0 is all zeros and we already have data, discard |
| 2024 | if (!m_prevPages.isEmpty() && newPages.contains(0)) { |
| 2025 | const QByteArray& p0 = newPages.value(0); |
| 2026 | bool allZero = true; |
| 2027 | for (int i = 0; i < p0.size(); ++i) { |
| 2028 | if (p0[i] != 0) { allZero = false; break; } |
| 2029 | } |
| 2030 | if (allZero) { |
| 2031 | qDebug() << "[Refresh] discarding all-zero page-0, keeping stale snapshot"; |
| 2032 | return; |
| 2033 | } |
| 2034 | } |
| 2035 | |
| 2036 | // Fast path: no changes at all |
| 2037 | if (newPages == m_prevPages) |
| 2038 | return; |
| 2039 | |
| 2040 | // Compute which byte offsets changed (for change highlighting). |
| 2041 | // Skip on first snapshot — nothing to compare against. |
| 2042 | m_changedOffsets.clear(); |
| 2043 | if (!m_prevPages.isEmpty()) { |
| 2044 | for (auto it = newPages.constBegin(); it != newPages.constEnd(); ++it) { |
| 2045 | uint64_t pageAddr = it.key(); |
| 2046 | const QByteArray& newPage = it.value(); |
| 2047 | auto oldIt = m_prevPages.constFind(pageAddr); |
| 2048 | if (oldIt == m_prevPages.constEnd()) |
| 2049 | continue; // new page, no previous data to diff against |
| 2050 | const QByteArray& oldPage = oldIt.value(); |
| 2051 | int cmpLen = qMin(oldPage.size(), newPage.size()); |
| 2052 | for (int i = 0; i < cmpLen; ++i) { |
| 2053 | if (oldPage[i] != newPage[i]) |
| 2054 | m_changedOffsets.insert(static_cast<int64_t>(pageAddr) + i); |
| 2055 | } |
| 2056 | } |
| 2057 | } |
| 2058 | |
| 2059 | int mainExtent = computeDataExtent(); |
| 2060 | m_prevPages = newPages; |
| 2061 | |
| 2062 | if (m_snapshotProv) |
| 2063 | m_snapshotProv->updatePages(std::move(newPages), mainExtent); |
| 2064 | else |
nothing calls this directly
no test coverage detected