From bd5effe78ce76d57955bc75e0a70323ae4ab2cdb Mon Sep 17 00:00:00 2001 From: Duncan Mac-Vicar P Date: Fri, 18 Mar 2011 13:54:32 +0100 Subject: [PATCH] - fix inotify/folderwatcher so that it uses full paths - make the test pass using QSignalSpy --- src/mirall/folderwatcher.cpp | 86 ++++++++++++++++-------------------- src/mirall/folderwatcher.h | 5 ++- src/mirall/inotify.cpp | 17 ++++--- src/mirall/inotify.h | 5 +-- test/testfolderwatcher.cpp | 14 +++++- 5 files changed, 63 insertions(+), 64 deletions(-) diff --git a/src/mirall/folderwatcher.cpp b/src/mirall/folderwatcher.cpp index db51cb1f79..a6398a9a53 100644 --- a/src/mirall/folderwatcher.cpp +++ b/src/mirall/folderwatcher.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include "mirall/inotify.h" #include "mirall/folderwatcher.h" @@ -15,11 +16,6 @@ static const uint32_t standard_event_mask = IN_MODIFY | IN_ATTRIB | IN_MOVE | IN_CREATE | IN_DELETE | IN_DELETE_SELF | IN_MOVE_SELF | IN_UNMOUNT | IN_ISDIR | IN_DONT_FOLLOW; -// IN_ONESHOT -// IN_ATTRIB | IN_CLOSE_WRITE | IN_CREATE | -// IN_DELETE | IN_DELETE_SELF | IN_MOVED_FROM | -// IN_MOVED_TO | IN_DONT_FOLLOW | IN_ONLYDIR; - namespace Mirall { enum SubFolderListOption { @@ -48,26 +44,12 @@ static QStringList subFoldersList(QString folder, return dirList; } -FolderWatcher::FolderWatcher(const QString &path, QObject *parent) - : QObject(parent) +FolderWatcher::FolderWatcher(const QString &root, QObject *parent) + : QObject(parent), + _root(root) { _inotify = new INotify(standard_event_mask); - _inotify->addPath(path); - - // watch the path and all subdirectories - { - QMutexLocker locker(&_mutex); - - QStringList subfolders(subFoldersList(path, SubFolderRecursive)); - if (! subfolders.empty() ) { - qDebug() << "adding watchers for " << subfolders; - - QStringListIterator subfoldersIt(subfolders); - while (subfoldersIt.hasNext()) { - _inotify->addPath(subfoldersIt.next()); - } - } - } + slotAddFolderRecursive(root); QObject::connect(_inotify, SIGNAL(notifyEvent(int, const QString &)), SLOT(slotDirectoryChanged(int, const QString &))); } @@ -82,44 +64,50 @@ QStringList FolderWatcher::folders() const return _inotify->directories(); } -void FolderWatcher::slotDirectoryChanged(int mask, const QString &path) +void FolderWatcher::slotAddFolderRecursive(const QString &path) { - QMutexLocker locker(&_mutex); - - qDebug() << mask << " : changed: " << path; - - qDebug() << "updating subdirectories"; - + qDebug() << "Recursive adding " << path; QStringList watchedFolders(_inotify->directories()); - QStringListIterator watchedFoldersIt(watchedFolders); - - while (watchedFoldersIt.hasNext()) { - QDir folder (watchedFoldersIt.next()); - if (!folder.exists()){ - qDebug() << "Removing " << folder.path(); - _inotify->removePath(folder.path()); - } - } - - //qDebug() << "Removing " << folder.path(); - + qDebug() << "currently watching " << watchedFolders; QStringListIterator subfoldersIt(subFoldersList(path, SubFolderRecursive)); while (subfoldersIt.hasNext()) { QDir folder (subfoldersIt.next()); if (folder.exists() && !watchedFolders.contains(folder.path())) { - qDebug() << "Adding " << folder.path(); + qDebug() << "`-> adding " << folder.path(); _inotify->addPath(folder.path()); } else - qDebug() << "discarding " << folder.path(); - - - // Look if some of the subdirectories disappeared - - + qDebug() << "`-> discarding " << folder.path(); } + qDebug() << "`-> adding " << path; + _inotify->addPath(path); +} +void FolderWatcher::slotDirectoryChanged(int mask, const QString &path) +{ + QMutexLocker locker(&_mutex); + if (mask & IN_CREATE) { + qDebug() << "CREATE: " << path; + if (QFileInfo(path).isDir()) { + slotAddFolderRecursive(path); + } + } + else if (mask & IN_DELETE) { + qDebug() << "DELETE: " << path; + if (_inotify->directories().contains(path)); + qDebug() << "`-> removing " << path; + _inotify->removePath(path); + } + else if (mask & IN_MODIFY) { + qDebug() << "MODIFIED: " << path; + } + else if (mask & IN_MOVE) { + qDebug() << "MOVE: " << path; + } + else { + qDebug() << "OTHER " << mask << " :" << path; + } emit folderChanged(path); } diff --git a/src/mirall/folderwatcher.h b/src/mirall/folderwatcher.h index 9f7e3c0e7e..fff24adf6c 100644 --- a/src/mirall/folderwatcher.h +++ b/src/mirall/folderwatcher.h @@ -15,7 +15,7 @@ class FolderWatcher : public QObject { Q_OBJECT public: - FolderWatcher(const QString &path, QObject *parent = 0L); + FolderWatcher(const QString &root, QObject *parent = 0L); ~FolderWatcher(); QStringList folders() const; @@ -24,9 +24,12 @@ signals: void folderChanged(const QString &path); protected slots: void slotDirectoryChanged(int mask, const QString &path); + void slotAddFolderRecursive(const QString &path); private: + QMutex _mutex; INotify *_inotify; + QString _root; }; } diff --git a/src/mirall/inotify.cpp b/src/mirall/inotify.cpp index 091f7ff4f1..7762950770 100644 --- a/src/mirall/inotify.cpp +++ b/src/mirall/inotify.cpp @@ -38,17 +38,14 @@ INotify::~INotify() s_thread->unregisterForNotification(this); // Remove all inotify watchs. - QMap::const_iterator it; - for (it = _wds.begin(); it != _wds.end(); ++it) { - inotify_rm_watch(s_fd, *it); - } + QString key; + foreach (key, _wds.keys()) + inotify_rm_watch(s_fd, _wds.value(key)); } void INotify::addPath(const QString &path) { // Add an inotify watch. - qDebug() << path; - path.toAscii().constData(); int wd = inotify_add_watch(s_fd, path.toAscii().constData(), _mask); @@ -88,9 +85,11 @@ INotify::INotifyThread::registerForNotification(INotify* notifier, int wd) } void -INotify::fireEvent(int mask, char* name) +INotify::fireEvent(int mask, int wd, char* name) { - emit notifyEvent(mask, QString::fromUtf8(name)); + QString path; + foreach (path, _wds.keys(wd)) + emit notifyEvent(mask, path + "/" + QString::fromUtf8(name)); } void @@ -138,7 +137,7 @@ INotify::INotifyThread::run() // with the help of watch descriptor, retrieve, corresponding INotify n = _map[event->wd]; // fire event - n->fireEvent(event->mask, event->name); + n->fireEvent(event->mask, event->wd, event->name); // increment counter i += sizeof(struct inotify_event) + event->len; } diff --git a/src/mirall/inotify.h b/src/mirall/inotify.h index 1976c8feab..f9281ec17a 100644 --- a/src/mirall/inotify.h +++ b/src/mirall/inotify.h @@ -12,7 +12,6 @@ http://www.gnu.org/licenses/gpl.txt . #include #include -#include #include #include @@ -53,13 +52,13 @@ private: }; //INotify(int wd); - void fireEvent(int mask, char *name); + void fireEvent(int mask, int wd, char *name); static int s_fd; static INotifyThread* s_thread; // the mask is shared for all paths int _mask; - QMap _wds; + QHash _wds; }; } diff --git a/test/testfolderwatcher.cpp b/test/testfolderwatcher.cpp index 8f9092ce34..52abadf286 100644 --- a/test/testfolderwatcher.cpp +++ b/test/testfolderwatcher.cpp @@ -29,9 +29,19 @@ void TestFolderWatcher::testFilesAdded() qDebug() << "Monitored: " << watcher.folders(); - QDir subdir = QDir(tmp.path() + "/sub1/sub2"); - QVERIFY(subdir.mkpath(tmp.path() + "/sub1/sub2")); + QDir subdir = QDir(tmp.path()); + QSignalSpy spy(&watcher, SIGNAL(folderChanged(const QString &))); + QVERIFY(subdir.mkpath(tmp.path() + "/sub1/sub2")); + QVERIFY(subdir.mkpath(tmp.path() + "/sub2")); + + while (spy.count() == 0) + QTest::qWait(200); + + // 2 directory changes + QCOMPARE(spy.count(), 2); + + qDebug() << "Monitored: " << watcher.folders(); } QTEST_MAIN(TestFolderWatcher)