Patch #163 ยป linuxdirwatch.diff
application/Common/Version.h | ||
---|---|---|
#define VERSION_TAG "Beta10"
|
||
// These two values are automatically updated during the release building process. See the script 'Application/Tools/update_version.sh'
|
||
#define BUILD_TIME "2011-03-28_13-03"
|
||
#define GIT_VERSION "57073952baf03b969debc1c36411eb755a03e2ca"
|
||
#define BUILD_TIME "2011-03-28_21-03"
|
||
#define GIT_VERSION "b4ed2536331d34ae92de94e82de03f0c5cb25c29"
|
||
#endif
|
application/Core/FileManager/FileManager.pro | ||
---|---|---|
# -------------------------------------------------
|
||
# Project created by QtCreator 2009-10-04T18:54:43
|
||
# -------------------------------------------------
|
||
QT -= gui
|
||
QT += network
|
||
TARGET = FileManager
|
||
TEMPLATE = lib
|
||
|
||
include(../../Common/common.pri)
|
||
include(../../Libs/protobuf.pri)
|
||
|
||
CONFIG += staticlib link_prl create_prl
|
||
|
||
INCLUDEPATH += . ../..
|
||
|
||
LIBS += -L../../Common/LogManager/output/$$FOLDER -lLogManager
|
||
POST_TARGETDEPS += ../../Common/LogManager/output/$$FOLDER/libLogManager.a
|
||
|
||
LIBS += -L../../Common/output/$$FOLDER -lCommon
|
||
POST_TARGETDEPS += ../../Common/output/$$FOLDER/libCommon.a
|
||
|
||
DEFINES += FILEMANAGER_LIBRARY
|
||
SOURCES += priv/Builder.cpp \
|
||
priv/FileManager.cpp \
|
||
priv/FileUpdater/FileUpdater.cpp \
|
||
priv/FileUpdater/DirWatcherWin.cpp \
|
||
priv/FileUpdater/DirWatcher.cpp \
|
||
priv/Cache/Entry.cpp \
|
||
priv/Cache/File.cpp \
|
||
priv/Cache/Directory.cpp \
|
||
priv/Cache/SharedDirectory.cpp \
|
||
priv/ChunkIndex/Chunks.cpp \
|
||
../../Protos/core_protocol.pb.cc \
|
||
../../Protos/common.pb.cc \
|
||
priv/Cache/Chunk.cpp \
|
||
priv/Cache/DataReader.cpp \
|
||
priv/Cache/DataWriter.cpp \
|
||
priv/Cache/Cache.cpp \
|
||
../../Protos/files_cache.pb.cc \
|
||
priv/FileUpdater/WaitCondition.cpp \
|
||
priv/FileUpdater/WaitConditionWin.cpp \
|
||
priv/FileUpdater/WaitConditionLinux.cpp \
|
||
priv/GetHashesResult.cpp \
|
||
priv/Log.cpp \
|
||
priv/Global.cpp
|
||
HEADERS += IGetHashesResult.h \
|
||
IFileManager.h \
|
||
IChunk.h \
|
||
Builder.h \
|
||
priv/Log.h \
|
||
priv/FileManager.h \
|
||
priv/FileUpdater/FileUpdater.h \
|
||
priv/FileUpdater/DirWatcherWin.h \
|
||
priv/FileUpdater/DirWatcher.h \
|
||
priv/Cache/Entry.h \
|
||
priv/Cache/File.h \
|
||
priv/Cache/Directory.h \
|
||
priv/Cache/SharedDirectory.h \
|
||
priv/ChunkIndex/Chunks.h \
|
||
priv/WordIndex/WordIndex.h \
|
||
priv/WordIndex/Node.h \
|
||
../../Protos/core_protocol.pb.h \
|
||
../../Protos/common.pb.h \
|
||
IDataReader.h \
|
||
IDataWriter.h \
|
||
priv/Cache/Chunk.h \
|
||
priv/Cache/DataReader.h \
|
||
priv/Cache/DataWriter.h \
|
||
priv/Cache/Cache.h \
|
||
priv/Exceptions.h \
|
||
Exceptions.h \
|
||
../../Protos/files_cache.pb.h \
|
||
priv/FileUpdater/WaitCondition.h \
|
||
priv/FileUpdater/WaitConditionWin.h \
|
||
priv/FileUpdater/WaitConditionLinux.h \
|
||
priv/Constants.h \
|
||
priv/GetHashesResult.h \
|
||
priv/Global.h
|
||
OTHER_FILES +=
|
||
# -------------------------------------------------
|
||
# Project created by QtCreator 2009-10-04T18:54:43
|
||
# -------------------------------------------------
|
||
QT -= gui
|
||
QT += network
|
||
TARGET = FileManager
|
||
TEMPLATE = lib
|
||
include(../../Common/common.pri)
|
||
include(../../Libs/protobuf.pri)
|
||
CONFIG += staticlib link_prl create_prl
|
||
INCLUDEPATH += . ../..
|
||
LIBS += -L../../Common/LogManager/output/$$FOLDER -lLogManager
|
||
POST_TARGETDEPS += ../../Common/LogManager/output/$$FOLDER/libLogManager.a
|
||
LIBS += -L../../Common/output/$$FOLDER -lCommon
|
||
POST_TARGETDEPS += ../../Common/output/$$FOLDER/libCommon.a
|
||
DEFINES += FILEMANAGER_LIBRARY
|
||
SOURCES += priv/Builder.cpp \
|
||
priv/FileManager.cpp \
|
||
priv/FileUpdater/FileUpdater.cpp \
|
||
priv/FileUpdater/DirWatcherWin.cpp \
|
||
priv/FileUpdater/DirWatcherLinux.cpp \
|
||
priv/FileUpdater/DirWatcher.cpp \
|
||
priv/Cache/Entry.cpp \
|
||
priv/Cache/File.cpp \
|
||
priv/Cache/Directory.cpp \
|
||
priv/Cache/SharedDirectory.cpp \
|
||
priv/ChunkIndex/Chunks.cpp \
|
||
../../Protos/core_protocol.pb.cc \
|
||
../../Protos/common.pb.cc \
|
||
priv/Cache/Chunk.cpp \
|
||
priv/Cache/DataReader.cpp \
|
||
priv/Cache/DataWriter.cpp \
|
||
priv/Cache/Cache.cpp \
|
||
../../Protos/files_cache.pb.cc \
|
||
priv/FileUpdater/WaitCondition.cpp \
|
||
priv/FileUpdater/WaitConditionWin.cpp \
|
||
priv/FileUpdater/WaitConditionLinux.cpp \
|
||
priv/GetHashesResult.cpp \
|
||
priv/Log.cpp \
|
||
priv/Global.cpp
|
||
HEADERS += IGetHashesResult.h \
|
||
IFileManager.h \
|
||
IChunk.h \
|
||
Builder.h \
|
||
priv/Log.h \
|
||
priv/FileManager.h \
|
||
priv/FileUpdater/FileUpdater.h \
|
||
priv/FileUpdater/DirWatcherWin.h \
|
||
priv/FileUpdater/DirWatcherLinux.h \
|
||
priv/FileUpdater/DirWatcher.h \
|
||
priv/Cache/Entry.h \
|
||
priv/Cache/File.h \
|
||
priv/Cache/Directory.h \
|
||
priv/Cache/SharedDirectory.h \
|
||
priv/ChunkIndex/Chunks.h \
|
||
priv/WordIndex/WordIndex.h \
|
||
priv/WordIndex/Node.h \
|
||
../../Protos/core_protocol.pb.h \
|
||
../../Protos/common.pb.h \
|
||
IDataReader.h \
|
||
IDataWriter.h \
|
||
priv/Cache/Chunk.h \
|
||
priv/Cache/DataReader.h \
|
||
priv/Cache/DataWriter.h \
|
||
priv/Cache/Cache.h \
|
||
priv/Exceptions.h \
|
||
Exceptions.h \
|
||
../../Protos/files_cache.pb.h \
|
||
priv/FileUpdater/WaitCondition.h \
|
||
priv/FileUpdater/WaitConditionWin.h \
|
||
priv/FileUpdater/WaitConditionLinux.h \
|
||
priv/Constants.h \
|
||
priv/GetHashesResult.h \
|
||
priv/Global.h
|
||
OTHER_FILES +=
|
application/Core/FileManager/priv/FileUpdater/DirWatcher.cpp | ||
---|---|---|
#if defined(Q_OS_WIN32)
|
||
#include <priv/FileUpdater/DirWatcherWin.h>
|
||
#elif defined(Q_OS_LINUX)
|
||
#include <priv/FileUpdater/DirWatcherLinux.h>
|
||
#endif
|
||
DirWatcher* DirWatcher::getNewWatcher()
|
||
... | ... | |
#if defined(Q_OS_WIN32)
|
||
return new DirWatcherWin();
|
||
#else
|
||
L_WARN("Cannot create a watcher for the current platform, no implementation.");
|
||
return 0;
|
||
return new DirWatcherLinux();
|
||
#endif
|
||
}
|
||
application/Core/FileManager/priv/FileUpdater/DirWatcherLinux.cpp | ||
---|---|---|
/**
|
||
* D-LAN - A decentralized LAN file sharing software.
|
||
* Copyright (C) 2010-2011 Greg Burri <greg.burri@gmail.com>
|
||
*
|
||
* 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 3 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.
|
||
*
|
||
* You should have received a copy of the GNU General Public License
|
||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
*/
|
||
#include <QtCore/QDebug>
|
||
#include <QMutexLocker>
|
||
#if defined(Q_OS_LINUX)
|
||
#include <priv/FileUpdater/DirWatcherLinux.h>
|
||
using namespace FM;
|
||
#include <priv/Exceptions.h>
|
||
#include <priv/FileUpdater/WaitConditionLinux.h>
|
||
/**
|
||
* @class FM::DirWatcherLinux
|
||
*
|
||
* Implementation of 'DirWatcher' for the linux platform.
|
||
*/
|
||
DirWatcherLinux::DirWatcherLinux() :
|
||
mutex(QMutex::Recursive)
|
||
{
|
||
this->inotify_fd = inotify_init();
|
||
fcntl(this->inotify_fd, F_SETFL, O_NONBLOCK);
|
||
}
|
||
DirWatcherLinux::~DirWatcherLinux()
|
||
{
|
||
QMutexLocker locker(&this->mutex);
|
||
close(this->inotify_fd);
|
||
this->dirs.clear();
|
||
}
|
||
/**
|
||
* @exception DirNotFoundException
|
||
*/
|
||
bool DirWatcherLinux::addDir(const QString& path)
|
||
{
|
||
QMutexLocker locker(&this->mutex);
|
||
if(this->dirs.contains(path))
|
||
{
|
||
L_WARN("Try to add an already watched directory: " + path);
|
||
return false;
|
||
}
|
||
L_USER("Add path: " + path);
|
||
int wd = inotify_add_watch(this->inotify_fd, path.toUtf8(), IN_CREATE | IN_DELETE | IN_MOVE | IN_MODIFY );
|
||
this->dirs.insert(path, wd);
|
||
return true;
|
||
}
|
||
void DirWatcherLinux::rmDir(const QString& path)
|
||
{
|
||
QMutexLocker locker(&this->mutex);
|
||
QMap<QString, int>::iterator it = this->dirs.find(path);
|
||
if(it != this->dirs.end())
|
||
{
|
||
L_USER("Remove path: " + path);
|
||
inotify_rm_watch(this->inotify_fd, it.value());
|
||
this->dirs.erase(it);
|
||
}
|
||
else
|
||
{
|
||
L_WARN("Try to remove an unwatched directory: " + path);
|
||
}
|
||
}
|
||
int DirWatcherLinux::nbWatchedDir()
|
||
{
|
||
QMutexLocker locker(&this->mutex);
|
||
return this->dirs.size();
|
||
}
|
||
const QList<WatcherEvent> DirWatcherLinux::waitEvent(QList<WaitCondition*> ws)
|
||
{
|
||
return this->waitEvent(-1, ws);
|
||
}
|
||
const QList<WatcherEvent> DirWatcherLinux::waitEvent(int timeout, QList<WaitCondition*> ws)
|
||
{
|
||
QMutexLocker locker(&this->mutex);
|
||
fd_set fds;
|
||
int ret;
|
||
int size;
|
||
struct inotify_event notify_events[16];
|
||
FD_ZERO(&fds);
|
||
FD_SET(this->inotify_fd, &fds);
|
||
for(QList<WaitCondition*>::iterator it = ws.begin(); it != ws.end(); it ++)
|
||
{
|
||
WaitCondition* wc = reinterpret_cast<WaitCondition*>(*it);
|
||
FD_SET((int)wc->getHandle(), &fds);
|
||
}
|
||
locker.unlock();
|
||
if(timeout != -1)
|
||
{
|
||
struct timeval tv;
|
||
tv.tv_usec = (timeout % 1000) * 1000;
|
||
tv.tv_sec = timeout / 1000;
|
||
ret = select(FD_SETSIZE, &fds, NULL, NULL, &tv) ;
|
||
}else{
|
||
ret = select(FD_SETSIZE, &fds, NULL, NULL, 0) ;
|
||
}
|
||
locker.relock();
|
||
if (ret > 0) {
|
||
if(FD_ISSET(this->inotify_fd, &fds))
|
||
{
|
||
QList<WatcherEvent> events;
|
||
QMap<int, QString> cookies;
|
||
do
|
||
{
|
||
size = read(this->inotify_fd, notify_events, sizeof(notify_events));
|
||
if (size > 0) {
|
||
size /= sizeof(struct inotify_event);
|
||
for(int i = 0; i < size; i++)
|
||
{
|
||
QString path = this->dirs.key(notify_events[i].wd);
|
||
if(!path.isEmpty())
|
||
{
|
||
QString fullpath = path + QString::fromUtf8(notify_events[i].name);
|
||
switch(notify_events[i].mask)
|
||
{
|
||
case IN_CREATE :
|
||
events << WatcherEvent(WatcherEvent::NEW, fullpath);
|
||
L_USER(QString("CREATE: %1").arg(fullpath));
|
||
break;
|
||
case IN_DELETE :
|
||
events << WatcherEvent(WatcherEvent::DELETED, fullpath);
|
||
L_USER(QString("DELETED: %1").arg(fullpath));
|
||
break;
|
||
case IN_MOVED_FROM :
|
||
cookies.insert(notify_events[i].cookie, fullpath);
|
||
break;
|
||
case IN_MOVED_TO :
|
||
if(cookies.contains(notify_events[i].cookie))
|
||
{
|
||
QString old = cookies.take(notify_events[i].cookie);
|
||
L_USER(QString("MOVE %1 -> %2").arg(old).arg(fullpath));
|
||
events << WatcherEvent(WatcherEvent::MOVE, old, fullpath);
|
||
}
|
||
else
|
||
{
|
||
events << WatcherEvent(WatcherEvent::NEW, fullpath);
|
||
//TRICK: why only "new" file are not used?
|
||
events << WatcherEvent(WatcherEvent::CONTENT_CHANGED, fullpath);
|
||
L_USER(QString("CREATE: %1").arg(fullpath));
|
||
}
|
||
break;
|
||
case IN_MODIFY:
|
||
events << WatcherEvent(WatcherEvent::CONTENT_CHANGED, fullpath);
|
||
L_USER(QString("MODIFIED: %1").arg(fullpath));
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}while(size >0);
|
||
for(QMap<int, QString>::iterator it = cookies.begin(); it != cookies.end(); ++it)
|
||
{
|
||
QString fullpath = it.value();
|
||
events << WatcherEvent(WatcherEvent::DELETED, fullpath);
|
||
L_USER(QString("DELETED: %1").arg(fullpath));
|
||
}
|
||
return events;
|
||
}
|
||
else
|
||
{
|
||
return QList<WatcherEvent>();
|
||
}
|
||
}
|
||
else if(ret == 0)
|
||
{
|
||
QList<WatcherEvent> events;
|
||
events.append(WatcherEvent(WatcherEvent::TIMEOUT));
|
||
return events;
|
||
}
|
||
else
|
||
{
|
||
L_ERRO(QString("select(..) failed, error code : %1").arg(errno));
|
||
}
|
||
QList<WatcherEvent> events;
|
||
events << WatcherEvent(WatcherEvent::UNKNOWN);
|
||
return QList<WatcherEvent>();
|
||
}
|
||
#endif
|
application/Core/FileManager/priv/FileUpdater/DirWatcherLinux.h | ||
---|---|---|
/**
|
||
* D-LAN - A decentralized LAN file sharing software.
|
||
* Copyright (C) 2010-2011 Greg Burri <greg.burri@gmail.com>
|
||
*
|
||
* 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 3 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.
|
||
*
|
||
* You should have received a copy of the GNU General Public License
|
||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
*/
|
||
#include <QtCore/QtCore> // Only for the Q_OS_* defines.
|
||
#if !defined(FILEMANAGER_DIRWATCHERLINUX_H) and defined(Q_OS_LINUX)
|
||
#define FILEMANAGER_DIRWATCHERLINUX_H
|
||
#include <QMutex>
|
||
#include <priv/FileUpdater/DirWatcher.h>
|
||
#include <priv/Log.h>
|
||
#include <sys/inotify.h>
|
||
#include <errno.h>
|
||
namespace FM
|
||
{
|
||
static const int NOTIFY_BUFFER_SIZE = 2048;
|
||
static const int MAX_WAIT_CONDITION = 4;
|
||
class DirWatcherLinux : public DirWatcher
|
||
{
|
||
public:
|
||
DirWatcherLinux();
|
||
~DirWatcherLinux();
|
||
bool addDir(const QString& path);
|
||
void rmDir(const QString& path);
|
||
int nbWatchedDir();
|
||
const QList<WatcherEvent> waitEvent(QList<WaitCondition*> ws = QList<WaitCondition*>());
|
||
const QList<WatcherEvent> waitEvent(int timeout, QList<WaitCondition*> ws = QList<WaitCondition*>());
|
||
private:
|
||
QMap<QString, int> dirs; ///< The watched dirs.
|
||
int inotify_fd;
|
||
QMutex mutex;
|
||
};
|
||
}
|
||
#endif
|
application/Core/FileManager/priv/FileUpdater/WaitConditionLinux.cpp | ||
---|---|---|
* You should have received a copy of the GNU General Public License
|
||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
*/
|
||
|
||
#include <QtCore/QDebug>
|
||
#if defined(Q_OS_LINUX)
|
||
... | ... | |
using namespace FM;
|
||
WaitConditionLinux::WaitConditionLinux() :
|
||
released(false)
|
||
released(false)
|
||
{
|
||
this->e_fd = eventfd(0, 0);
|
||
fcntl(this->e_fd, F_SETFL, O_NONBLOCK);
|
||
}
|
||
WaitConditionLinux::~WaitConditionLinux()
|
||
{
|
||
close(this->e_fd);
|
||
}
|
||
void WaitConditionLinux::release()
|
||
{
|
||
this->mutex.lock();
|
||
this->released = true;
|
||
this->waitCondition.wakeOne();
|
||
this->mutex.unlock();
|
||
{
|
||
char buffer[8];
|
||
int ret;
|
||
memset(buffer, 1, 8);
|
||
ret = write(this->e_fd, buffer, 8);
|
||
}
|
||
bool WaitConditionLinux::wait(int timeout)
|
||
{
|
||
bool timeouted = false;
|
||
fd_set rfds;
|
||
char buffer[8];
|
||
int ret;
|
||
int timeouted;
|
||
FD_ZERO(&rfds);
|
||
FD_SET(this->e_fd, &rfds);
|
||
this->mutex.lock();
|
||
if (!this->released)
|
||
timeouted = !this->waitCondition.wait(&this->mutex, timeout == -1 ? ULONG_MAX : timeout);
|
||
if(timeout != -1)
|
||
{
|
||
struct timeval tv;
|
||
tv.tv_usec = (timeout % 1000) * 1000;
|
||
tv.tv_sec = timeout / 1000;
|
||
timeouted = select(this->e_fd + 1, &rfds, NULL, NULL, &tv);
|
||
}else{
|
||
timeouted = select(this->e_fd + 1, &rfds, NULL, NULL, NULL);
|
||
}
|
||
this->released = false;
|
||
this->mutex.unlock();
|
||
return timeouted;
|
||
ret = read(this->e_fd, buffer, 8);
|
||
return timeouted == 0;
|
||
}
|
||
void* WaitConditionLinux::getHandle()
|
||
{
|
||
return 0;
|
||
return (void * )this->e_fd;
|
||
}
|
||
#endif
|
application/Core/FileManager/priv/FileUpdater/WaitConditionLinux.h | ||
---|---|---|
#if !defined(FILEMANAGER_WAITCONDITIONLINUX_H) and defined(Q_OS_LINUX)
|
||
#define FILEMANAGER_WAITCONDITIONLINUX_H
|
||
#include <QMutex>
|
||
#include <QWaitCondition>
|
||
#include <sys/eventfd.h>
|
||
#include <sys/types.h>
|
||
#include <unistd.h>
|
||
#include <fcntl.h>
|
||
#include <priv/FileUpdater/WaitCondition.h>
|
||
... | ... | |
private:
|
||
bool released;
|
||
QMutex mutex;
|
||
QWaitCondition waitCondition;
|
||
int e_fd;
|
||
};
|
||
}
|
||