Introduce more comprehensive helper functions
This commit is contained in:
@@ -95,8 +95,7 @@ void KOReaderSyncActivity::onWifiSelectionComplete(const bool success) {
|
|||||||
logSyncMemSnapshot("after_performSync");
|
logSyncMemSnapshot("after_performSync");
|
||||||
}
|
}
|
||||||
|
|
||||||
void KOReaderSyncActivity::performSync() {
|
bool KOReaderSyncActivity::calculateDocumentHash() {
|
||||||
// Calculate document hash based on user's preferred method
|
|
||||||
if (KOREADER_STORE.getMatchMethod() == DocumentMatchMethod::FILENAME) {
|
if (KOREADER_STORE.getMatchMethod() == DocumentMatchMethod::FILENAME) {
|
||||||
documentHash = KOReaderDocumentId::calculateFromFilename(epubPath);
|
documentHash = KOReaderDocumentId::calculateFromFilename(epubPath);
|
||||||
} else {
|
} else {
|
||||||
@@ -109,81 +108,48 @@ void KOReaderSyncActivity::performSync() {
|
|||||||
statusMessage = tr(STR_HASH_FAILED);
|
statusMessage = tr(STR_HASH_FAILED);
|
||||||
}
|
}
|
||||||
requestUpdate(true);
|
requestUpdate(true);
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_DBG("KOSync", "Document hash: %s", documentHash.c_str());
|
LOG_DBG("KOSync", "Document hash: %s", documentHash.c_str());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Local mapping is only needed for compare/upload paths.
|
bool KOReaderSyncActivity::handleAutoPushPreflight() {
|
||||||
// Pull-only modes can skip this expensive step and go straight to remote fetch.
|
KOReaderSyncClient::beginPersistentSession();
|
||||||
if (syncIntent != KOReaderSyncIntentState::PULL_REMOTE && syncIntent != KOReaderSyncIntentState::AUTO_PULL) {
|
KOReaderProgress warmupProgress;
|
||||||
// Precompute local mapping before first network request so the expensive
|
const auto warmupResult = KOReaderSyncClient::getProgress(documentHash, warmupProgress);
|
||||||
// inflate/index work happens before TLS. This avoids a second local mapping
|
if (warmupResult != KOReaderSyncClient::OK && warmupResult != KOReaderSyncClient::NOT_FOUND) {
|
||||||
// pass later and keeps the upload path lightweight.
|
KOReaderSyncClient::endPersistentSession();
|
||||||
{
|
{
|
||||||
RenderLock lock(*this);
|
RenderLock lock(*this);
|
||||||
statusMessage = tr(STR_MAPPING_LOCAL);
|
state = SYNC_FAILED;
|
||||||
}
|
statusMessage = KOReaderSyncClient::errorString(warmupResult);
|
||||||
requestUpdateAndWait();
|
const char* detail = KOReaderSyncClient::lastFailureDetail();
|
||||||
if (!computeLocalProgressAndChapter()) {
|
if (detail && detail[0]) {
|
||||||
{
|
statusMessage += " — ";
|
||||||
RenderLock lock(*this);
|
statusMessage += detail;
|
||||||
state = SYNC_FAILED;
|
|
||||||
statusMessage = tr(STR_SYNC_FAILED_MSG);
|
|
||||||
}
|
}
|
||||||
requestUpdate(true);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
requestUpdate(true);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
// Auto-push must not overwrite progress that is already further along on the server.
|
||||||
// Drop EPUB state before HTTPS to maximize contiguous heap for TLS.
|
if (syncIntent == KOReaderSyncIntentState::AUTO_PUSH && warmupResult == KOReaderSyncClient::OK &&
|
||||||
releaseEpubForMapping();
|
warmupProgress.percentage > localProgress.percentage) {
|
||||||
|
LOG_DBG("KOSync", "AUTO_PUSH skipped: remote %.4f >= local %.4f", warmupProgress.percentage,
|
||||||
// Push intent skips comparison UI but still warms an HTTP/TLS session first
|
localProgress.percentage);
|
||||||
// so PUT can reuse the connection instead of forcing a fresh handshake.
|
KOReaderSyncClient::endPersistentSession();
|
||||||
if (syncIntent == KOReaderSyncIntentState::PUSH_LOCAL || syncIntent == KOReaderSyncIntentState::AUTO_PUSH) {
|
HalClock::wifiOff(true);
|
||||||
// Direct push previously started with no reusable HTTP/TLS session, forcing
|
APP_STATE.koReaderSyncSession.outcome = KOReaderSyncOutcomeState::UPLOAD_COMPLETE;
|
||||||
// a fresh handshake in updateProgress. Compare flow often succeeds because
|
APP_STATE.saveToFile();
|
||||||
// upload reuses the GET session. Warm the session here so push can take the
|
resumeReader(KOReaderSyncOutcomeState::UPLOAD_COMPLETE);
|
||||||
// same reuse path without showing comparison UI.
|
return false;
|
||||||
KOReaderSyncClient::beginPersistentSession();
|
|
||||||
KOReaderProgress warmupProgress;
|
|
||||||
const auto warmupResult = KOReaderSyncClient::getProgress(documentHash, warmupProgress);
|
|
||||||
if (warmupResult != KOReaderSyncClient::OK && warmupResult != KOReaderSyncClient::NOT_FOUND) {
|
|
||||||
KOReaderSyncClient::endPersistentSession();
|
|
||||||
{
|
|
||||||
RenderLock lock(*this);
|
|
||||||
state = SYNC_FAILED;
|
|
||||||
statusMessage = KOReaderSyncClient::errorString(warmupResult);
|
|
||||||
const char* detail = KOReaderSyncClient::lastFailureDetail();
|
|
||||||
if (detail && detail[0]) {
|
|
||||||
statusMessage += " — ";
|
|
||||||
statusMessage += detail;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
requestUpdate(true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Auto-push must not overwrite progress that is already further along on the server.
|
|
||||||
// Compare percentages from the warmup GET; users opted into automatic sync, so a
|
|
||||||
// remote-ahead state is treated as "nothing to do" and falls straight back to home.
|
|
||||||
if (syncIntent == KOReaderSyncIntentState::AUTO_PUSH && warmupResult == KOReaderSyncClient::OK &&
|
|
||||||
warmupProgress.percentage > localProgress.percentage) {
|
|
||||||
LOG_DBG("KOSync", "AUTO_PUSH skipped: remote %.4f >= local %.4f", warmupProgress.percentage,
|
|
||||||
localProgress.percentage);
|
|
||||||
KOReaderSyncClient::endPersistentSession();
|
|
||||||
HalClock::wifiOff(true);
|
|
||||||
// Reuse UPLOAD_COMPLETE outcome so the resume path is identical to a successful push;
|
|
||||||
// there is nothing to apply to the reader and progress.bin already reflects local state.
|
|
||||||
APP_STATE.koReaderSyncSession.outcome = KOReaderSyncOutcomeState::UPLOAD_COMPLETE;
|
|
||||||
APP_STATE.saveToFile();
|
|
||||||
resumeReader(KOReaderSyncOutcomeState::UPLOAD_COMPLETE);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
performUpload();
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KOReaderSyncActivity::performFetchAndCompare() {
|
||||||
{
|
{
|
||||||
RenderLock lock(*this);
|
RenderLock lock(*this);
|
||||||
statusMessage = tr(STR_FETCH_PROGRESS);
|
statusMessage = tr(STR_FETCH_PROGRESS);
|
||||||
@@ -213,7 +179,6 @@ void KOReaderSyncActivity::performSync() {
|
|||||||
|
|
||||||
if (syncIntent == KOReaderSyncIntentState::AUTO_PULL) {
|
if (syncIntent == KOReaderSyncIntentState::AUTO_PULL) {
|
||||||
// Auto-pull at book open: nothing to apply, just open the book with local progress.
|
// Auto-pull at book open: nothing to apply, just open the book with local progress.
|
||||||
// No user-visible failure since the user opted into "open with sync, if available".
|
|
||||||
KOReaderSyncClient::endPersistentSession();
|
KOReaderSyncClient::endPersistentSession();
|
||||||
HalClock::wifiOff(true);
|
HalClock::wifiOff(true);
|
||||||
resumeReader(KOReaderSyncOutcomeState::CANCELLED);
|
resumeReader(KOReaderSyncOutcomeState::CANCELLED);
|
||||||
@@ -236,8 +201,6 @@ void KOReaderSyncActivity::performSync() {
|
|||||||
{
|
{
|
||||||
RenderLock lock(*this);
|
RenderLock lock(*this);
|
||||||
state = SYNC_FAILED;
|
state = SYNC_FAILED;
|
||||||
// Combine the short category label with the rich diagnostic so users (and bug
|
|
||||||
// reports) can tell network/TLS/server/heap failures apart at a glance.
|
|
||||||
statusMessage = KOReaderSyncClient::errorString(result);
|
statusMessage = KOReaderSyncClient::errorString(result);
|
||||||
const char* detail = KOReaderSyncClient::lastFailureDetail();
|
const char* detail = KOReaderSyncClient::lastFailureDetail();
|
||||||
if (detail && detail[0]) {
|
if (detail && detail[0]) {
|
||||||
@@ -326,10 +289,6 @@ void KOReaderSyncActivity::performSync() {
|
|||||||
state = SHOWING_RESULT;
|
state = SHOWING_RESULT;
|
||||||
|
|
||||||
// Default to the option that corresponds to the furthest progress.
|
// Default to the option that corresponds to the furthest progress.
|
||||||
// Compare in the shared CrossPoint coordinate system (spine → page → paragraph)
|
|
||||||
// rather than percentage, since percentages are derived differently on each
|
|
||||||
// side and lose resolution. Remote has already been mapped via
|
|
||||||
// ensureRemotePositionMapped() at this point.
|
|
||||||
auto isLocalAhead = [&]() {
|
auto isLocalAhead = [&]() {
|
||||||
if (remotePosition.spineIndex < 0) {
|
if (remotePosition.spineIndex < 0) {
|
||||||
return localProgress.percentage > remoteProgress.percentage; // mapping unavailable; fall back
|
return localProgress.percentage > remoteProgress.percentage; // mapping unavailable; fall back
|
||||||
@@ -350,6 +309,49 @@ void KOReaderSyncActivity::performSync() {
|
|||||||
requestUpdate(true);
|
requestUpdate(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void KOReaderSyncActivity::performSync() {
|
||||||
|
if (!calculateDocumentHash()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Local mapping is only needed for compare/upload paths.
|
||||||
|
// Pull-only modes can skip this expensive step and go straight to remote fetch.
|
||||||
|
if (syncIntent != KOReaderSyncIntentState::PULL_REMOTE && syncIntent != KOReaderSyncIntentState::AUTO_PULL) {
|
||||||
|
// Precompute local mapping before first network request so the expensive
|
||||||
|
// inflate/index work happens before TLS. This avoids a second local mapping
|
||||||
|
// pass later and keeps the upload path lightweight.
|
||||||
|
{
|
||||||
|
RenderLock lock(*this);
|
||||||
|
statusMessage = tr(STR_MAPPING_LOCAL);
|
||||||
|
}
|
||||||
|
requestUpdateAndWait();
|
||||||
|
if (!computeLocalProgressAndChapter()) {
|
||||||
|
{
|
||||||
|
RenderLock lock(*this);
|
||||||
|
state = SYNC_FAILED;
|
||||||
|
statusMessage = tr(STR_SYNC_FAILED_MSG);
|
||||||
|
}
|
||||||
|
requestUpdate(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Drop EPUB state before HTTPS to maximize contiguous heap for TLS.
|
||||||
|
releaseEpubForMapping();
|
||||||
|
|
||||||
|
// Push intent skips comparison UI but still warms an HTTP/TLS session first
|
||||||
|
// so PUT can reuse the connection instead of forcing a fresh handshake.
|
||||||
|
if (syncIntent == KOReaderSyncIntentState::PUSH_LOCAL || syncIntent == KOReaderSyncIntentState::AUTO_PUSH) {
|
||||||
|
if (!handleAutoPushPreflight()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
performUpload();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
performFetchAndCompare();
|
||||||
|
}
|
||||||
|
|
||||||
void KOReaderSyncActivity::performUpload() {
|
void KOReaderSyncActivity::performUpload() {
|
||||||
{
|
{
|
||||||
RenderLock lock(*this);
|
RenderLock lock(*this);
|
||||||
|
|||||||
@@ -103,6 +103,9 @@ class KOReaderSyncActivity final : public Activity {
|
|||||||
|
|
||||||
void onWifiSelectionComplete(bool success);
|
void onWifiSelectionComplete(bool success);
|
||||||
void performSync();
|
void performSync();
|
||||||
|
bool calculateDocumentHash();
|
||||||
|
bool handleAutoPushPreflight();
|
||||||
|
void performFetchAndCompare();
|
||||||
void performUpload();
|
void performUpload();
|
||||||
void closeCancelled();
|
void closeCancelled();
|
||||||
void resumeReader(KOReaderSyncOutcomeState outcome, const SyncResult* appliedResult = nullptr);
|
void resumeReader(KOReaderSyncOutcomeState outcome, const SyncResult* appliedResult = nullptr);
|
||||||
|
|||||||
Reference in New Issue
Block a user