Vfs: Distinguish availability error kinds #7143

Previously "no-availability" meant db-error and querying the
availability of a nonexistant path returned AllHydrated.

Now, the availability has a DbError and a NoSuchItem error case.
This commit is contained in:
Christian Kamm 2019-04-25 11:10:52 +02:00 committed by Kevin Ottens
parent 1e5ae77994
commit 7774b8049e
No known key found for this signature in database
GPG key ID: 074BBBCB8DECC9E2
5 changed files with 45 additions and 28 deletions

View file

@ -79,13 +79,13 @@ Optional<PinState> Vfs::pinStateInDb(const QString &folderPath)
return _setupParams.journal->internalPinStates().effectiveForPath(folderPath.toUtf8());
}
Optional<VfsItemAvailability> Vfs::availabilityInDb(const QString &folderPath, const QString &pinPath)
Vfs::AvailabilityResult Vfs::availabilityInDb(const QString &folderPath, const QString &pinPath)
{
auto pin = _setupParams.journal->internalPinStates().effectiveForPathRecursive(pinPath.toUtf8());
// not being able to retrieve the pin state isn't too bad
auto hydrationStatus = _setupParams.journal->hasHydratedOrDehydratedFiles(folderPath.toUtf8());
if (!hydrationStatus)
return {};
return AvailabilityError::DbError;
if (hydrationStatus->hasDehydrated) {
if (hydrationStatus->hasHydrated)
@ -94,12 +94,13 @@ Optional<VfsItemAvailability> Vfs::availabilityInDb(const QString &folderPath, c
return VfsItemAvailability::OnlineOnly;
else
return VfsItemAvailability::AllDehydrated;
} else {
} else if (hydrationStatus->hasHydrated) {
if (pin && *pin == PinState::AlwaysLocal)
return VfsItemAvailability::AlwaysLocal;
else
return VfsItemAvailability::AllHydrated;
}
return AvailabilityError::NoSuchItem;
}
VfsOff::VfsOff(QObject *parent)

View file

@ -99,6 +99,15 @@ public:
static QString modeToString(Mode mode);
static Optional<Mode> modeFromString(const QString &str);
enum class AvailabilityError
{
// Availability can't be retrieved due to db error
DbError,
// Availability not available since the item doesn't exist
NoSuchItem,
};
using AvailabilityResult = Result<VfsItemAvailability, AvailabilityError>;
public:
explicit Vfs(QObject* parent = nullptr);
virtual ~Vfs();
@ -204,6 +213,8 @@ public:
* plugins will override it to retrieve the state from elsewhere.
*
* folderPath is relative to the sync folder. Can be "" for root folder.
*
* Returns none on retrieval error.
*/
virtual Optional<PinState> pinState(const QString &folderPath) = 0;
@ -214,7 +225,7 @@ public:
*
* folderPath is relative to the sync folder. Can be "" for root folder.
*/
virtual Optional<VfsItemAvailability> availability(const QString &folderPath) = 0;
virtual AvailabilityResult availability(const QString &folderPath) = 0;
public slots:
/** Update in-sync state based on SyncFileStatusTracker signal.
@ -247,7 +258,7 @@ protected:
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'
Optional<VfsItemAvailability> availabilityInDb(const QString &folderPath, const QString &pinPath);
AvailabilityResult availabilityInDb(const QString &folderPath, const QString &pinPath);
// the parameters passed to start()
VfsSetupParams _setupParams;
@ -282,7 +293,7 @@ public:
bool setPinState(const QString &, PinState) override { return true; }
Optional<PinState> pinState(const QString &) override { return PinState::AlwaysLocal; }
Optional<VfsItemAvailability> availability(const QString &) override { return VfsItemAvailability::AlwaysLocal; }
AvailabilityResult availability(const QString &) override { return VfsItemAvailability::AlwaysLocal; }
public slots:
void fileStatusChanged(const QString &, SyncFileStatus) override {}

View file

@ -1049,26 +1049,29 @@ void SocketApi::command_GET_MENU_ITEMS(const QString &argument, OCC::SocketListe
auto merge = [](VfsItemAvailability lhs, VfsItemAvailability rhs) {
if (lhs == rhs)
return lhs;
auto l = int(lhs) < int(rhs) ? lhs : rhs; // reduce cases by sorting
auto r = int(lhs) < int(rhs) ? rhs : lhs;
if (l == VfsItemAvailability::AlwaysLocal && r == VfsItemAvailability::AllHydrated)
if (int(lhs) > int(rhs))
std::swap(lhs, rhs); // reduce cases ensuring lhs < rhs
if (lhs == VfsItemAvailability::AlwaysLocal && rhs == VfsItemAvailability::AllHydrated)
return VfsItemAvailability::AllHydrated;
if (l == VfsItemAvailability::AllDehydrated && r == VfsItemAvailability::OnlineOnly)
if (lhs == VfsItemAvailability::AllDehydrated && rhs == VfsItemAvailability::OnlineOnly)
return VfsItemAvailability::AllDehydrated;
return VfsItemAvailability::Mixed;
};
for (const auto &file : files) {
auto fileData = FileData::get(file);
auto availability = syncFolder->vfs().availability(fileData.folderRelativePath);
if (!availability)
availability = VfsItemAvailability::Mixed; // db error
if (!availability) {
if (availability.error() == Vfs::AvailabilityError::DbError)
availability = VfsItemAvailability::Mixed;
if (availability.error() == Vfs::AvailabilityError::NoSuchItem)
continue;
}
if (!combined) {
combined = availability;
combined = *availability;
} else {
combined = merge(*combined, *availability);
}
}
ENFORCE(combined);
// TODO: Should be a submenu, should use icons
auto makePinContextMenu = [&](bool makeAvailableLocally, bool freeSpace) {
@ -1082,18 +1085,20 @@ void SocketApi::command_GET_MENU_ITEMS(const QString &argument, OCC::SocketListe
+ Utility::vfsFreeSpaceActionText());
};
switch (*combined) {
case VfsItemAvailability::AlwaysLocal:
makePinContextMenu(false, true);
break;
case VfsItemAvailability::AllHydrated:
case VfsItemAvailability::Mixed:
makePinContextMenu(true, true);
break;
case VfsItemAvailability::AllDehydrated:
case VfsItemAvailability::OnlineOnly:
makePinContextMenu(true, false);
break;
if (combined) {
switch (*combined) {
case VfsItemAvailability::AlwaysLocal:
makePinContextMenu(false, true);
break;
case VfsItemAvailability::AllHydrated:
case VfsItemAvailability::Mixed:
makePinContextMenu(true, true);
break;
case VfsItemAvailability::AllDehydrated:
case VfsItemAvailability::OnlineOnly:
makePinContextMenu(true, false);
break;
}
}
}

View file

@ -105,7 +105,7 @@ bool VfsSuffix::statTypeVirtualFile(csync_file_stat_t *stat, void *)
return false;
}
Optional<VfsItemAvailability> VfsSuffix::availability(const QString &folderPath)
Vfs::AvailabilityResult VfsSuffix::availability(const QString &folderPath)
{
const auto suffix = fileSuffix();
QString pinPath = folderPath;

View file

@ -51,7 +51,7 @@ public:
{ return setPinStateInDb(folderPath, state); }
Optional<PinState> pinState(const QString &folderPath) override
{ return pinStateInDb(folderPath); }
Optional<VfsItemAvailability> availability(const QString &folderPath) override;
AvailabilityResult availability(const QString &folderPath) override;
public slots:
void fileStatusChanged(const QString &, SyncFileStatus) override {}