[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