- fix inotify/folderwatcher so that it uses full paths

- make the test pass using QSignalSpy
This commit is contained in:
Duncan Mac-Vicar P 2011-03-18 13:54:32 +01:00
parent e6a135273d
commit bd5effe78c
5 changed files with 63 additions and 64 deletions

View File

@ -8,6 +8,7 @@
#include <QDir>
#include <QMutexLocker>
#include <QStringList>
#include <QTimer>
#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);
}

View File

@ -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;
};
}

View File

@ -38,17 +38,14 @@ INotify::~INotify()
s_thread->unregisterForNotification(this);
// Remove all inotify watchs.
QMap<QString, int>::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;
}

View File

@ -12,7 +12,6 @@ http://www.gnu.org/licenses/gpl.txt .
#include <QObject>
#include <QHash>
#include <QMap>
#include <QString>
#include <QThread>
@ -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<QString, int> _wds;
QHash<QString, int> _wds;
};
}

View File

@ -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)