[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    branches/KDE/4.2/kdelibs/kio/kio
From:       David Faure <faure () kde ! org>
Date:       2009-04-21 21:56:33
Message-ID: 1240350993.927639.1270.nullmailer () svn ! kde ! org
[Download RAW message or body]

SVN commit 957379 by dfaure:

Backport r907250 by sstjames:
"Make proper use of inotify's implicit "WatchFiles" ability.  Immediate effect: \
Dolphin etc should now report changes to file attributes, rather than just creations \
and deletions, when KDirWatch uses inotify as its backend.  Secondary effect: \
Assuming no bugs, we should consume at most the same number of inotify watches as \
                before (and often much less)."
CCBUG: 154676

As a third effect, it fixes kdirlistertest being stuck in \
KDirListerTest::testRenameAndOverwrite() because kdirwatch wasn't informing \
kdirlister of the newly recreated file.


 M  +63 -10    kdirwatch.cpp  
 M  +9 -3      kdirwatch_p.h  


--- branches/KDE/4.2/kdelibs/kio/kio/kdirwatch.cpp #957378:957379
@@ -339,7 +339,54 @@
               }
             }
           }
+          if (event->mask & (IN_DELETE|IN_MOVED_FROM)) {
+            if ((e->isDir) && (!e->m_clients.empty())) {
+              Client* client = 0;
+              // A file in this directory has been removed.  It wasn't an explicitly
+              // watched file as it would have its own watch descriptor, so
+              // no addEntry/ removeEntry bookkeeping should be required.  Emit
+              // the event immediately if any clients are interested.
+              KDE_struct_stat stat_buf;
+              QByteArray tpath = QFile::encodeName(e->path + QLatin1Char('/') + \
path); +              // Unlike clientsForFileOrDir, the stat can fail here (item \
deleted), +              // so in that case we'll just take both kinds of clients and \
emit Deleted. +              KDirWatch::WatchModes flag = KDirWatch::WatchSubDirs | \
KDirWatch::WatchFiles; +              if (KDE_stat(tpath, &stat_buf) == 0) {
+                bool isDir = S_ISDIR(stat_buf.st_mode);
+                flag = isDir ? KDirWatch::WatchSubDirs : KDirWatch::WatchFiles;
+              }
+              int counter = 0;
+              Q_FOREACH(client, e->m_clients) {
+                  if (client->m_watchModes & flag) {
+                        counter++;
+                  }
+              }
+              if (counter != 0) {
+                  emitEvent (e, Deleted, e->path+'/'+path);
+              }
+            }
+          }
+          if (event->mask & (IN_MODIFY|IN_ATTRIB)) {
+            if ((e->isDir) && (!e->m_clients.empty())) {
+              // A file in this directory has been changed.  No
+              // addEntry/ removeEntry bookkeeping should be required.
+              // Add the path to the list of pending file changes if
+              // there are any interested clients.
+              //KDE_struct_stat stat_buf;
+              //QByteArray tpath = QFile::encodeName(e->path+'/'+path);
+              //KDE_stat(tpath, &stat_buf);
+              //bool isDir = S_ISDIR(stat_buf.st_mode);
 
+              // The API doc is somewhat vague as to whether we should emit
+              // dirty() for implicitly watched files when WatchFiles has
+              // not been specified - we'll assume they are always interested,
+              // regardless.
+              // Don't worry about duplicates for the time
+              // being; this is handled in slotRescan.
+              e->m_pendingFileChanges.append(e->path+'/'+path);
+            }
+          }
+
           if (!rescan_timer.isActive())
             rescan_timer.start(m_PollInterval); // singleshot
 
@@ -533,17 +580,9 @@
     return true;
   }
 
-  int mask = IN_DELETE|IN_DELETE_SELF|IN_CREATE|IN_MOVE|IN_MOVE_SELF|IN_DONT_FOLLOW;
-  if(!e->isDir)
-    mask |= IN_MODIFY|IN_ATTRIB;
-  else
-    mask |= IN_ONLYDIR;
+  // May as well register for almost everything - it's free!
+  int mask = IN_DELETE|IN_DELETE_SELF|IN_CREATE|IN_MOVE|IN_MOVE_SELF|IN_DONT_FOLLOW|IN_MOVED_FROM|IN_MODIFY|IN_ATTRIB;
  
-  // if dependant is a file watch, we check for MODIFY & ATTRIB too
-  foreach(Entry *dep, e->m_entries) {
-    if (!dep->isDir) { mask |= IN_MODIFY|IN_ATTRIB; break; }
-  }
-
   if ( ( e->wd = inotify_add_watch( m_inotify_fd,
                                     QFile::encodeName( e->path ), mask) ) > 0)
   {
@@ -1236,6 +1275,20 @@
         useStat( &(*it) );
       }
     }
+
+    if ((*it).isDir)
+    {
+      // Report and clear the the list of files that have changed in this directory.
+      // Remove duplicates by changing to set and back again:
+      // we don't really care about preserving the order of the
+      // original changes.
+      QList<QString> pendingFileChanges = \
(*it).m_pendingFileChanges.toSet().toList(); +      Q_FOREACH(QString \
changedFilename, pendingFileChanges ) +      {
+        emitEvent(&(*it), Changed, changedFilename);
+      }
+      (*it).m_pendingFileChanges.clear();
+    }
 #endif
 
     if ( ev != NoChange )
--- branches/KDE/4.2/kdelibs/kio/kio/kdirwatch_p.h #957378:957379
@@ -72,11 +72,11 @@
  * the maximum number of object handles is MAXIMUM_WAIT_OBJECTS (64) per thread.
  *
  * From http://msdn.microsoft.com/en-us/library/ms687025(VS.85).aspx
- * "To wait on more than MAXIMUM_WAIT_OBJECTS handles, create a thread to wait 
- *  on MAXIMUM_WAIT_OBJECTS handles, then wait on that thread plus the other \
handles.  + * "To wait on more than MAXIMUM_WAIT_OBJECTS handles, create a thread to \
wait + *  on MAXIMUM_WAIT_OBJECTS handles, then wait on that thread plus the other \
                handles.
  *  Use this technique to break the handles into groups of MAXIMUM_WAIT_OBJECTS."
  *
- * QFileSystemWatcher is implemented as thread, so KFileSystemWatcher 
+ * QFileSystemWatcher is implemented as thread, so KFileSystemWatcher
  * allocates more QFileSystemWatcher instances on demand (and deallocates them \
                later).
  */
 class KFileSystemWatcher : public QObject
@@ -161,6 +161,12 @@
 
 #ifdef HAVE_SYS_INOTIFY_H
     int wd;
+    // Creation and Deletion of files happens infrequently, so
+    // can safely be reported as they occur.  File changes i.e. those that emity \
"dirty()" can +    // happen many times per second, though, so maintain a list of \
files in this directory +    // that can be emitted and flushed at the next \
slotRescan(...). +    // This will be unused if the Entry is not a directory.
+    QList<QString> m_pendingFileChanges;
 #endif
   };
 


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic