FolderWatcher: Become unreliable if test notification fails #7241
authorChristian Kamm <mail@ckamm.de>
Thu, 13 Jun 2019 07:59:01 +0000 (09:59 +0200)
committerCamila (Rebase PR Action) <hello@camila.codes>
Tue, 24 Nov 2020 16:56:49 +0000 (16:56 +0000)
Necessary for some filesystems on windows that don't have full file
watching capabilities.

src/gui/folder.cpp
src/gui/folderwatcher.cpp
src/gui/folderwatcher.h
src/gui/folderwatcher_linux.cpp

index aad3c0b6fc238e7d6046a94c3561d2b494e0359c..d6f84937e8f987419e7fc7b675c47974be4d31c3 100644 (file)
@@ -1040,6 +1040,7 @@ void Folder::registerFolderWatcher()
     connect(_folderWatcher.data(), &FolderWatcher::becameUnreliable,
         this, &Folder::slotWatcherUnreliable);
     _folderWatcher->init(path());
+    _folderWatcher->startNotificatonTest(path() + QLatin1String(".owncloudsync.log"));
 }
 
 void Folder::slotAboutToRemoveAllFiles(SyncFileItem::Direction dir, bool *cancel)
index 68aa57e9c42d588bf1dca33a4eaf1ddd5686554f..6151b1116edb1d89416ab20927e2f00aefbdf7f6 100644 (file)
@@ -33,6 +33,7 @@
 #endif
 
 #include "folder.h"
+#include "filesystem.h"
 
 namespace OCC {
 
@@ -86,6 +87,26 @@ void FolderWatcher::appendSubPaths(QDir dir, QStringList& subPaths) {
     }
 }
 
+void FolderWatcher::startNotificatonTest(const QString &path)
+{
+    Q_ASSERT(_testNotificationPath.isEmpty());
+    _testNotificationPath = path;
+
+    if (QFile::exists(path)) {
+        auto mtime = FileSystem::getModTime(path);
+        FileSystem::setModTime(path, mtime + 1);
+    } else {
+        QFile f(path);
+        f.open(QIODevice::WriteOnly | QIODevice::Append);
+    }
+
+    QTimer::singleShot(5000, this, [&]() {
+        if (!_testNotificationPath.isEmpty())
+            emit becameUnreliable(tr("The watcher did not receive a test notification."));
+        _testNotificationPath.clear();
+    });
+}
+
 int FolderWatcher::testLinuxWatchCount() const
 {
 #ifdef Q_OS_LINUX
@@ -127,6 +148,10 @@ void FolderWatcher::changeDetected(const QStringList &paths)
     // ------- handle ignores:
     for (int i = 0; i < paths.size(); ++i) {
         QString path = paths[i];
+        if (!_testNotificationPath.isEmpty()
+            && Utility::fileNamesEqual(path, _testNotificationPath)) {
+            _testNotificationPath.clear();
+        }
         if (pathIsIgnored(path)) {
             continue;
         }
index 0a30ef4827cd9c1650cc67bb3e1509e427530511..ef1a7c39478ba1acb0eedbc7479b34c1ddfb766e 100644 (file)
@@ -72,6 +72,14 @@ public:
      */
     bool isReliable() const;
 
+    /**
+     * Triggers a change in the path and verifies a notification arrives.
+     *
+     * If no notification is seen, the folderwatcher marks itself as unreliable.
+     * The path must be ignored by the watcher.
+     */
+    void startNotificatonTest(const QString &path);
+
     /// For testing linux behavior only
     int testLinuxWatchCount() const;
 
@@ -113,6 +121,9 @@ private:
 
     void appendSubPaths(QDir dir, QStringList& subPaths);
 
+    /** Path of the expected test notification */
+    QString _testNotificationPath;
+
     friend class FolderWatcherPrivate;
 };
 }
index 2feda4e5eaf3fdf47cda15d7605d25d733c8b75d..d8316c81d6fc98bdc194640a24723a5cf8cef125 100644 (file)
@@ -169,9 +169,10 @@ void FolderWatcherPrivate::slotReceivedNotification(int fd)
         if (event->len == 0 || event->wd <= -1)
             continue;
         QByteArray fileName(event->name);
+        // Filter out journal changes - redundant with filtering in
+        // FolderWatcher::pathIsIgnored.
         if (fileName.startsWith("._sync_")
             || fileName.startsWith(".csync_journal.db")
-            || fileName.startsWith(".owncloudsync.log")
             || fileName.startsWith(".sync_")) {
             continue;
         }