Skip to content

Commit

Permalink
Merge pull request #5481 from nextcloud/backport/5459/stable-3.7
Browse files Browse the repository at this point in the history
[stable-3.7] Always discover blacklisted folders to avoid data loss when modifying selectivesync list.
  • Loading branch information
allexzander authored Feb 28, 2023
2 parents 035fa24 + b1186e2 commit ebfaefb
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 1 deletion.
5 changes: 4 additions & 1 deletion src/libsync/discovery.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ void ProcessDirectoryJob::start()
// Check whether a normal local query is even necessary
if (_queryLocal == NormalQuery) {
if (!_discoveryData->_shouldDiscoverLocaly(_currentFolder._local)
&& (_currentFolder._local == _currentFolder._original || !_discoveryData->_shouldDiscoverLocaly(_currentFolder._original))) {
&& (_currentFolder._local == _currentFolder._original || !_discoveryData->_shouldDiscoverLocaly(_currentFolder._original))
&& !_discoveryData->isInSelectiveSyncBlackList(_currentFolder._original)) {
_queryLocal = ParentNotChanged;
qCDebug(lcDisco) << "adjusted discovery policy" << _currentFolder._server << _queryServer << _currentFolder._local << _queryLocal;
}
Expand Down Expand Up @@ -1586,6 +1587,7 @@ void ProcessDirectoryJob::processBlacklisted(const PathTuple &path, const OCC::L
item->_instruction = CSYNC_INSTRUCTION_IGNORE;
item->_status = SyncFileItem::FileIgnored;
item->_errorString = tr("Ignored because of the \"choose what to sync\" blacklist");
qCInfo(lcDisco) << "Ignored because of the \"choose what to sync\" blacklist" << item->_file << "direction" << item->_direction;
_childIgnored = true;
}

Expand Down Expand Up @@ -1785,6 +1787,7 @@ int ProcessDirectoryJob::processSubJobs(int nbJobs)
}
if (_childIgnored && _dirItem->_instruction == CSYNC_INSTRUCTION_REMOVE) {
// Do not remove a directory that has ignored files
qCInfo(lcDisco) << "Child ignored for a folder to remove" << _dirItem->_file << "direction" << _dirItem->_direction;
_dirItem->_instruction = CSYNC_INSTRUCTION_NONE;
}
}
Expand Down
81 changes: 81 additions & 0 deletions test/testlocaldiscovery.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,87 @@ class TestLocalDiscovery : public QObject
Q_OBJECT

private slots:
void testSelectiveSyncQuotaExceededDataLoss()
{
FakeFolder fakeFolder{FileInfo{}};

// folders that fit the quota
fakeFolder.localModifier().mkdir("big-files");
fakeFolder.localModifier().insert("big-files/bigfile_A.data", 1000);
fakeFolder.localModifier().insert("big-files/bigfile_B.data", 1000);
fakeFolder.localModifier().insert("big-files/bigfile_C.data", 1000);
fakeFolder.localModifier().mkdir("more-big-files");
fakeFolder.localModifier().insert("more-big-files/bigfile_A.data", 1000);
fakeFolder.localModifier().insert("more-big-files/bigfile_B.data", 1000);
fakeFolder.localModifier().insert("more-big-files/bigfile_C.data", 1000);
QVERIFY(fakeFolder.syncOnce());
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());

// folders that won't fit
fakeFolder.localModifier().mkdir("big-files-wont-fit");
fakeFolder.localModifier().insert("big-files-wont-fit/bigfile_A.data", 800);
fakeFolder.localModifier().insert("big-files-wont-fit/bigfile_B.data", 800);
fakeFolder.localModifier().mkdir("more-big-files-wont-fit");
fakeFolder.localModifier().insert("more-big-files-wont-fit/bigfile_A.data", 800);
fakeFolder.localModifier().insert("more-big-files-wont-fit/bigfile_B.data", 800);

const auto remoteQuota = 600;
QObject parent;
fakeFolder.setServerOverride([&](QNetworkAccessManager::Operation op, const QNetworkRequest &request, QIODevice *outgoingData) -> QNetworkReply * {
Q_UNUSED(outgoingData)
if (op == QNetworkAccessManager::PutOperation) {
if (request.rawHeader("OC-Total-Length").toInt() > remoteQuota) {
return new FakeErrorReply(op, request, &parent, 507);
}
}
return nullptr;
});

QVERIFY(!fakeFolder.syncOnce());

fakeFolder.syncEngine().journal()->setSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList, {"big-files-wont-fit/", "more-big-files-wont-fit/"});
fakeFolder.syncEngine().setLocalDiscoveryOptions(LocalDiscoveryStyle::DatabaseAndFilesystem, {"big-files-wont-fit/", "more-big-files-wont-fit/"});

QVERIFY(fakeFolder.syncEngine().journal()->wipeErrorBlacklist());
QVERIFY(fakeFolder.syncOnce());
QVERIFY(fakeFolder.currentLocalState().find("big-files-wont-fit/bigfile_A.data"));
QVERIFY(fakeFolder.currentLocalState().find("big-files-wont-fit/bigfile_B.data"));
QVERIFY(fakeFolder.currentLocalState().find("more-big-files-wont-fit/bigfile_A.data"));
QVERIFY(fakeFolder.currentLocalState().find("more-big-files-wont-fit/bigfile_B.data"));
QVERIFY(!fakeFolder.currentRemoteState().find("big-files-wont-fit/bigfile_A.data"));
QVERIFY(!fakeFolder.currentRemoteState().find("big-files-wont-fit/bigfile_B.data"));
QVERIFY(!fakeFolder.currentRemoteState().find("more-big-files-wont-fit/bigfile_A.data"));
QVERIFY(!fakeFolder.currentRemoteState().find("more-big-files-wont-fit/bigfile_B.data"));

fakeFolder.syncEngine().journal()->setSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList, {"big-files-wont-fit/", "more-big-files-wont-fit/", "big-files/"});
fakeFolder.syncEngine().journal()->setSelectiveSyncList(SyncJournalDb::SelectiveSyncWhiteList, {"more-big-files/"});
fakeFolder.syncEngine().setLocalDiscoveryOptions(LocalDiscoveryStyle::DatabaseAndFilesystem, {"big-files/", "more-big-files/"});

QVERIFY(fakeFolder.syncOnce());
QVERIFY(fakeFolder.currentLocalState().find("big-files-wont-fit/bigfile_A.data"));
QVERIFY(fakeFolder.currentLocalState().find("big-files-wont-fit/bigfile_B.data"));
QVERIFY(fakeFolder.currentLocalState().find("more-big-files-wont-fit/bigfile_A.data"));
QVERIFY(fakeFolder.currentLocalState().find("more-big-files-wont-fit/bigfile_B.data"));
QVERIFY(!fakeFolder.currentRemoteState().find("big-files-wont-fit/bigfile_A.data"));
QVERIFY(!fakeFolder.currentRemoteState().find("big-files-wont-fit/bigfile_B.data"));
QVERIFY(!fakeFolder.currentRemoteState().find("more-big-files-wont-fit/bigfile_A.data"));
QVERIFY(!fakeFolder.currentRemoteState().find("more-big-files-wont-fit/bigfile_B.data"));

fakeFolder.syncEngine().journal()->setSelectiveSyncList(SyncJournalDb::SelectiveSyncWhiteList, {"big-files/", "more-big-files/"});
fakeFolder.syncEngine().journal()->setSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList, {"big-files-wont-fit/", "more-big-files-wont-fit/"});
fakeFolder.syncEngine().setLocalDiscoveryOptions(LocalDiscoveryStyle::DatabaseAndFilesystem, {"big-files/", "more-big-files/"});

QVERIFY(fakeFolder.syncOnce());
QVERIFY(fakeFolder.currentLocalState().find("big-files-wont-fit/bigfile_A.data"));
QVERIFY(fakeFolder.currentLocalState().find("big-files-wont-fit/bigfile_B.data"));
QVERIFY(fakeFolder.currentLocalState().find("more-big-files-wont-fit/bigfile_A.data"));
QVERIFY(fakeFolder.currentLocalState().find("more-big-files-wont-fit/bigfile_B.data"));
QVERIFY(!fakeFolder.currentRemoteState().find("big-files-wont-fit/bigfile_A.data"));
QVERIFY(!fakeFolder.currentRemoteState().find("big-files-wont-fit/bigfile_B.data"));
QVERIFY(!fakeFolder.currentRemoteState().find("more-big-files-wont-fit/bigfile_A.data"));
QVERIFY(!fakeFolder.currentRemoteState().find("more-big-files-wont-fit/bigfile_B.data"));
}

// Check correct behavior when local discovery is partially drawn from the db
void testLocalDiscoveryStyle()
{
Expand Down

0 comments on commit ebfaefb

Please sign in to comment.