Infrastructure for inotify. To replace QFileSystemWatcher, which, due

to a Qt bug, can't see modified files.
See http://qt.gitorious.org/qt/qt/merge_requests/2301
This commit is contained in:
Duncan Mac-Vicar P 2011-03-16 14:50:34 +01:00
parent b7a3fc7ab8
commit 5294bee2bf
6 changed files with 198 additions and 0 deletions

View file

@ -8,6 +8,7 @@ mirall/application.cpp
mirall/folder.cpp
mirall/gitfolder.cpp
mirall/folderwatcher.cpp
mirall/inotify.cpp
main.cpp)
qt4_automoc(${mirall_SRCS})

View file

@ -8,12 +8,15 @@
#include "mirall/application.h"
#include "mirall/folder.h"
#include "mirall/gitfolder.h"
#include "mirall/inotify.h"
namespace Mirall {
Application::Application(int argc, char **argv) :
QApplication(argc, argv)
{
INotify::initialize();
_folder = new GitFolder(QDir::homePath() + "/Mirall", this);
setApplicationName("Mirall");
setupActions();
@ -23,6 +26,7 @@ Application::Application(int argc, char **argv) :
Application::~Application()
{
INotify::cleanup();
}
void Application::setupActions()

View file

@ -1,4 +1,7 @@
// event masks
#include <sys/inotify.h>
#include <QFileInfo>
#include <QFileSystemWatcher>
#include <QFlags>
@ -7,8 +10,14 @@
#include <QMutexLocker>
#include <QStringList>
#include "mirall/inotify.h"
#include "mirall/folderwatcher.h"
static const uint32_t standard_event_mask =
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 {
@ -41,6 +50,8 @@ FolderWatcher::FolderWatcher(const QString &path, QObject *parent)
: QObject(parent)
{
_watcher = new QFileSystemWatcher(this);
_inotify = new INotify(path, standard_event_mask);
// watch the path and all subdirectories
{

View file

@ -1,4 +1,5 @@
#ifndef MIRALL_FOLDERWATCHER_H
#define MIRALL_FOLDERWATCHER_H
@ -6,7 +7,10 @@
#include <QString>
#include <QMutex>
#include "mirall/inotify.h"
class QFileSystemWatcher;
class INotify;
namespace Mirall {
@ -23,6 +27,7 @@ protected slots:
private:
QFileSystemWatcher *_watcher;
QMutex _mutex;
INotify *_inotify;
};
}

118
src/mirall/inotify.cpp Normal file
View file

@ -0,0 +1,118 @@
/**
Based on example by:
Copyright (c) Ashish Shukla
This is licensed under GNU GPL v2 or later.
For license text, Refer to the the file COPYING or visit
http://www.gnu.org/licenses/gpl.txt .
*/
#include <sys/inotify.h>
#include <unistd.h>
#include "inotify.h"
// Buffer Size for read() buffer
#define BUFFERSIZE 512
namespace Mirall {
// Allocate space for static members of class.
int INotify::s_fd;
INotify::INotifyThread* INotify::s_thread;
INotify::INotify(int wd) : _wd(wd)
{
}
INotify::INotify(const QString &path, int mask)
{
// Add an inotify watch.
_wd = inotify_add_watch(s_fd, path.toUtf8().data(), mask);
// Register for iNotifycation from iNotifier thread.
s_thread->registerForNotification(this);
}
INotify::~INotify()
{
// Unregister from iNotifier thread.
s_thread->unregisterForNotification(this);
// Remove the inotify watch.
inotify_rm_watch(s_fd, _wd);
}
void
INotify::INotifyThread::unregisterForNotification(INotify* notifier)
{
_map.remove(notifier->_wd);
}
void
INotify::INotifyThread::registerForNotification(INotify* notifier)
{
_map[notifier->_wd] = notifier;
}
void
INotify::fireEvent(int mask, char* name)
{
emit notifyEvent(mask, QString::fromUtf8(name));
}
void
INotify::initialize()
{
s_fd = inotify_init();
s_thread = new INotifyThread(s_fd);
s_thread->start();
}
void
INotify::cleanup()
{
close(s_fd);
s_thread->terminate();
s_thread->wait(3000);
delete s_thread;
}
INotify::INotifyThread::INotifyThread(int fd) : _fd(fd)
{
}
// Thread routine
void
INotify::INotifyThread::run()
{
int len;
struct inotify_event* event;
char buffer[BUFFERSIZE];
INotify* n = NULL;
int i;
// read the inotify file descriptor.
while((len = read(_fd, buffer, BUFFERSIZE)) > 0)
{
// reset counter
i = 0;
// while there are enough events in the buffer
while(i + sizeof(struct inotify_event) < len)
{
// cast an inotify_event
event = (struct inotify_event*)&buffer[i];
// with the help of watch descriptor, retrieve, corresponding INotify
n = _map[event->wd];
// fire event
n->fireEvent(event->mask, event->name);
// increment counter
i += sizeof(struct inotify_event) + event->len;
}
}
}
} // ns mirall
#include "inotify.moc"

59
src/mirall/inotify.h Normal file
View file

@ -0,0 +1,59 @@
/**
Based on example by:
Copyright (c) Ashish Shukla
This is licensed under GNU GPL v2 or later.
For license text, Refer to the the file COPYING or visit
http://www.gnu.org/licenses/gpl.txt .
*/
#ifndef MIRALL_INOTIFY_H
#define MIRALL_INOTIFY_H
#include <QObject>
#include <QHash>
#include <QString>
#include <QThread>
namespace Mirall
{
class INotify : public QObject
{
Q_OBJECT
public:
INotify(const QString &name, int mask);
~INotify();
static void initialize();
static void cleanup();
signals:
void notifyEvent(int mask, const QString &name);
private:
class INotifyThread : public QThread
{
int _fd;
QHash<int, INotify*> _map;
public:
INotifyThread(int fd);
void registerForNotification(INotify*);
void unregisterForNotification(INotify*);
protected:
void run();
};
INotify(int wd);
void fireEvent(int mask, char *name);
static int s_fd;
static INotifyThread* s_thread;
int _wd;
};
}
#endif