[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