Vfs: Distinguish availability error kinds #7143
authorChristian Kamm <mail@ckamm.de>
Thu, 25 Apr 2019 09:10:52 +0000 (11:10 +0200)
committerKevin Ottens <kevin.ottens@nextcloud.com>
Tue, 15 Dec 2020 09:58:49 +0000 (10:58 +0100)
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
src/common/vfs.h
src/gui/socketapi.cpp
src/libsync/vfs/suffix/vfs_suffix.cpp
src/libsync/vfs/suffix/vfs_suffix.h

index c24c11cd6044413e0d939938f89b5f0bc2d31e2c..2265d5410ffff2d647e5c5b480a3e8dd7bf4dc63 100644 (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)
index 59153024ad944c5045a19b0f753a04e34cb018ff..916c009a6b827cda80b5079abcb4960371fc5036 100644 (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 {}
index be8f0beacc69d28f4bdf7dc71ce90b7df967b91b..88dc7af8b48f19b4e3f9e24c709a2f4f119e93ca 100644 (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;
+            }
         }
     }
 
index 0480d02b27c261751e1c2da7f00a2d588d3bfe35..5a2d829c85e7298014cc3b29e00a83cc388499fb 100644 (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;
index 5aadf54494c95a35b3dbb8eb6750c8776ba5832a..89b13d5269a118e10caa99bd20afa7ccf5dd6a40 100644 (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 {}