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

List:       kfm-devel
Subject:    Patch: KDirWatch change proposal
From:       Malte Starostik <malte () kde ! org>
Date:       2002-03-01 0:47:35
[Download RAW message or body]

Hi,

the attached patch changes a few things in KDirWatch:
* it reduces the number of signals from 6 to 3, making it easier to use if you 
need all signals (and you should connect to all of them)
* it emits the most accurate signal possible for every event. i.e. when using 
FAM, dirty() is not emitted for the parent dir if a file is created, but 
instead created() is emitted with the name of the new file as parameter. With 
polling or dnotify this isn't possible, so then dirty() is emitted for the 
parent dir just like before.
* dirty() is emitted when a file's size/attributes change when the file's 
parent directory is watched and FAM is used. This makes it possible to update 
file size changes in KDirLister in "real time" w/o rescanning the directory.

If there are no objections agains t this change, I'll also care about adapting 
all apps in CVS and adding a note to the porting doc.

Please note that Konqueror will _not_ react to all events correctly as of now, 
Michael will care for that. So, if you want to check this patch, all you can 
see to test is the debug output that appears when dirty(), created() or 
deleted() are emitted.

Filesystem events and resulting signals:

*** Watching /home/someuser (~)

touch ~/a
stat, dnotify: dirty("/home/someuser")
fam: created("/home/someuser/a")

touch ~/a
stat, dnotify: nothing emitted
fam: dirty("/home/someuser/a")

rm ~/a
stat, dnotify: dirty("/home/someuser")
fam: deleted("/home/someuser/a")

mkdir ~/somedir
stat, dnotify: dirty("/home/someuser")
fam: created("/home/someuser/somedir")

*** start to watch ~/somedir
rmdir ~/somedir
stat, dnotify: dirty("/home/someuser"), deleted("/home/someuser/somedir")
fam: deleted("/home/someuser/somedir")

mkdir ~/somedir
stat, dnotify: dirty("/home/someuser"), created("/home/someuser/somedir")
fam: created("/home/someuser/somedir")

rm -rf ~
stat, dnotify, fam: deleted("/home/someuser")

So, at least when using FAM, directory rescans can be largely eliminated.
-- 
Malte Starostik
PGP: 1024D/D2F3C787 [C138 2121 FAF3 410A 1C2A  27CD 5431 7745 D2F3 C787]

["kdirwatch.diff" (text/x-diff)]

Index: kautomount.cpp
===================================================================
RCS file: /home/kde/kdelibs/kio/kio/kautomount.cpp,v
retrieving revision 1.24
diff -u -3 -d -p -r1.24 kautomount.cpp
--- kautomount.cpp	2001/12/14 12:18:34	1.24
+++ kautomount.cpp	2002/03/01 00:31:18
@@ -59,7 +59,7 @@ void KAutoMount::slotResult( KIO::Job * 
 
     // Update of window which contains the desktop entry which is used for mount/unmount
     kdDebug(7015) << " mount finished : updating " << m_desktopFile << endl;
-    KDirWatch::self()->setFileDirty( m_desktopFile );
+    KDirWatch::self()->setDirty( m_desktopFile );
   }
   delete this;
 }
@@ -79,7 +79,7 @@ void KAutoUnmount::slotResult( KIO::Job 
   {
     // Update of window which contains the desktop entry which is used for mount/unmount
     kdDebug(7015) << "unmount finished : updating " << m_desktopFile << endl;
-    KDirWatch::self()->setFileDirty( m_desktopFile );
+    KDirWatch::self()->setDirty( m_desktopFile );
 
     // Notify about the new stuff in that dir, in case of opened windows showing it
     // You may think we removed files, but this may have also readded some
Index: kdirwatch.cpp
===================================================================
RCS file: /home/kde/kdelibs/kio/kio/kdirwatch.cpp,v
retrieving revision 1.67
diff -u -3 -d -p -r1.67 kdirwatch.cpp
--- kdirwatch.cpp	2002/02/26 09:57:57	1.67
+++ kdirwatch.cpp	2002/03/01 00:31:18
@@ -145,7 +145,7 @@ KDirWatchPrivate::KDirWatchPrivate()
  	     this, SLOT(famEventReceived()) );
   }
   else {
-    kdDebug(7001) << "Can't use FAM (fam damon not running?)" << endl;
+    kdDebug(7001) << "Can't use FAM (fam daemon not running?)" << endl;
     use_fam=false;
   }
 #endif
@@ -692,7 +692,7 @@ bool KDirWatchPrivate::restartEntryScan(
   return true;
 }
 
-// instance ==0: start scanning for all instances
+// instance ==0: stop scanning for all instances
 void KDirWatchPrivate::stopScan(KDirWatch* instance)
 {
   EntryMap::Iterator it = m_mapEntries.begin();
@@ -793,8 +793,11 @@ int KDirWatchPrivate::scanEntry(Entry* e
  * and stored pending events. When watching is stopped, the event is
  * added to the pending events.
  */
-void KDirWatchPrivate::emitEvent(Entry* e, int event)
+void KDirWatchPrivate::emitEvent(Entry* e, int event, const QString &fileName)
 {
+  QString path = e->path;
+  if (!fileName.isEmpty()) path += "/" + fileName;
+
   Client* c = e->m_clients.first();
   for(;c;c=e->m_clients.next()) {
     if (c->instance==0 || c->count==0) continue;
@@ -814,28 +817,18 @@ void KDirWatchPrivate::emitEvent(Entry* 
     if (event == NoChange) continue;
 
     if (event & Deleted) {
-      if (e->isDir)
-	c->instance->setDirDeleted(e->path);
-      else
-	c->instance->setFileDeleted(e->path);
+      c->instance->setDeleted(path);
       // emit only Deleted event...
       continue;
     }
 
     if (event & Created) {
-      if (e->isDir)
-	c->instance->setDirCreated(e->path);
-      else
-	c->instance->setFileCreated(e->path);
+      c->instance->setCreated(path);
       // possible emit Change event after creation
     }
 
-    if (event & Changed) {
-      if (e->isDir)
-	c->instance->setDirDirty(e->path);
-      else
-	c->instance->setFileDirty(e->path);      
-    }
+    if (event & Changed)
+      c->instance->setDirty(path);
   }
 }
 
@@ -966,74 +959,61 @@ void KDirWatchPrivate::checkFAMEvent(FAM
     kdDebug(7001) << "FAM event for nonExistent entry " << e->path << endl;
     return;
   }
-
-  // Was a watched file changed?
-  if ( !e->isDir ) {
-    if (fe->code == FAMDeleted) emitEvent(e, Deleted);
-    else if (fe->code == FAMChanged) emitEvent(e, Changed);
-    else if (fe->code == FAMCreated) emitEvent(e, Created);
-    return;
-  }
 
-  /* only interested in 
-   * - dir/file creation inside a watched dir
-   * - dir/file deletion inside a watched dir
-   * - deletion of a watched dir
-   */
+  if (e->isDir)
+    switch (fe->code)
+    {
+      case FAMDeleted: 
+        if (strlen(fe->filename) == 0)
+        {
+          // a watched directory was deleted
 
-  if (fe->code != FAMCreated &&
-      fe->code != FAMDeleted) return;
+          e->m_status = NonExistent;
+          FAMCancelMonitor(&fc, &(e->fr) ); // needed ?
+          kdDebug(7001) << "Cancelled FAMReq "
+                        << FAMREQUEST_GETREQNUM(&(e->fr))
+                        << " for " << e->path << endl;
+          // Scan parent for a new creation
+          addEntry(0, QDir::cleanDirPath( e->path+"/.."), e, true);
+        }
+        emitEvent(e, Deleted, QFile::decodeName(fe->filename));
+        break;
 
-  // if fe->filename is relative, a file in a watched dir was
-  // changed, deleted or created
-  if ( fe->filename[0] != '/') {
+      case FAMCreated: {
+          // check for creation of a directory we have to watch
+          Entry *sub_entry = e->m_entries.first();
+          for(;sub_entry; sub_entry = e->m_entries.next())
+            if (sub_entry->path == e->path + "/" + fe->filename) break;
+          if (sub_entry && sub_entry->isDir) {
+            QString path = e->path;
+            removeEntry(0,e->path,sub_entry); // <e> can be invalid here!!
+            sub_entry->m_status = Normal;
+            if (!useFAM(sub_entry))
+              useStat(sub_entry);
+        
+            emitEvent(sub_entry, Created);
+          }
+          else emitEvent(e, Created, QFile::decodeName(fe->filename));
+          break;
+        }
 
-    // WABA: We ignore changes to ".directory*" files because they
-    // tend to be generated as a result of 'dirty' events. Which
-    // leads to a never ending stream of cause & result.
-    if (strncmp(fe->filename, ".directory", 10) == 0) return;
-    // $HOME/.X.err grows with debug output, so don't notify change
-    if (strncmp(fe->filename, ".X.err", 6) == 0) return;
-    if (strncmp(fe->filename, ".xsession-errors", 16) == 0) return;
+      case FAMChanged:
+        // WABA: We ignore changes to ".directory*" files because they
+        // tend to be generated as a result of 'dirty' events. Which
+        // leads to a never ending stream of cause & result.
+        if (strncmp(fe->filename, ".directory", 10) == 0) return;
+        // $HOME/.X.err grows with debug output, so don't notify change
+        if (strncmp(fe->filename, ".X.err", 6) == 0) return;
+        if (strncmp(fe->filename, ".xsession-errors", 16) == 0) return;
 
-    emitEvent(e, Changed);
+        emitEvent(e, Changed, QFile::decodeName(fe->filename));
 
-    if (fe->code == FAMCreated) {
-      // check for creation of a directory we have to watch
-      Entry *sub_entry = e->m_entries.first();
-      for(;sub_entry; sub_entry = e->m_entries.next())
-	if (sub_entry->path == e->path + "/" + fe->filename) break;
-      if (sub_entry && sub_entry->isDir) {
-	// only possible for a FAMCreated event
-	QString path = e->path;
-	removeEntry(0,e->path,sub_entry); // <e> can be invalid here!!
-	sub_entry->m_status = Normal;
-	if (!useFAM(sub_entry))
-	  useStat(sub_entry);
-	
-	emitEvent(sub_entry, Created);
-      }
+      default:
+        break;
     }
+  else if (fe->code == FAMCreated)
+    emitEvent(e, Changed);
 
-    return;
-  }
-  
-  if (fe->code == FAMDeleted) {
-    // a watched directory was deleted
-
-    e->m_status = NonExistent;
-    FAMCancelMonitor(&fc, &(e->fr) ); // needed ?
-    kdDebug(7001) << "Cancelled FAMReq "
-		  << FAMREQUEST_GETREQNUM(&(e->fr))
-		  << " for " << e->path << endl;
-    // Scan parent for a new creation
-    addEntry(0, QDir::cleanDirPath( e->path+"/.."), e, true);
-    emitEvent(e, Deleted);
-    return;
-  }
-
-  // a watched directory was changed
-  emitEvent(e, Changed);
 }
 #else
 void KDirWatchPrivate::famEventReceived() {}
@@ -1216,45 +1196,28 @@ void KDirWatch::statistics()
   dwp_self->statistics();
 }
 
-
-void KDirWatch::setFileCreated( const QString & _file )
-{
-  kdDebug(7001) << name() << " emitting fileCreated " << _file << endl;
-  emit fileCreated( _file );
-}
-
-void KDirWatch::setFileDirty( const QString & _file )
-{
-  kdDebug(7001) << name() << " emitting fileDirty " << _file << endl;
-  emit fileDirty( _file );
-}
-
-void KDirWatch::setFileDeleted( const QString & _file )
-{
-  kdDebug(7001) << name() << " emitting fileDeleted " << _file << endl;
-  emit fileDeleted( _file );
-}
 
-void KDirWatch::setDirCreated( const QString & _path )
+void KDirWatch::setCreated( const QString & _file )
 {
-  kdDebug(7001) << name() << " emitting created dir " << _path << endl;
-  emit created( _path );
+  kdDebug(7001) << name() << " emitting created " << _file << endl;
+  emit created( _file );
 }
 
-void KDirWatch::setDirDirty( const QString & _path )
+void KDirWatch::setDirty( const QString & _file )
 {
-  kdDebug(7001) << name() << " emitting dirty dir " << _path << endl;
-  emit dirty( _path );
+  kdDebug(7001) << name() << " emitting dirty " << _file << endl;
+  emit dirty( _file );
 }
 
-void KDirWatch::setDirDeleted( const QString & _path )
+void KDirWatch::setDeleted( const QString & _file )
 {
-  kdDebug(7001) << name() << " emitting deleted dir " << _path << endl;
-  emit deleted( _path );
+  kdDebug(7001) << name() << " emitting deleted " << _file << endl;
+  emit deleted( _file );
 }
 
-
 #include "kdirwatch.moc"
 #include "kdirwatch_p.moc"
 
 //sven
+
+// vim: sw=2 ts=8 et
Index: kdirwatch.h
===================================================================
RCS file: /home/kde/kdelibs/kio/kio/kdirwatch.h,v
retrieving revision 1.30
diff -u -3 -d -p -r1.30 kdirwatch.h
--- kdirwatch.h	2002/02/22 11:02:37	1.30
+++ kdirwatch.h	2002/03/01 00:31:18
@@ -183,17 +183,11 @@ class KDirWatch : public QObject
    static void statistics();
 
    /** @ref created() */
-   void setDirCreated( const QString& );
+   void setCreated( const QString& );
    /** @ref dirty() */
-   void setDirDirty( const QString& );
+   void setDirty( const QString& );
    /** @ref deleted() */
-   void setDirDeleted( const QString& );
-   /** @ref fileCreated() */
-   void setFileCreated( const QString& );
-   /** @ref fileDirty() */
-   void setFileDirty( const QString& );
-   /** @ref fileDeleted() */
-   void setFileDeleted( const QString& );
+   void setDeleted( const QString& );
 
    /**
     * The KDirWatch instance usually globally used in an application.
@@ -205,51 +199,32 @@ class KDirWatch : public QObject
  signals:
 
    /**
-    * Emitted when a watched directory is changed, i.e. files
+    * Emitted when a watched object is changed.
+    * For a directory this signal is emitted when files
     * therein are created or deleted.
+    * For a file this signal is emitted when its size or attributes change.
     *
+    * When you watch a directory, changes in the size or attributes of
+    * contained files may or may not trigger this signal to be emitted
+    * depending on which backend is used by KDirWatch.
+    *
     * The new ctime is set
     * before the signal is emitted.
     */
    void dirty (const QString&);
 
    /**
-    * Emitted when a watched directory is created.
+    * Emitted when a file or directory is created.
     */
    void created (const QString&);
      
    /**
-    * Emitted when a watched directory is deleted.
+    * Emitted when a file or directory is deleted.
     *
-    * The directory is still watched for new creation.
+    * The object is still watched for new creation.
     */
    void deleted (const QString&);
      
-   
-   /**
-    * Emitted when KDirWatch learns that the file
-    * @p _file has changed.
-    *
-    * This happens for instance when a .desktop file 
-    * gets a new icon. One has to call 
-    * @ref setFileDirty() or watch the file for changes
-    * for this signal to be emitted.
-    *
-    * Note that KDirNotify is network transparent and
-    * broadcasts to all processes, so it sort of supersedes this.
-    */
-   void fileDirty (const QString&);
-
-   /**
-    * Emitted when a watched file is created.
-    */
-   void fileCreated (const QString&);
-
-   /**
-    * Emitted when a watched file is deleted.
-    */
-   void fileDeleted (const QString&);
-
  private:
    bool _isStopped;
    
@@ -258,3 +233,5 @@ class KDirWatch : public QObject
 };
 
 #endif
+
+// vim: sw=3 et
Index: kdirwatch_p.h
===================================================================
RCS file: /home/kde/kdelibs/kio/kio/kdirwatch_p.h,v
retrieving revision 1.4
diff -u -3 -d -p -r1.4 kdirwatch_p.h
--- kdirwatch_p.h	2002/02/26 09:57:57	1.4
+++ kdirwatch_p.h	2002/03/01 00:31:18
@@ -82,7 +82,7 @@ public:
 
   Entry* entry(const QString&);
   int scanEntry(Entry* e);
-  void emitEvent(Entry* e, int event);
+  void emitEvent(Entry* e, int event, const QString &fileName = QString::null);
 
 public slots:
   void slotRescan();


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

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