[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-core-devel
Subject: Re: [RFC] Use QFileSystemWatcher as another method for KDirWatch?
From: Christian Ehrlicher <Ch.Ehrlicher () gmx ! de>
Date: 2007-12-06 18:29:37
Message-ID: 47583F91.40102 () gmx ! de
[Download RAW message or body]
[Attachment #2 (multipart/mixed)]
Here an updated patch. It now compiles cleanly when
HAVE_QFILESYSTEMWATCHER is not set.
Any objections against committing this patch?
Christian
["kdirwatch_qfilesystemwatcher.patch" (text/x-diff)]
Index: CMakeLists.txt
===================================================================
--- CMakeLists.txt (revision 745221)
+++ CMakeLists.txt (working copy)
@@ -31,6 +31,11 @@
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 --> enable it for all in 4.1?
+ OPTION(USE_QFILESYSTEMWATCHER "Use QFileSystemWatcher instead polling for KDirWatch" ON)
+ macro_bool_to_01(USE_QFILESYSTEMWATCHER HAVE_QFILESYSTEMWATCHER)
+endif(WIN32)
configure_file(kio/config-kdirwatch.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/kio/config-kdirwatch.h )
Index: kio/config-kdirwatch.h.cmake
===================================================================
--- kio/config-kdirwatch.h.cmake (revision 745221)
+++ kio/config-kdirwatch.h.cmake (working copy)
@@ -3,3 +3,5 @@
#cmakedefine HAVE_INOTIFY 1
#cmakedefine HAVE_SYS_INOTIFY_H 1
+
+#cmakedefine HAVE_QFILESYSTEMWATCHER 1
Index: kio/kdirwatch.cpp
===================================================================
--- kio/kdirwatch.cpp (revision 745221)
+++ kio/kdirwatch.cpp (working copy)
@@ -50,8 +50,10 @@
#include <QtCore/QDir>
#include <QtCore/QFile>
#include <QtCore/QSocketNotifier>
-#include <QtCore/QMutableStringListIterator>
#include <QtCore/QTimer>
+#ifdef HAVE_QFILESYSTEMWATCHER
+#include <QtCore/QFileSystemWatcher>
+#endif
#include <kapplication.h>
#include <kdebug.h>
@@ -122,16 +124,22 @@
m_nfsPollInterval = config.readEntry("NFSPollInterval", 5000);
m_PollInterval = config.readEntry("PollInterval", 500);
- QString method = config.readEntry("PreferredMethod", "Fam");
+ QString method = config.readEntry("PreferredMethod", "Fam");
if (method == "Fam")
{
m_preferredMethod = Fam;
}else if (method == "Stat")
{
m_preferredMethod = Stat;
+ }else if (method == "QFSWatch") {
+ m_preferredMethod = QFSWatch;
}else
{
+#ifdef Q_OS_WIN
+ m_preferredMethod = QFSWatch;
+#else
m_preferredMethod = INotify;
+#endif
}
@@ -192,7 +200,12 @@
this, SLOT( inotifyEventReceived() ) );
}
#endif
-
+#ifdef HAVE_QFILESYSTEMWATCHER
+ availableMethods << "QFileSystemWatcher";
+ fsWatcher = new QFileSystemWatcher();
+ connect(fsWatcher, SIGNAL(directoryChanged(QString)), this, SLOT(fswEventReceived(QString)));
+ connect(fsWatcher, SIGNAL(fileChanged(QString)), this, SLOT(fswEventReceived(QString)));
+#endif
kDebug(7001) << "Available methods: " << availableMethods;
}
@@ -213,6 +226,9 @@
if ( supports_inotify )
::close( m_inotify_fd );
#endif
+#ifdef HAVE_QFILESYSTEMWATCHER
+ delete fsWatcher;
+#endif
}
void KDirWatchPrivate::inotifyEventReceived()
@@ -353,7 +369,7 @@
{
if (instance == 0)
return;
-
+
foreach(Client* client, m_clients) {
if (client->instance == instance) {
client->count++;
@@ -529,7 +545,22 @@
return false;
}
#endif
+#ifdef HAVE_QFILESYSTEMWATCHER
+bool KDirWatchPrivate::useQFSWatch(Entry* e)
+{
+ e->m_mode = QFSWatchMode;
+ e->dirty = false;
+ if ( e->m_status == NonExistent ) {
+ addEntry( 0, QDir::cleanPath( e->path + "/.." ), e, true );
+ return true;
+ }
+
+ fsWatcher->addPath( e->path );
+ return true;
+}
+#endif
+
bool KDirWatchPrivate::useStat(Entry* e)
{
KMountPoint::Ptr mp = KMountPoint::currentMountPoints().findByPath(e->path);
@@ -668,7 +699,7 @@
} else if (watchModes & KDirWatch::WatchFiles) {
filters |= QDir::Files;
}
-
+
QDir basedir (e->path);
QFileInfoList contents = basedir.entryInfoList(filters);
for (QFileInfoList::iterator iter = contents.begin();
@@ -680,11 +711,11 @@
isDir ? watchModes : KDirWatch::WatchDirOnly);
}
}
-
+
// Now I've put inotify check before famd one, otherwise famd will be used
// also when inotify is available. Since inotify works
// better than famd, it is preferred to the last one
-
+
//First try to use the preferred method, if that fails use the usual order:
//inotify,fam,stat
bool entryAdded = false;
@@ -698,6 +729,11 @@
#if defined(HAVE_SYS_INOTIFY_H)
entryAdded = useINotify(e);
#endif
+ }else if (m_preferredMethod == QFSWatch)
+ {
+#ifdef HAVE_QFILESYSTEMWATCHER
+ entryAdded = useQFSWatch(e);
+#endif
}else if (m_preferredMethod == Stat)
{
entryAdded = useStat(e);
@@ -708,18 +744,22 @@
#if defined(HAVE_SYS_INOTIFY_H)
if (useINotify(e)) return;
#endif
-
+
#if defined(HAVE_FAM)
if (useFAM(e)) return;
#endif
-
+
+#if defined(HAVE_QFILESYSTEMWATCHER)
+ if (useQFSWatch(e)) return;
+#endif
+
useStat(e);
}
}
void KDirWatchPrivate::removeEntry( KDirWatch* instance,
- const QString& _path, Entry* sub_entry )
+ const QString& _path, Entry* sub_entry )
{
kDebug(7001) << "KDirWatchPrivate::removeEntry for" << _path
<< "sub_entry:" << sub_entry;
@@ -778,6 +818,11 @@
}
#endif
+#ifdef HAVE_QFILESYSTEMWATCHER
+ if (e->m_mode == QFSWatchMode) {
+ fsWatcher->removePath(e->path);
+ }
+#endif
if (e->m_mode == StatMode) {
statEntries--;
if ( statEntries == 0 ) {
@@ -961,6 +1006,14 @@
}
#endif
+#if defined( USE_QFILSYSTEMWATCHER )
+ if (e->m_mode == QFSWatchMode ) {
+ // we know nothing has changed, no need to stat
+ if(!e->dirty) return NoChange;
+ e->dirty = false;
+ }
+#endif
+
if (e->m_mode == StatMode) {
// only scan if timeout on entry timer happens;
// e.g. when using 500msec global timer, a entry
@@ -1012,7 +1065,7 @@
* and stored pending events. When watching is stopped, the event is
* added to the pending events.
*/
-void KDirWatchPrivate::emitEvent(Entry* e, int event, const QString &fileName)
+void KDirWatchPrivate::emitEvent(const Entry* e, int event, const QString &fileName)
{
QString path (e->path);
if (!fileName.isEmpty()) {
@@ -1347,6 +1400,7 @@
<< ((e->m_mode == FAMMode) ? "FAM" :
(e->m_mode == INotifyMode) ? "INotify" :
(e->m_mode == DNotifyMode) ? "DNotify" :
+ (e->m_mode == QFSWatchMode) ? "QFSWatch" :
(e->m_mode == StatMode) ? "Stat" : "Unknown Method")
<< ")";
@@ -1372,7 +1426,58 @@
}
}
+#ifdef HAVE_QFILESYSTEMWATCHER
+// Slot for QFileSystemWatcher
+void KDirWatchPrivate::fswEventReceived(const QString &path)
+{
+ EntryMap::Iterator it;
+ it = m_mapEntries.find(path);
+ if(it != m_mapEntries.end()) {
+ Entry* e = &(*it);
+ e->dirty = true;
+ int ev = scanEntry(e);
+ if (ev != NoChange)
+ emitEvent(e, ev);
+ if(ev == Deleted) {
+ if (e->isDir)
+ addEntry(0, QDir::cleanPath(e->path + "/.."), e, true);
+ else
+ addEntry(0, QFileInfo(e->path).absolutePath(), e, true);
+ } else
+ if (ev == Changed && e->isDir && e->m_entries.count()) {
+ Entry* sub_entry = 0;
+ Q_FOREACH(sub_entry, e->m_entries) {
+ if(e->isDir) {
+ if (QFileInfo(sub_entry->path).isDir())
+ break;
+ } else {
+ if (QFileInfo(sub_entry->path).isFile())
+ break;
+ }
+ }
+ if (sub_entry) {
+ removeEntry(0, e->path, 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);
+ }
+ }
+ }
+}
+#else
+void KDirWatchPrivate::fswEventReceived(const QString &path)
+{
+ kWarning (7001) << "QFileSystemWatcher event received but QFileSystemWatcher isn't supported";
+}
+#endif // HAVE_QFILESYSTEMWATCHER
+
//
// Class KDirWatch
//
Index: kio/kdirwatch.h
===================================================================
--- kio/kdirwatch.h (revision 745221)
+++ kio/kdirwatch.h (working copy)
@@ -18,10 +18,9 @@
#ifndef _KDIRWATCH_H
#define _KDIRWATCH_H
-#include <QtCore/QTimer>
-#include <QtCore/QDate>
-#include <QtCore/QMap>
-#include <QtCore/QSocketNotifier>
+#include <QtCore/QDateTime>
+#include <QtCore/QObject>
+#include <QtCore/QString>
#include <kio/kio_export.h>
@@ -75,7 +74,7 @@
WatchSubDirs = 0x02 ///< Watch also all the subdirs contained by the directory
};
Q_DECLARE_FLAGS(WatchModes, WatchMode)
-
+
/**
* Constructor.
*
Index: kio/kdirwatch_p.h
===================================================================
--- kio/kdirwatch_p.h (revision 745221)
+++ kio/kdirwatch_p.h (working copy)
@@ -29,6 +29,14 @@
#include <config-kdirwatch.h>
#include "kdirwatch.h"
+#include <QtCore/QList>
+#include <QtCore/QMap>
+#include <QtCore/QObject>
+#include <QtCore/QString>
+#include <QtCore/QTimer>
+class QFileSystemWatcher;
+class QSocketNotifier;
+
#ifdef HAVE_FAM
#include <limits.h>
#include <fam.h>
@@ -63,11 +71,11 @@
public:
enum entryStatus { Normal = 0, NonExistent };
- enum entryMode { UnknownMode = 0, StatMode, DNotifyMode, INotifyMode, FAMMode };
+ enum entryMode { UnknownMode = 0, StatMode, DNotifyMode, INotifyMode, FAMMode, QFSWatchMode };
enum { NoChange=0, Changed=1, Created=2, Deleted=4 };
- enum WatchMethod { Stat, Fam, INotify };
+ enum WatchMethod { Stat, Fam, INotify, QFSWatch };
struct Client {
KDirWatch* instance;
@@ -134,7 +142,7 @@
Entry* entry(const QString&);
int scanEntry(Entry* e);
- void emitEvent(Entry* e, int event, const QString &fileName = QString());
+ void emitEvent(const Entry* e, int event, const QString &fileName = QString());
// Memory management - delete when last KDirWatch gets deleted
void ref() { m_ref++; }
@@ -147,6 +155,7 @@
void famEventReceived(); // for FAM
void inotifyEventReceived(); // for inotify
void slotRemoveDelayed();
+ void fswEventReceived(const QString &path); // for QFileSystemWatcher
public:
QTimer timer;
@@ -181,6 +190,10 @@
bool useINotify(Entry*);
#endif
+#ifdef HAVE_QFILESYSTEMWATCHER
+ QFileSystemWatcher *fsWatcher;
+ bool useQFSWatch(Entry* e);
+#endif
bool _isStopped;
};
["signature.asc" (application/pgp-signature)]
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic