From eccd12923bddfeb1bad396b1f68852ca0455e6fc Mon Sep 17 00:00:00 2001 From: Daniel Molkentin Date: Tue, 4 Dec 2012 17:46:44 +0100 Subject: [PATCH] factor inotify out of folderwatcher --- src/mirall/folderwatcher.cpp | 161 +++------------------------ src/mirall/folderwatcher.h | 3 + src/mirall/folderwatcher_dummy.cpp | 50 +++++++++ src/mirall/folderwatcher_inotify.cpp | 154 +++++++++++++++++++++++++ 4 files changed, 223 insertions(+), 145 deletions(-) create mode 100644 src/mirall/folderwatcher_dummy.cpp create mode 100644 src/mirall/folderwatcher_inotify.cpp diff --git a/src/mirall/folderwatcher.cpp b/src/mirall/folderwatcher.cpp index 9ea962d50c..62ac774efa 100644 --- a/src/mirall/folderwatcher.cpp +++ b/src/mirall/folderwatcher.cpp @@ -28,20 +28,24 @@ #include #include -#ifdef USE_INOTIFY -#include -#endif - -static const uint32_t standard_event_mask = -#ifdef USE_INOTIFY - IN_CLOSE_WRITE | IN_ATTRIB | IN_MOVE | IN_CREATE | IN_DELETE | IN_DELETE_SELF | IN_MOVE_SELF | IN_UNMOUNT | IN_ONLYDIR | IN_DONT_FOLLOW; -#else - 0; -#endif /* minimum amount of seconds between two events to consider it a new event */ #define DEFAULT_EVENT_INTERVAL_MSEC 1000 +#ifdef NEW_FW_BEHAVIOR +#if defined(Q_OS_WIN) +#include "mirall/folderwatcher_win.cpp" +#elif defined(Q_OS_MAC) +#include "mirall/folderwatcher_mac.cpp" +#endif +#endif + +#ifdef USE_INOTIFY +#include "mirall/folderwatcher_inotify.cpp" +#else +#include "mirall/folderwatcher_dummy.cpp" +#endif + namespace Mirall { FolderWatcher::FolderWatcher(const QString &root, QObject *parent) @@ -53,15 +57,7 @@ FolderWatcher::FolderWatcher(const QString &root, QObject *parent) _lastMask(0), _initialSyncDone(false) { -#ifdef USE_INOTIFY - _processTimer->setSingleShot(true); - QObject::connect(_processTimer, SIGNAL(timeout()), this, SLOT(slotProcessTimerTimeout())); - - _inotify = new INotify(standard_event_mask); - slotAddFolderRecursive(root); - QObject::connect(_inotify, SIGNAL(notifyEvent(int, int, const QString &)), - this, SLOT(slotINotifyEvent(int, int, const QString &))); -#endif + setupBackend(); // do a first synchronization to get changes while // the application was not running setProcessTimer(); @@ -139,131 +135,6 @@ void FolderWatcher::setEventInterval(int seconds) _eventInterval = seconds; } -QStringList FolderWatcher::folders() const -{ -#ifdef USE_INOTIFY - return _inotify->directories(); -#else - return QStringList(); -#endif -} - -void FolderWatcher::slotAddFolderRecursive(const QString &path) -{ - int subdirs = 0; - qDebug() << "(+) Watcher:" << path; -#ifdef USE_INOTIFY - - _inotify->addPath(path); - QStringList watchedFolders(_inotify->directories()); - // qDebug() << "currently watching " << watchedFolders; - QStringListIterator subfoldersIt(FileUtils::subFoldersList(path, FileUtils::SubFolderRecursive)); - while (subfoldersIt.hasNext()) { - QString subfolder = subfoldersIt.next(); - // qDebug() << " (**) subfolder: " << subfolder; - QDir folder (subfolder); - if (folder.exists() && !watchedFolders.contains(folder.path())) { - subdirs++; - // check that it does not match the ignore list - foreach ( const QString& pattern, _ignores) { - QRegExp regexp(pattern); - regexp.setPatternSyntax(QRegExp::Wildcard); - if ( regexp.exactMatch(folder.path()) ) { - qDebug() << "* Not adding" << folder.path(); - continue; - } - - } - _inotify->addPath(folder.path()); - } - else - qDebug() << " `-> discarded:" << folder.path(); - } - if (subdirs >0) - qDebug() << " `-> and" << subdirs << "subdirectories"; -#else - qDebug() << "** Watcher is not compiled in!"; -#endif -} - -void FolderWatcher::slotINotifyEvent(int mask, int cookie, const QString &path) -{ - int lastMask = _lastMask; - QString lastPath = _lastPath; - - _lastMask = mask; - _lastPath = path; - - if( ! eventsEnabled() ) return; -#ifdef USE_INOTIFY - qDebug() << "** Inotify Event " << mask << " on " << path; - // cancel close write events that come after create - if (lastMask == IN_CREATE && mask == IN_CLOSE_WRITE - && lastPath == path ) { - return; - } - - if (IN_IGNORED & mask) { - //qDebug() << "IGNORE event"; - return; - } - - if (IN_Q_OVERFLOW & mask) { - //qDebug() << "OVERFLOW"; - } - - if (mask & IN_CREATE) { - //qDebug() << cookie << " CREATE: " << path; - if (QFileInfo(path).isDir()) { - //setEventsEnabled(false); - slotAddFolderRecursive(path); - //setEventsEnabled(true); - } - } - else if (mask & IN_DELETE) { - //qDebug() << cookie << " DELETE: " << path; - if ( QFileInfo(path).isDir() && _inotify->directories().contains(path) ) { - qDebug() << "(-) Watcher:" << path; - _inotify->removePath(path); - } - } - else if (mask & IN_CLOSE_WRITE) { - //qDebug() << cookie << " WRITABLE CLOSED: " << path; - } - else if (mask & IN_MOVE) { - //qDebug() << cookie << " MOVE: " << path; - } - else { - //qDebug() << cookie << " OTHER " << mask << " :" << path; - } - - foreach (const QString& pattern, _ignores) { - QRegExp regexp(pattern); - regexp.setPatternSyntax(QRegExp::Wildcard); - - if (regexp.exactMatch(path)) { - qDebug() << "* Discarded by ignore pattern: " << path; - return; - } - QFileInfo fInfo(path); - if( regexp.exactMatch(fInfo.fileName())) { - qDebug() << "* Discarded by ignore pattern:" << path; - return; - } - if( fInfo.isHidden() ) { - qDebug() << "* Discarded as is hidden!"; - return; - } - } - - if( !_pendingPathes.contains( path )) { - _pendingPathes[path] = 0; - } - _pendingPathes[path] = _pendingPathes[path]+mask; -#endif - setProcessTimer(); -} - void FolderWatcher::slotProcessTimerTimeout() { qDebug() << "* Processing of event queue for" << root(); @@ -290,5 +161,5 @@ void FolderWatcher::setProcessTimer() _processTimer->start(eventInterval()); } -} +} // namespace Mirall diff --git a/src/mirall/folderwatcher.h b/src/mirall/folderwatcher.h index 4c5e32ad9f..558fa2196a 100644 --- a/src/mirall/folderwatcher.h +++ b/src/mirall/folderwatcher.h @@ -121,6 +121,9 @@ protected slots: // called when the manually process timer triggers void slotProcessTimerTimeout(); +private: + void setupBackend(); + private: bool _eventsEnabled; int _eventInterval; diff --git a/src/mirall/folderwatcher_dummy.cpp b/src/mirall/folderwatcher_dummy.cpp new file mode 100644 index 0000000000..fd5d238486 --- /dev/null +++ b/src/mirall/folderwatcher_dummy.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (C) by Daniel Molkentin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "mirall/folderwatcher.h" + +namespace Mirall { + +void FolderWatcher::setupBackend() +{ + // blank +} + +QStringList FolderWatcher::folders() const +{ + return QStringList(); +} + +void FolderWatcher::slotAddFolderRecursive(const QString &path) +{ + Q_UNUSED(path); + qDebug() << "** Watcher is not compiled in!"; +} + +void FolderWatcher::slotINotifyEvent(int mask, int cookie, const QString &path) +{ + // TODO: refactor! + + int lastMask = _lastMask; + QString lastPath = _lastPath; + + _lastMask = mask; + _lastPath = path; + + if( ! eventsEnabled() ) return; + + setProcessTimer(); +} + +} // namespace Mirall diff --git a/src/mirall/folderwatcher_inotify.cpp b/src/mirall/folderwatcher_inotify.cpp new file mode 100644 index 0000000000..b77468500f --- /dev/null +++ b/src/mirall/folderwatcher_inotify.cpp @@ -0,0 +1,154 @@ +/* + * Copyright (C) by Duncan Mac-Vicar P. + * Copyright (C) by Daniel Molkentin + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include + +#include "mirall/folderwatcher.h" + +namespace Mirall { + +static const uint32_t standard_event_mask = + IN_CLOSE_WRITE | IN_ATTRIB | IN_MOVE | + IN_CREATE |IN_DELETE | IN_DELETE_SELF | + IN_MOVE_SELF |IN_UNMOUNT |IN_ONLYDIR | + IN_DONT_FOLLOW; + +void FolderWatcher::setupBackend() { + _processTimer->setSingleShot(true); + QObject::connect(_processTimer, SIGNAL(timeout()), this, SLOT(slotProcessTimerTimeout())); + + _inotify = new INotify(standard_event_mask); + slotAddFolderRecursive(_root); + QObject::connect(_inotify, SIGNAL(notifyEvent(int, int, const QString &)), + this, SLOT(slotINotifyEvent(int, int, const QString &))); +} + +QStringList FolderWatcher::folders() const +{ + return _inotify->directories(); +} + +void FolderWatcher::slotAddFolderRecursive(const QString &path) +{ + int subdirs = 0; + qDebug() << "(+) Watcher:" << path; + + _inotify->addPath(path); + QStringList watchedFolders(_inotify->directories()); + // qDebug() << "currently watching " << watchedFolders; + QStringListIterator subfoldersIt(FileUtils::subFoldersList(path, FileUtils::SubFolderRecursive)); + while (subfoldersIt.hasNext()) { + QString subfolder = subfoldersIt.next(); + // qDebug() << " (**) subfolder: " << subfolder; + QDir folder (subfolder); + if (folder.exists() && !watchedFolders.contains(folder.path())) { + subdirs++; + // check that it does not match the ignore list + foreach ( const QString& pattern, _ignores) { + QRegExp regexp(pattern); + regexp.setPatternSyntax(QRegExp::Wildcard); + if ( regexp.exactMatch(folder.path()) ) { + qDebug() << "* Not adding" << folder.path(); + continue; + } + + } + _inotify->addPath(folder.path()); + } + else + qDebug() << " `-> discarded:" << folder.path(); + } + if (subdirs >0) + qDebug() << " `-> and" << subdirs << "subdirectories"; +} + +void FolderWatcher::slotINotifyEvent(int mask, int cookie, const QString &path) +{ + int lastMask = _lastMask; + QString lastPath = _lastPath; + + _lastMask = mask; + _lastPath = path; + + if( ! eventsEnabled() ) return; + qDebug() << "** Inotify Event " << mask << " on " << path; + // cancel close write events that come after create + if (lastMask == IN_CREATE && mask == IN_CLOSE_WRITE + && lastPath == path ) { + return; + } + + if (IN_IGNORED & mask) { + //qDebug() << "IGNORE event"; + return; + } + + if (IN_Q_OVERFLOW & mask) { + //qDebug() << "OVERFLOW"; + } + + if (mask & IN_CREATE) { + //qDebug() << cookie << " CREATE: " << path; + if (QFileInfo(path).isDir()) { + //setEventsEnabled(false); + slotAddFolderRecursive(path); + //setEventsEnabled(true); + } + } + else if (mask & IN_DELETE) { + //qDebug() << cookie << " DELETE: " << path; + if ( QFileInfo(path).isDir() && _inotify->directories().contains(path) ) { + qDebug() << "(-) Watcher:" << path; + _inotify->removePath(path); + } + } + else if (mask & IN_CLOSE_WRITE) { + //qDebug() << cookie << " WRITABLE CLOSED: " << path; + } + else if (mask & IN_MOVE) { + //qDebug() << cookie << " MOVE: " << path; + } + else { + //qDebug() << cookie << " OTHER " << mask << " :" << path; + } + + foreach (const QString& pattern, _ignores) { + QRegExp regexp(pattern); + regexp.setPatternSyntax(QRegExp::Wildcard); + + if (regexp.exactMatch(path)) { + qDebug() << "* Discarded by ignore pattern: " << path; + return; + } + QFileInfo fInfo(path); + if( regexp.exactMatch(fInfo.fileName())) { + qDebug() << "* Discarded by ignore pattern:" << path; + return; + } + if( fInfo.isHidden() ) { + qDebug() << "* Discarded as is hidden!"; + return; + } + } + + if( !_pendingPathes.contains( path )) { + _pendingPathes[path] = 0; + } + _pendingPathes[path] = _pendingPathes[path]+mask; + setProcessTimer(); +} + +} // namespace Mirall