[kde-freebsd] QFilesSystemWatcher instead of polling/FAM

Tijl Coosemans tijl at coosemans.org
Mon Sep 20 23:35:02 CEST 2010


On Monday 20 September 2010 19:25:56 Max Brazhnikov wrote:
> On Sun, 19 Sep 2010 23:03:32 +0200, Tijl Coosemans wrote:
>> On Sunday 19 September 2010 20:10:48 Max Brazhnikov wrote:
>>> We can commit the patches to ports and wait until they will be
>>> merged upstream.
>>
>> That's ok for me. I'll be here to help if more problems do turn up.
>
> Should we use you latest patches you've sent to the list, or you have
> updated ones?

The latest patches I sent to the list. Someone ported them to KDE 4.5.
In any case, I've attached the patches I've been using.
-------------- next part --------------
--- kdecore/CMakeLists.txt.orig	2010-06-24 14:08:17.000000000 +0200
+++ kdecore/CMakeLists.txt	2010-06-24 14:08:42.000000000 +0200
@@ -15,11 +15,9 @@
 
 check_include_files(sys/inotify.h SYS_INOTIFY_H_FOUND)
 macro_bool_to_01(SYS_INOTIFY_H_FOUND HAVE_SYS_INOTIFY_H)
-if(WIN32)
- # currently for win32 only, since it doesn't support watching files that don't exist yet
- option(USE_QFILESYSTEMWATCHER "Use QFileSystemWatcher instead polling for KDirWatch" ON)
- macro_bool_to_01(USE_QFILESYSTEMWATCHER HAVE_QFILESYSTEMWATCHER)
-endif(WIN32)
+
+option(USE_QFILESYSTEMWATCHER "Use QFileSystemWatcher instead polling for KDirWatch" ON)
+macro_bool_to_01(USE_QFILESYSTEMWATCHER HAVE_QFILESYSTEMWATCHER)
 
 # Generate io/config-kdirwatch.h
 include(io/ConfigureChecks.cmake)
--- kdecore/io/kdirwatch_p.h.orig  2010-06-24 15:21:37.000000000 +0200
+++ kdecore/io/kdirwatch_p.h   2010-06-24 15:21:58.000000000 +0200
@@ -102,7 +102,7 @@
   QHash<QString,QFileSystemWatcher*> m_paths;
 };
 #else
-typedef KFileSystemWatcher QFileSystemWatcher;
+typedef QFileSystemWatcher KFileSystemWatcher;
 #endif
 #endif
 
--- kdecore/io/kdirwatch.cpp.orig	2010-02-26 19:30:10.000000000 +0100
+++ kdecore/io/kdirwatch.cpp	2010-08-08 20:39:38.000000000 +0200
@@ -94,7 +94,7 @@ static KDirWatchPrivate::WatchMethod met
 #ifdef Q_OS_WIN
     return KDirWatchPrivate::QFSWatch;
 #elif defined(Q_OS_FREEBSD)
-    return KDirWatchPrivate::Stat;
+    return KDirWatchPrivate::QFSWatch;
 #else
     return KDirWatchPrivate::INotify;
 #endif
@@ -150,7 +150,11 @@ KDirWatchPrivate::KDirWatchPrivate()
   m_preferredMethod = methodFromString(method);
 
   // The nfs method defaults to the normal (local) method
+#if defined(Q_OS_FREEBSD)
+  m_nfsPreferredMethod = methodFromString(config.readEntry("nfsPreferredMethod", "Stat"));
+#else
   m_nfsPreferredMethod = methodFromString(config.readEntry("nfsPreferredMethod", method));
+#endif
 
   QStringList availableMethods;
 
@@ -961,7 +965,16 @@ void KDirWatchPrivate::removeEntry(KDirW
 
 #ifdef HAVE_QFILESYSTEMWATCHER
   if (e->m_mode == QFSWatchMode) {
-    fsWatcher->removePath(e->path);
+    if ( e->m_status == Normal ) {
+      fsWatcher->removePath(e->path);
+      kDebug(7001).nospace() << "Cancelled QFSWatch for " << e->path;
+    }
+    else {
+      if (e->isDir)
+        removeEntry(0, QDir::cleanPath(e->path+"/.."), e);
+      else
+        removeEntry(0, QFileInfo(e->path).absolutePath(), e);
+    }
   }
 #endif
   if (e->m_mode == StatMode) {
@@ -1595,8 +1608,7 @@ void KDirWatchPrivate::fswEventReceived(
   EntryMap::Iterator it;
   it = m_mapEntries.find(path);
   if(it != m_mapEntries.end()) {
-    Entry entry = *it;  // deep copy to not point to uninialized data (can happen inside emitEvent() )
-    Entry *e = &entry;
+    Entry *e = &(*it);
     e->dirty = true;
     int ev = scanEntry(e);
     if (ev != NoChange)
@@ -1607,28 +1619,20 @@ void KDirWatchPrivate::fswEventReceived(
       else
         addEntry(0, QFileInfo(e->path).absolutePath(), e, true);
     } else
+    if(ev == Created) {
+      if(!useQFSWatch(e))
+#ifdef HAVE_SYS_INOTIFY_H
+        if(!useINotify(e))
+#endif
+          useStat(e);
+    } else
     if (ev == Changed && e->isDir && e->m_entries.count()) {
       Entry* sub_entry = 0;
       Q_FOREACH(sub_entry, e->m_entries) {
-        if(e->isDir) { // ####### !?!? Already checked above
-          if (QFileInfo(sub_entry->path).isDir()) // ##### !? no comparison between sub_entry->path and path?
-            break;
-        } else {
-          if (QFileInfo(sub_entry->path).isFile())
-            break;
-        }
+        if (QFileInfo(sub_entry->path).exists())
+          break;
       }
       if (sub_entry) {
-        removeEntry(0, e, sub_entry);
-        //KDE_struct_stat stat_buf;
-        //QByteArray tpath = QFile::encodeName(path);
-        //KDE_stat(tpath, &stat_buf);
-
-        if(!useQFSWatch(sub_entry))
-#ifdef HAVE_SYS_INOTIFY_H
-          if(!useINotify(sub_entry))
-#endif
-            useStat(sub_entry);
         fswEventReceived(sub_entry->path);
       }
     }
-------------- next part --------------
diff --git src/corelib/io/qfilesystemwatcher_kqueue.cpp src/corelib/io/qfilesystemwatcher_kqueue.cpp
index 99c165e..ce79cf7 100644
--- src/corelib/io/qfilesystemwatcher_kqueue.cpp
+++ src/corelib/io/qfilesystemwatcher_kqueue.cpp
@@ -133,6 +133,14 @@ QStringList QKqueueFileSystemWatcherEngine::addPaths(const QStringList &paths,
             perror("QKqueueFileSystemWatcherEngine::addPaths: open");
             continue;
         }
+        if (fd >= FD_SETSIZE / 2 && fd < FD_SETSIZE) {
+            int fddup = fcntl(fd, F_DUPFD, FD_SETSIZE);
+            if (fddup != -1) {
+                ::close(fd);
+                fd = fddup;
+            }
+        }
+        fcntl(fd, F_SETFD, FD_CLOEXEC);
 
         QT_STATBUF st;
         if (QT_FSTAT(fd, &st) == -1) {
@@ -157,7 +165,7 @@ QStringList QKqueueFileSystemWatcherEngine::addPaths(const QStringList &paths,
         EV_SET(&kev,
                fd,
                EVFILT_VNODE,
-               EV_ADD | EV_ENABLE | EV_ONESHOT,
+               EV_ADD | EV_ENABLE | EV_CLEAR,
                NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND | NOTE_ATTRIB | NOTE_RENAME | NOTE_REVOKE,
                0,
                0);
@@ -180,6 +188,8 @@ QStringList QKqueueFileSystemWatcherEngine::addPaths(const QStringList &paths,
         idToPath.insert(id, path);
     }
 
+    locker.unlock();
+
     if (!isRunning())
         start();
     else
@@ -203,19 +213,7 @@ QStringList QKqueueFileSystemWatcherEngine::removePaths(const QStringList &paths
         if (x.isEmpty() || x != path)
             continue;
 
-        int fd = id < 0 ? -id : id;
-        struct kevent kev;
-        EV_SET(&kev,
-               fd,
-               EVFILT_VNODE,
-               EV_DELETE,
-               NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND | NOTE_ATTRIB | NOTE_RENAME | NOTE_REVOKE,
-               0,
-               0);
-        if (kevent(kqfd, &kev, 1, 0, 0, 0) == -1) {
-            perror("QKqueueFileSystemWatcherEngine::removeWatch: kevent");
-        }
-        ::close(fd);
+        ::close(id < 0 ? -id : id);
 
         it.remove();
         if (id < 0)
@@ -225,11 +223,11 @@ QStringList QKqueueFileSystemWatcherEngine::removePaths(const QStringList &paths
     }
 
     if (pathToID.isEmpty()) {
+        locker.unlock();
         stop();
-        locker.unlock();
         wait();
-        locker.relock();
     } else {
+        locker.unlock();
         write(kqpipe[1], "@", 1);
     }
 
@@ -243,19 +241,18 @@ void QKqueueFileSystemWatcherEngine::stop()
 
 void QKqueueFileSystemWatcherEngine::run()
 {
-    static const struct timespec ZeroTimeout = { 0, 0 };
-
     forever {
         struct kevent kev;
         DEBUG() << "QKqueueFileSystemWatcherEngine: waiting for kevents...";
         int r = kevent(kqfd, 0, 0, &kev, 1, 0);
         if (r < 0) {
+            if(errno == EINTR) {
+                DEBUG() << "QKqueueFileSystemWatcherEngine: kevent call was interrupted, restarting...";
+                continue;
+            }
             perror("QKqueueFileSystemWatcherEngine: error during kevent wait");
             return;
-        }
-
-        QMutexLocker locker(&mutex);
-        do {
+        } else {
             int fd = kev.ident;
 
             DEBUG() << "QKqueueFileSystemWatcherEngine: processing kevent" << kev.ident << kev.filter;
@@ -287,6 +284,8 @@ void QKqueueFileSystemWatcherEngine::run()
                     break;
                 }
             } else {
+                QMutexLocker locker(&mutex);
+
                 int id = fd;
                 QString path = idToPath.value(id);
                 if (path.isEmpty()) {
@@ -315,30 +314,15 @@ void QKqueueFileSystemWatcherEngine::run()
                     else
                         emit fileChanged(path, true);
                 } else {
-                    DEBUG() << path << "changed, re-enabling watch";
+                    DEBUG() << path << "changed";
 
                     if (id < 0)
                         emit directoryChanged(path, false);
                     else
                         emit fileChanged(path, false);
-
-                    // renable the watch
-                    EV_SET(&kev,
-                           fd,
-                           EVFILT_VNODE,
-                           EV_ADD | EV_ENABLE | EV_ONESHOT,
-                           NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND | NOTE_ATTRIB | NOTE_RENAME | NOTE_REVOKE,
-                           0,
-                           0);
-                    if (kevent(kqfd, &kev, 1, 0, 0, 0) == -1) {
-                        perror("QKqueueFileSystemWatcherEngine::processKqueueEvents: kevent EV_ADD");
-                    }
                 }
             }
-
-            // are there any more?
-            r = kevent(kqfd, 0, 0, &kev, 1, &ZeroTimeout);
-        } while (r > 0);
+        }
     }
 }
 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 228 bytes
Desc: This is a digitally signed message part.
Url : http://mail.kde.org/pipermail/kde-freebsd/attachments/20100920/c42a8953/attachment.sig 


More information about the kde-freebsd mailing list