Skip to content

Commit b385cf5

Browse files
committed
fix: keep a full local discovery request across a running sync
slotNextSyncFullLocalDiscovery() is documented to ensure the next sync performs a full local discovery, but it only invalidated _timeSinceLastFullLocalDiscovery. A sync that was already running restarts that timer when it finishes, so a request arriving mid-sync -- the common case, since the watcher emits lostChanges() precisely while changes are pouring in -- was silently dropped and the next sync read from the database instead. The missed changes then waited for the periodic full local discovery, an hour by default, or forever where that interval is configured negative. Track whether a request arrived after the running sync fixed its discovery style, and only mark a full local discovery as done when none did. While here, check the selective sync list in warnOnNewExcludedItem() before stat()ing the file: the function runs once per added file and the list is empty unless the user configured selective sync. Signed-off-by: Felipe Tumonis <ftumonis@gmail.com>
1 parent 340f128 commit b385cf5

2 files changed

Lines changed: 34 additions & 10 deletions

File tree

src/gui/folder.cpp

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1203,6 +1203,10 @@ void Folder::startSync(const QStringList &pathList)
12031203
fullLocalDiscoveryInterval.count() >= 0 // negative means we don't require periodic full runs
12041204
&& _timeSinceLastFullLocalDiscovery.hasExpired(fullLocalDiscoveryInterval.count());
12051205

1206+
// From here on the sync's discovery style is fixed, so a request arriving later is about a
1207+
// state this sync will not see and must not be marked as covered by it.
1208+
_fullLocalDiscoveryRequestedDuringSync = false;
1209+
12061210
if (singleItemDiscoveryOptions.isValid() && singleItemDiscoveryOptions.discoveryPath != QStringLiteral("/")) {
12071211
qCInfo(lcFolder) << "Going to sync just one file";
12081212
_engine->setLocalDiscoveryOptions(LocalDiscoveryStyle::DatabaseAndFilesystem, {singleItemDiscoveryOptions.discoveryPath});
@@ -1369,7 +1373,8 @@ void Folder::slotSyncFinished(bool success)
13691373
if ((_syncResult.status() == SyncResult::Success
13701374
|| _syncResult.status() == SyncResult::Problem)
13711375
&& success) {
1372-
if (_engine->lastLocalDiscoveryStyle() == LocalDiscoveryStyle::FilesystemOnly) {
1376+
if (_engine->lastLocalDiscoveryStyle() == LocalDiscoveryStyle::FilesystemOnly
1377+
&& !_fullLocalDiscoveryRequestedDuringSync) {
13731378
_timeSinceLastFullLocalDiscovery.start();
13741379
}
13751380
}
@@ -1588,6 +1593,10 @@ void Folder::slotScheduleThisFolder()
15881593
void Folder::slotNextSyncFullLocalDiscovery()
15891594
{
15901595
_timeSinceLastFullLocalDiscovery.invalidate();
1596+
1597+
// Invalidating on its own is not enough: a sync that is already running restarts the timer when
1598+
// it finishes (see slotSyncFinished), which would drop this request.
1599+
_fullLocalDiscoveryRequestedDuringSync = true;
15911600
}
15921601

15931602
void Folder::setSilenceErrorsUntilNextSync(bool silenceErrors)
@@ -1618,15 +1627,8 @@ void Folder::warnOnNewExcludedItem(const SyncJournalFileRecord &record, const QS
16181627
return;
16191628
}
16201629

1621-
// Don't warn for items that no longer exist.
1622-
// Note: This assumes we're getting file watcher notifications
1623-
// for folders only on creation and deletion - if we got a notification
1624-
// on content change that would create spurious warnings.
1625-
const auto fullPath = QString{_canonicalLocalPath + path};
1626-
if (!FileSystem::fileExists(fullPath)) {
1627-
return;
1628-
}
1629-
1630+
// Checked before touching the filesystem below: this runs once per added file, and the list is
1631+
// empty unless the user configured selective sync.
16301632
bool ok = false;
16311633
const auto selectiveSyncList = _journal.getSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList, &ok);
16321634
if (!ok) {
@@ -1636,6 +1638,15 @@ void Folder::warnOnNewExcludedItem(const SyncJournalFileRecord &record, const QS
16361638
return;
16371639
}
16381640

1641+
// Don't warn for items that no longer exist.
1642+
// Note: This assumes we're getting file watcher notifications
1643+
// for folders only on creation and deletion - if we got a notification
1644+
// on content change that would create spurious warnings.
1645+
const auto fullPath = QString{_canonicalLocalPath + path};
1646+
if (!FileSystem::fileExists(fullPath)) {
1647+
return;
1648+
}
1649+
16391650
QFileInfo excludeItemFileInfo(fullPath);
16401651
const auto excludeItemFilePath = excludeItemFileInfo.filePath();
16411652
const auto message = FileSystem::isDir(fullPath)
@@ -1749,6 +1760,10 @@ void Folder::registerFolderWatcher()
17491760
this, [this](const QString &path) { slotWatchedPathChanged(path, Folder::ChangeReason::Other); });
17501761
connect(_folderWatcher.data(), &FolderWatcher::lostChanges,
17511762
this, &Folder::slotNextSyncFullLocalDiscovery);
1763+
// The watcher reports no paths along with lostChanges(), so nothing else would trigger the
1764+
// sync that is supposed to pick the missed changes up.
1765+
connect(_folderWatcher.data(), &FolderWatcher::lostChanges,
1766+
this, &Folder::scheduleThisFolderSoon);
17521767
connect(_folderWatcher.data(), &FolderWatcher::becameUnreliable,
17531768
this, &Folder::slotWatcherUnreliable);
17541769
if (_accountState->account()->capabilities().filesLockAvailable()) {
@@ -1769,6 +1784,7 @@ void Folder::disconnectFolderWatcher()
17691784
}
17701785
disconnect(_folderWatcher.data(), &FolderWatcher::pathChanged, nullptr, nullptr);
17711786
disconnect(_folderWatcher.data(), &FolderWatcher::lostChanges, this, &Folder::slotNextSyncFullLocalDiscovery);
1787+
disconnect(_folderWatcher.data(), &FolderWatcher::lostChanges, this, &Folder::scheduleThisFolderSoon);
17721788
disconnect(_folderWatcher.data(), &FolderWatcher::becameUnreliable, this, &Folder::slotWatcherUnreliable);
17731789
if (_accountState->account()->capabilities().filesLockAvailable()) {
17741790
disconnect(_folderWatcher.data(), &FolderWatcher::filesLockReleased, this, &Folder::slotFilesLockReleased);

src/gui/folder.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -580,6 +580,14 @@ private slots:
580580
QElapsedTimer _timeSinceLastSyncDone;
581581
QElapsedTimer _timeSinceLastSyncStart;
582582
QElapsedTimer _timeSinceLastFullLocalDiscovery;
583+
584+
/** Whether a full local discovery was requested after the running sync picked its discovery
585+
* style, and is therefore not covered by it.
586+
*
587+
* Without this, slotSyncFinished() would restart _timeSinceLastFullLocalDiscovery and the
588+
* request would be lost.
589+
*/
590+
bool _fullLocalDiscoveryRequestedDuringSync = false;
583591
std::chrono::milliseconds _lastSyncDuration;
584592

585593
/// The number of syncs that failed in a row.

0 commit comments

Comments
 (0)