Quellcode durchsuchen

Ensure local discovery on selective sync changes

As far as I'm aware local discovery can be skipped on folders that are
selective-sync blacklisted, so a local discovery is required when an
entry is removed from the blacklist.

Also rename
avoidReadFromDbOnNextSync() -> schedulePathForRemoteDiscovery()
since the old name might also imply it's not read from db in the local
discovery - which is not the case. Use Folder::
schedulePathForLocalDiscovery() for that.
Christian Kamm vor 7 Jahren
Ursprung
Commit
238ac53666

+ 1 - 1
src/cmd/cmd.cpp

@@ -303,7 +303,7 @@ void selectiveSyncFixup(OCC::SyncJournalDb *journal, const QStringList &newList)
         auto blackListSet = newList.toSet();
         const auto changes = (oldBlackListSet - blackListSet) + (blackListSet - oldBlackListSet);
         for (const auto &it : changes) {
-            journal->avoidReadFromDbOnNextSync(it);
+            journal->schedulePathForRemoteDiscovery(it);
         }
 
         journal->setSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList, newList);

+ 3 - 3
src/common/syncjournaldb.cpp

@@ -1819,10 +1819,10 @@ void SyncJournalDb::avoidRenamesOnNextSync(const QByteArray &path)
 
     // We also need to remove the ETags so the update phase refreshes the directory paths
     // on the next sync
-    avoidReadFromDbOnNextSync(path);
+    schedulePathForRemoteDiscovery(path);
 }
 
-void SyncJournalDb::avoidReadFromDbOnNextSync(const QByteArray &fileName)
+void SyncJournalDb::schedulePathForRemoteDiscovery(const QByteArray &fileName)
 {
     QMutexLocker locker(&_mutex);
 
@@ -2077,7 +2077,7 @@ void SyncJournalDb::markVirtualFileForDownloadRecursively(const QByteArray &path
     query.bindValue(1, path);
     query.exec();
 
-    // We also must make sure we do not read the files from the database (same logic as in avoidReadFromDbOnNextSync)
+    // We also must make sure we do not read the files from the database (same logic as in schedulePathForRemoteDiscovery)
     // This includes all the parents up to the root, but also all the directory within the selected dir.
     static_assert(ItemTypeDirectory == 2, "");
     query.prepare("UPDATE metadata SET md5='_invalid_' WHERE "

+ 4 - 4
src/common/syncjournaldb.h

@@ -169,8 +169,8 @@ public:
      * Any setFileRecord() call to affected directories before the next sync run will be
      * adjusted to retain the invalid etag via _etagStorageFilter.
      */
-    void avoidReadFromDbOnNextSync(const QString &fileName) { avoidReadFromDbOnNextSync(fileName.toUtf8()); }
-    void avoidReadFromDbOnNextSync(const QByteArray &fileName);
+    void schedulePathForRemoteDiscovery(const QString &fileName) { schedulePathForRemoteDiscovery(fileName.toUtf8()); }
+    void schedulePathForRemoteDiscovery(const QByteArray &fileName);
 
     /**
      * Wipe _etagStorageFilter. Also done implicitly on close().
@@ -180,7 +180,7 @@ public:
     /**
      * Ensures full remote discovery happens on the next sync.
      *
-     * Equivalent to calling avoidReadFromDbOnNextSync() for all files.
+     * Equivalent to calling schedulePathForRemoteDiscovery() for all files.
      */
     void forceRemoteDiscoveryNextSync();
 
@@ -390,7 +390,7 @@ private:
 
     /* Storing etags to these folders, or their parent folders, is filtered out.
      *
-     * When avoidReadFromDbOnNextSync() is called some etags to _invalid_ in the
+     * When schedulePathForRemoteDiscovery() is called some etags to _invalid_ in the
      * database. If this is done during a sync run, a later propagation job might
      * undo that by writing the correct etag to the database instead. This filter
      * will prevent this write and instead guarantee the _invalid_ etag stays in

+ 2 - 1
src/gui/accountsettings.cpp

@@ -662,7 +662,8 @@ void AccountSettings::slotEnableVfsCurrentFolder()
             auto oldBlacklist = folder->journalDb()->getSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList, &ok);
             folder->journalDb()->setSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList, {});
             for (const auto &entry : oldBlacklist) {
-                folder->journalDb()->avoidReadFromDbOnNextSync(entry);
+                folder->journalDb()->schedulePathForRemoteDiscovery(entry);
+                folder->schedulePathForLocalDiscovery(entry);
             }
 
             // Change the folder vfs mode and load the plugin

+ 8 - 2
src/gui/folder.cpp

@@ -603,8 +603,9 @@ void Folder::downloadVirtualFile(const QString &_relativepath)
     if (record._type == ItemTypeVirtualFile) {
         record._type = ItemTypeVirtualFileDownload;
         _journal.setFileRecord(record);
-        // Make sure we go over that file during the discovery
-        _journal.avoidReadFromDbOnNextSync(relativepath);
+        // Make sure we go over that file during the discovery even if
+        // no actual remote discovery would be necessary
+        _journal.schedulePathForRemoteDiscovery(relativepath);
     } else if (record._type == ItemTypeDirectory || relativepath.isEmpty()) {
         _journal.markVirtualFileForDownloadRecursively(relativepath);
     } else {
@@ -1125,6 +1126,11 @@ void Folder::slotNextSyncFullLocalDiscovery()
     _timeSinceLastFullLocalDiscovery.invalidate();
 }
 
+void Folder::schedulePathForLocalDiscovery(const QString &relativePath)
+{
+    _localDiscoveryTracker->addTouchedPath(relativePath.toUtf8());
+}
+
 void Folder::slotFolderConflicts(const QString &folder, const QStringList &conflictPaths)
 {
     if (folder != _definition.alias)

+ 8 - 0
src/gui/folder.h

@@ -348,6 +348,14 @@ public slots:
      */
     void dehydrateFile(const QString &relativepath);
 
+    /** Adds the path to the local discovery list
+     *
+     * A weaker version of slotNextSyncFullLocalDiscovery() that just
+     * schedules all parent and child items of the path for local
+     * discovery.
+     */
+    void schedulePathForLocalDiscovery(const QString &relativePath);
+
 private slots:
     void slotSyncStarted();
     void slotSyncFinished(bool);

+ 4 - 2
src/gui/folderstatusmodel.cpp

@@ -871,7 +871,8 @@ void FolderStatusModel::slotApplySelectiveSync()
             //The part that changed should not be read from the DB on next sync because there might be new folders
             // (the ones that are no longer in the blacklist)
             foreach (const auto &it, changes) {
-                folder->journalDb()->avoidReadFromDbOnNextSync(it);
+                folder->journalDb()->schedulePathForRemoteDiscovery(it);
+                folder->schedulePathForLocalDiscovery(it);
             }
             FolderMan::instance()->scheduleFolder(folder);
         }
@@ -1177,7 +1178,8 @@ void FolderStatusModel::slotSyncAllPendingBigFolders()
         // The part that changed should not be read from the DB on next sync because there might be new folders
         // (the ones that are no longer in the blacklist)
         foreach (const auto &it, undecidedList) {
-            folder->journalDb()->avoidReadFromDbOnNextSync(it);
+            folder->journalDb()->schedulePathForRemoteDiscovery(it);
+            folder->schedulePathForLocalDiscovery(it);
         }
         FolderMan::instance()->scheduleFolder(folder);
     }

+ 2 - 1
src/gui/selectivesyncdialog.cpp

@@ -497,7 +497,8 @@ void SelectiveSyncDialog::accept()
         auto blackListSet = blackList.toSet();
         auto changes = (oldBlackListSet - blackListSet) + (blackListSet - oldBlackListSet);
         foreach (const auto &it, changes) {
-            _folder->journalDb()->avoidReadFromDbOnNextSync(it);
+            _folder->journalDb()->schedulePathForRemoteDiscovery(it);
+            _folder->schedulePathForLocalDiscovery(it);
         }
 
         folderMan->scheduleFolder(_folder);

+ 1 - 1
src/gui/sharemanager.cpp

@@ -38,7 +38,7 @@ static void updateFolder(const AccountPtr &account, const QString &path)
             // Workaround the fact that the server does not invalidate the etags of parent directories
             // when something is shared.
             auto relative = path.midRef(f->remotePathTrailingSlash().length());
-            f->journalDb()->avoidReadFromDbOnNextSync(relative.toString());
+            f->journalDb()->schedulePathForRemoteDiscovery(relative.toString());
 
             // Schedule a sync so it can update the remote permission flag and let the socket API
             // know about the shared icon.

+ 1 - 1
src/libsync/propagatedownload.cpp

@@ -688,7 +688,7 @@ void PropagateDownloadFile::slotGetFinished()
             // As a precaution against bugs that cause our database and the
             // reality on the server to diverge, rediscover this folder on the
             // next sync run.
-            propagator()->_journal->avoidReadFromDbOnNextSync(_item->_file);
+            propagator()->_journal->schedulePathForRemoteDiscovery(_item->_file);
         }
 
         QByteArray errorBody;

+ 1 - 1
src/libsync/propagateupload.cpp

@@ -643,7 +643,7 @@ void PropagateUploadFileCommon::commonErrorHandling(AbstractNetworkJob *job)
 
         // Maybe the bad etag is in the database, we need to clear the
         // parent folder etag so we won't read from DB next sync.
-        propagator()->_journal->avoidReadFromDbOnNextSync(_item->_file);
+        propagator()->_journal->schedulePathForRemoteDiscovery(_item->_file);
         propagator()->_anotherSyncNeeded = true;
     }
 

+ 1 - 1
src/libsync/syncengine.cpp

@@ -491,7 +491,7 @@ void SyncEngine::startSync()
     }
 
     // Functionality like selective sync might have set up etag storage
-    // filtering via avoidReadFromDbOnNextSync(). This *is* the next sync, so
+    // filtering via schedulePathForRemoteDiscovery(). This *is* the next sync, so
     // undo the filter to allow this sync to retrieve and store the correct etags.
     _journal->clearEtagStorageFilter();
 

+ 2 - 2
test/testselectivesync.cpp

@@ -69,7 +69,7 @@ private slots:
 
         auto oldSync = fakeFolder.currentLocalState();
         // syncing again should do the same
-        fakeFolder.syncEngine().journal()->avoidReadFromDbOnNextSync(QString("A/newBigDir"));
+        fakeFolder.syncEngine().journal()->schedulePathForRemoteDiscovery(QString("A/newBigDir"));
         QVERIFY(fakeFolder.syncOnce());
         QCOMPARE(fakeFolder.currentLocalState(), oldSync);
         QCOMPARE(newBigFolder.count(), 1); // (since we don't have a real Folder, the files were not added to any list)
@@ -80,7 +80,7 @@ private slots:
         // Simulate that we accept all files by seting a wildcard white list
         fakeFolder.syncEngine().journal()->setSelectiveSyncList(SyncJournalDb::SelectiveSyncWhiteList,
             QStringList() << QLatin1String("/"));
-        fakeFolder.syncEngine().journal()->avoidReadFromDbOnNextSync(QString("A/newBigDir"));
+        fakeFolder.syncEngine().journal()->schedulePathForRemoteDiscovery(QString("A/newBigDir"));
         QVERIFY(fakeFolder.syncOnce());
         QCOMPARE(newBigFolder.count(), 0);
         QCOMPARE(sizeRequests.count(), 0);

+ 1 - 1
test/testsyncengine.cpp

@@ -171,7 +171,7 @@ private slots:
         // Remove subFolderA with selectiveSync:
         fakeFolder.syncEngine().journal()->setSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList,
                                                                 {"parentFolder/subFolderA/"});
-        fakeFolder.syncEngine().journal()->avoidReadFromDbOnNextSync(QByteArrayLiteral("parentFolder/subFolderA/"));
+        fakeFolder.syncEngine().journal()->schedulePathForRemoteDiscovery(QByteArrayLiteral("parentFolder/subFolderA/"));
         auto getEtag = [&](const QByteArray &file) {
             SyncJournalFileRecord rec;
             fakeFolder.syncJournal().getFileRecord(file, &rec);

+ 1 - 1
test/testsyncjournaldb.cpp

@@ -236,7 +236,7 @@ private slots:
         makeEntry("foodir/subdir/subsubdir/file", ItemTypeFile);
         makeEntry("foodir/subdir/otherdir", ItemTypeDirectory);
 
-        _db.avoidReadFromDbOnNextSync(QByteArray("foodir/subdir"));
+        _db.schedulePathForRemoteDiscovery(QByteArray("foodir/subdir"));
 
         // Direct effects of parent directories being set to _invalid_
         QCOMPARE(getEtag("foodir"), invalidEtag);

+ 1 - 1
test/testsyncmove.cpp

@@ -126,7 +126,7 @@ private slots:
         // Remove subFolderA with selectiveSync:
         fakeFolder.syncEngine().journal()->setSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList,
             { "parentFolder/subFolderA/" });
-        fakeFolder.syncEngine().journal()->avoidReadFromDbOnNextSync(QByteArrayLiteral("parentFolder/subFolderA/"));
+        fakeFolder.syncEngine().journal()->schedulePathForRemoteDiscovery(QByteArrayLiteral("parentFolder/subFolderA/"));
 
         fakeFolder.syncOnce();
 

+ 2 - 2
test/testsyncvirtualfiles.cpp

@@ -44,7 +44,7 @@ void triggerDownload(FakeFolder &folder, const QByteArray &path)
         return;
     record._type = ItemTypeVirtualFileDownload;
     journal.setFileRecord(record);
-    journal.avoidReadFromDbOnNextSync(record._path);
+    journal.schedulePathForRemoteDiscovery(record._path);
 }
 
 void markForDehydration(FakeFolder &folder, const QByteArray &path)
@@ -56,7 +56,7 @@ void markForDehydration(FakeFolder &folder, const QByteArray &path)
         return;
     record._type = ItemTypeVirtualFileDehydration;
     journal.setFileRecord(record);
-    journal.avoidReadFromDbOnNextSync(record._path);
+    journal.schedulePathForRemoteDiscovery(record._path);
 }
 
 QSharedPointer<Vfs> setupVfs(FakeFolder &folder)