From 7774b8049e412560d0446870b73ff3c5da8e82bd Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Thu, 25 Apr 2019 11:10:52 +0200 Subject: [PATCH] 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. --- src/common/vfs.cpp | 7 +++-- src/common/vfs.h | 17 ++++++++-- src/gui/socketapi.cpp | 45 +++++++++++++++------------ src/libsync/vfs/suffix/vfs_suffix.cpp | 2 +- src/libsync/vfs/suffix/vfs_suffix.h | 2 +- 5 files changed, 45 insertions(+), 28 deletions(-) diff --git a/src/common/vfs.cpp b/src/common/vfs.cpp index c24c11cd6..2265d5410 100644 --- a/src/common/vfs.cpp +++ b/src/common/vfs.cpp @@ -79,13 +79,13 @@ Optional Vfs::pinStateInDb(const QString &folderPath) return _setupParams.journal->internalPinStates().effectiveForPath(folderPath.toUtf8()); } -Optional 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 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) diff --git a/src/common/vfs.h b/src/common/vfs.h index 59153024a..916c009a6 100644 --- a/src/common/vfs.h +++ b/src/common/vfs.h @@ -99,6 +99,15 @@ public: static QString modeToString(Mode mode); static Optional 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; + 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(const QString &folderPath) = 0; @@ -214,7 +225,7 @@ public: * * folderPath is relative to the sync folder. Can be "" for root folder. */ - virtual Optional 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 pinStateInDb(const QString &folderPath); // sadly for virtual files the path in the metadata table can differ from path in 'flags' - Optional 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(const QString &) override { return PinState::AlwaysLocal; } - Optional availability(const QString &) override { return VfsItemAvailability::AlwaysLocal; } + AvailabilityResult availability(const QString &) override { return VfsItemAvailability::AlwaysLocal; } public slots: void fileStatusChanged(const QString &, SyncFileStatus) override {} diff --git a/src/gui/socketapi.cpp b/src/gui/socketapi.cpp index be8f0beac..88dc7af8b 100644 --- a/src/gui/socketapi.cpp +++ b/src/gui/socketapi.cpp @@ -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; + } } } diff --git a/src/libsync/vfs/suffix/vfs_suffix.cpp b/src/libsync/vfs/suffix/vfs_suffix.cpp index 0480d02b2..5a2d829c8 100644 --- a/src/libsync/vfs/suffix/vfs_suffix.cpp +++ b/src/libsync/vfs/suffix/vfs_suffix.cpp @@ -105,7 +105,7 @@ bool VfsSuffix::statTypeVirtualFile(csync_file_stat_t *stat, void *) return false; } -Optional VfsSuffix::availability(const QString &folderPath) +Vfs::AvailabilityResult VfsSuffix::availability(const QString &folderPath) { const auto suffix = fileSuffix(); QString pinPath = folderPath; diff --git a/src/libsync/vfs/suffix/vfs_suffix.h b/src/libsync/vfs/suffix/vfs_suffix.h index 5aadf5449..89b13d526 100644 --- a/src/libsync/vfs/suffix/vfs_suffix.h +++ b/src/libsync/vfs/suffix/vfs_suffix.h @@ -51,7 +51,7 @@ public: { return setPinStateInDb(folderPath, state); } Optional pinState(const QString &folderPath) override { return pinStateInDb(folderPath); } - Optional availability(const QString &folderPath) override; + AvailabilityResult availability(const QString &folderPath) override; public slots: void fileStatusChanged(const QString &, SyncFileStatus) override {}