return deleteBatch(delQuery, superfluousPaths, "blacklist");
}
+void SyncJournalDb::deleteStaleFlagsEntries()
+{
+ QMutexLocker locker(&_mutex);
+ if (!checkConnect())
+ return;
+
+ SqlQuery delQuery("DELETE FROM flags WHERE path != '' AND path NOT IN (SELECT path from metadata);", _db);
+ delQuery.exec();
+}
+
int SyncJournalDb::errorBlackListEntryCount()
{
int re = 0;
SyncJournalErrorBlacklistRecord errorBlacklistEntry(const QString &);
bool deleteStaleErrorBlacklistEntries(const QSet<QString> &keep);
+ /// Delete flags table entries that have no metadata correspondent
+ void deleteStaleFlagsEntries();
+
void avoidRenamesOnNextSync(const QString &path) { avoidRenamesOnNextSync(path.toUtf8()); }
void avoidRenamesOnNextSync(const QByteArray &path);
void setPollInfo(const PollInfo &);
Optional<PinState> Vfs::pinStateInDb(const QString &folderPath)
{
- return _setupParams.journal->internalPinStates().effectiveForPath(folderPath.toUtf8());
+ auto pin = _setupParams.journal->internalPinStates().effectiveForPath(folderPath.toUtf8());
+ return pin;
}
-Vfs::AvailabilityResult Vfs::availabilityInDb(const QString &folderPath, const QString &pinPath)
+Vfs::AvailabilityResult Vfs::availabilityInDb(const QString &folderPath)
{
- auto pin = _setupParams.journal->internalPinStates().effectiveForPathRecursive(pinPath.toUtf8());
+ auto path = folderPath.toUtf8();
+ auto pin = _setupParams.journal->internalPinStates().effectiveForPathRecursive(path);
// not being able to retrieve the pin state isn't too bad
- auto hydrationStatus = _setupParams.journal->hasHydratedOrDehydratedFiles(folderPath.toUtf8());
+ auto hydrationStatus = _setupParams.journal->hasHydratedOrDehydratedFiles(path);
if (!hydrationStatus)
return AvailabilityError::DbError;
// Db-backed pin state handling. Derived classes may use it to implement pin states.
bool setPinStateInDb(const QString &folderPath, PinState state);
Optional<PinState> pinStateInDb(const QString &folderPath);
- // sadly for virtual files the path in the metadata table can differ from path in 'flags'
- AvailabilityResult availabilityInDb(const QString &folderPath, const QString &pinPath);
+ AvailabilityResult availabilityInDb(const QString &folderPath);
// the parameters passed to start()
VfsSetupParams _setupParams;
// Change the file's pin state if it's contradictory to being hydrated
// (suffix-virtual file's pin state is stored at the hydrated path)
- QString pinPath = relativepath;
- if (_vfs->mode() == Vfs::WithSuffix && pinPath.endsWith(_vfs->fileSuffix()))
- pinPath.chop(_vfs->fileSuffix().size());
- const auto pin = _vfs->pinState(pinPath);
+ const auto pin = _vfs->pinState(relativepath);
if (pin && *pin == PinState::OnlineOnly) {
- _vfs->setPinState(pinPath, PinState::Unspecified);
+ _vfs->setPinState(relativepath, PinState::Unspecified);
}
// Add to local discovery
continue;
// Update the pin state on all items
- auto pinPath = data.folderRelativePathNoVfsSuffix();
- data.folder->vfs().setPinState(pinPath, PinState::AlwaysLocal);
+ data.folder->vfs().setPinState(data.folderRelativePath, PinState::AlwaysLocal);
// Trigger sync
data.folder->schedulePathForLocalDiscovery(data.folderRelativePath);
continue;
// Update the pin state on all items
- auto pinPath = data.folderRelativePathNoVfsSuffix();
- data.folder->vfs().setPinState(pinPath, PinState::OnlineOnly);
+ data.folder->vfs().setPinState(data.folderRelativePath, PinState::OnlineOnly);
// Trigger sync
data.folder->schedulePathForLocalDiscovery(data.folderRelativePath);
if (!isVfsWithSuffix())
return;
- QByteArray pinPath = record._path;
- if (record.isVirtualFile()) {
- const auto suffix = _discoveryData->_syncOptions._vfs->fileSuffix().toUtf8();
- if (pinPath.endsWith(suffix))
- pinPath.chop(suffix.size());
- }
- auto pin = _discoveryData->_statedb->internalPinStates().rawForPath(pinPath);
+ auto pin = _discoveryData->_statedb->internalPinStates().rawForPath(record._path);
if (!pin || *pin == PinState::Inherited)
pin = _pinState;
qCDebug(lcPropagateDownload) << "Download of previous virtual file finished" << fn;
QFile::remove(fn);
propagator()->_journal->deleteFileRecord(virtualFile);
+
+ // Move the pin state to the new location
+ auto pin = propagator()->_journal->internalPinStates().rawForPath(_item->_file.toUtf8());
+ if (pin && *pin != PinState::Inherited) {
+ vfs->setPinState(virtualFile, *pin);
+ vfs->setPinState(_item->_file, PinState::Inherited);
+ }
}
}
conflictRecordMaintenance();
+ _journal->deleteStaleFlagsEntries();
_journal->commit("All Finished.", false);
// Send final progress information even if no
#include "syncfileitem.h"
#include "filesystem.h"
+#include "common/syncjournaldb.h"
namespace OCC {
SyncFileItem virtualItem(item);
virtualItem._file = item._renameTarget;
createPlaceholder(virtualItem);
+
+ // Move the item's pin state
+ auto pin = _setupParams.journal->internalPinStates().rawForPath(item._file.toUtf8());
+ if (pin && *pin != PinState::Inherited) {
+ setPinState(item._renameTarget, *pin);
+ setPinState(item._file, PinState::Inherited);
+ }
}
void VfsSuffix::convertToPlaceholder(const QString &, const SyncFileItem &, const QString &)
Vfs::AvailabilityResult VfsSuffix::availability(const QString &folderPath)
{
- const auto suffix = fileSuffix();
- QString pinPath = folderPath;
- if (pinPath.endsWith(suffix))
- pinPath.chop(suffix.size());
- return availabilityInDb(folderPath, pinPath);
+ return availabilityInDb(folderPath);
}
} // namespace OCC
triggerDownload(fakeFolder, "unspec/file1");
setPin("local/file2", PinState::OnlineOnly);
- setPin("online/file2", PinState::AlwaysLocal);
+ setPin("online/file2.owncloud", PinState::AlwaysLocal);
QVERIFY(fakeFolder.syncOnce());
QCOMPARE(*vfs->availability("unspec"), VfsItemAvailability::AllHydrated);
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
// root is unspecified
- QCOMPARE(*vfs->pinState("file1"), PinState::Unspecified);
+ QCOMPARE(*vfs->pinState("file1.owncloud"), PinState::Unspecified);
QCOMPARE(*vfs->pinState("local/file1"), PinState::AlwaysLocal);
QCOMPARE(*vfs->pinState("online/file1"), PinState::Unspecified);
QCOMPARE(*vfs->pinState("unspec/file1"), PinState::Unspecified);
QCOMPARE(*vfs->pinState("onlinerenamed2/file1rename"), PinState::Unspecified);
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
+
+ // When a file is deleted and later a new file has the same name, the old pin
+ // state isn't preserved.
+ QCOMPARE(*vfs->pinState("onlinerenamed2/file1rename"), PinState::Unspecified);
+ fakeFolder.remoteModifier().remove("onlinerenamed2/file1rename");
+ QVERIFY(fakeFolder.syncOnce());
+ QCOMPARE(*vfs->pinState("onlinerenamed2/file1rename"), PinState::OnlineOnly);
+ fakeFolder.remoteModifier().insert("onlinerenamed2/file1rename");
+ QVERIFY(fakeFolder.syncOnce());
+ QCOMPARE(*vfs->pinState("onlinerenamed2/file1rename"), PinState::OnlineOnly);
+ QCOMPARE(*vfs->pinState("onlinerenamed2/file1rename.owncloud"), PinState::OnlineOnly);
}
};