Project

General

Profile

Patch #163 ยป linuxdirwatch.diff

dyblast dyblast, 03/29/2011 08:28 PM

View differences:

application/Common/Version.h
23 23
#define VERSION_TAG "Beta10"
24 24

  
25 25
// These two values are automatically updated during the release building process. See the script 'Application/Tools/update_version.sh'
26
#define BUILD_TIME "2011-03-28_13-03"
27
#define GIT_VERSION "57073952baf03b969debc1c36411eb755a03e2ca"
26
#define BUILD_TIME "2011-03-28_21-03"
27
#define GIT_VERSION "b4ed2536331d34ae92de94e82de03f0c5cb25c29"
28 28

  
29 29
#endif
application/Core/FileManager/FileManager.pro
1
# -------------------------------------------------
2
# Project created by QtCreator 2009-10-04T18:54:43
3
# -------------------------------------------------
4
QT -= gui
5
QT += network
6
TARGET = FileManager
7
TEMPLATE = lib
8

  
9
include(../../Common/common.pri)
10
include(../../Libs/protobuf.pri)
11

  
12
CONFIG += staticlib link_prl create_prl
13

  
14
INCLUDEPATH += . ../..
15

  
16
LIBS += -L../../Common/LogManager/output/$$FOLDER -lLogManager
17
POST_TARGETDEPS += ../../Common/LogManager/output/$$FOLDER/libLogManager.a
18

  
19
LIBS += -L../../Common/output/$$FOLDER -lCommon
20
POST_TARGETDEPS += ../../Common/output/$$FOLDER/libCommon.a
21

  
22
DEFINES += FILEMANAGER_LIBRARY
23
SOURCES += priv/Builder.cpp \
24
    priv/FileManager.cpp \
25
    priv/FileUpdater/FileUpdater.cpp \
26
    priv/FileUpdater/DirWatcherWin.cpp \
27
    priv/FileUpdater/DirWatcher.cpp \
28
    priv/Cache/Entry.cpp \
29
    priv/Cache/File.cpp \
30
    priv/Cache/Directory.cpp \
31
    priv/Cache/SharedDirectory.cpp \
32
    priv/ChunkIndex/Chunks.cpp \
33
    ../../Protos/core_protocol.pb.cc \
34
    ../../Protos/common.pb.cc \
35
    priv/Cache/Chunk.cpp \
36
    priv/Cache/DataReader.cpp \
37
    priv/Cache/DataWriter.cpp \
38
    priv/Cache/Cache.cpp \
39
    ../../Protos/files_cache.pb.cc \
40
    priv/FileUpdater/WaitCondition.cpp \
41
    priv/FileUpdater/WaitConditionWin.cpp \
42
    priv/FileUpdater/WaitConditionLinux.cpp \
43
    priv/GetHashesResult.cpp \
44
    priv/Log.cpp \
45
    priv/Global.cpp
46
HEADERS += IGetHashesResult.h \
47
    IFileManager.h \
48
    IChunk.h \
49
    Builder.h \
50
    priv/Log.h \
51
    priv/FileManager.h \
52
    priv/FileUpdater/FileUpdater.h \
53
    priv/FileUpdater/DirWatcherWin.h \
54
    priv/FileUpdater/DirWatcher.h \
55
    priv/Cache/Entry.h \
56
    priv/Cache/File.h \
57
    priv/Cache/Directory.h \
58
    priv/Cache/SharedDirectory.h \
59
    priv/ChunkIndex/Chunks.h \
60
    priv/WordIndex/WordIndex.h \
61
    priv/WordIndex/Node.h \
62
    ../../Protos/core_protocol.pb.h \
63
    ../../Protos/common.pb.h \
64
    IDataReader.h \
65
    IDataWriter.h \
66
    priv/Cache/Chunk.h \
67
    priv/Cache/DataReader.h \
68
    priv/Cache/DataWriter.h \
69
    priv/Cache/Cache.h \
70
    priv/Exceptions.h \
71
    Exceptions.h \
72
    ../../Protos/files_cache.pb.h \
73
    priv/FileUpdater/WaitCondition.h \
74
    priv/FileUpdater/WaitConditionWin.h \
75
    priv/FileUpdater/WaitConditionLinux.h \
76
    priv/Constants.h \
77
    priv/GetHashesResult.h \
78
    priv/Global.h
79
OTHER_FILES +=
1
# -------------------------------------------------
2
# Project created by QtCreator 2009-10-04T18:54:43
3
# -------------------------------------------------
4
QT -= gui
5
QT += network
6
TARGET = FileManager
7
TEMPLATE = lib
8

  
9
include(../../Common/common.pri)
10
include(../../Libs/protobuf.pri)
11

  
12
CONFIG += staticlib link_prl create_prl
13

  
14
INCLUDEPATH += . ../..
15

  
16
LIBS += -L../../Common/LogManager/output/$$FOLDER -lLogManager
17
POST_TARGETDEPS += ../../Common/LogManager/output/$$FOLDER/libLogManager.a
18

  
19
LIBS += -L../../Common/output/$$FOLDER -lCommon
20
POST_TARGETDEPS += ../../Common/output/$$FOLDER/libCommon.a
21

  
22
DEFINES += FILEMANAGER_LIBRARY
23
SOURCES += priv/Builder.cpp \
24
    priv/FileManager.cpp \
25
    priv/FileUpdater/FileUpdater.cpp \
26
    priv/FileUpdater/DirWatcherWin.cpp \
27
    priv/FileUpdater/DirWatcherLinux.cpp \
28
    priv/FileUpdater/DirWatcher.cpp \
29
    priv/Cache/Entry.cpp \
30
    priv/Cache/File.cpp \
31
    priv/Cache/Directory.cpp \
32
    priv/Cache/SharedDirectory.cpp \
33
    priv/ChunkIndex/Chunks.cpp \
34
    ../../Protos/core_protocol.pb.cc \
35
    ../../Protos/common.pb.cc \
36
    priv/Cache/Chunk.cpp \
37
    priv/Cache/DataReader.cpp \
38
    priv/Cache/DataWriter.cpp \
39
    priv/Cache/Cache.cpp \
40
    ../../Protos/files_cache.pb.cc \
41
    priv/FileUpdater/WaitCondition.cpp \
42
    priv/FileUpdater/WaitConditionWin.cpp \
43
    priv/FileUpdater/WaitConditionLinux.cpp \
44
    priv/GetHashesResult.cpp \
45
    priv/Log.cpp \
46
    priv/Global.cpp
47
HEADERS += IGetHashesResult.h \
48
    IFileManager.h \
49
    IChunk.h \
50
    Builder.h \
51
    priv/Log.h \
52
    priv/FileManager.h \
53
    priv/FileUpdater/FileUpdater.h \
54
    priv/FileUpdater/DirWatcherWin.h \
55
    priv/FileUpdater/DirWatcherLinux.h \
56
    priv/FileUpdater/DirWatcher.h \
57
    priv/Cache/Entry.h \
58
    priv/Cache/File.h \
59
    priv/Cache/Directory.h \
60
    priv/Cache/SharedDirectory.h \
61
    priv/ChunkIndex/Chunks.h \
62
    priv/WordIndex/WordIndex.h \
63
    priv/WordIndex/Node.h \
64
    ../../Protos/core_protocol.pb.h \
65
    ../../Protos/common.pb.h \
66
    IDataReader.h \
67
    IDataWriter.h \
68
    priv/Cache/Chunk.h \
69
    priv/Cache/DataReader.h \
70
    priv/Cache/DataWriter.h \
71
    priv/Cache/Cache.h \
72
    priv/Exceptions.h \
73
    Exceptions.h \
74
    ../../Protos/files_cache.pb.h \
75
    priv/FileUpdater/WaitCondition.h \
76
    priv/FileUpdater/WaitConditionWin.h \
77
    priv/FileUpdater/WaitConditionLinux.h \
78
    priv/Constants.h \
79
    priv/GetHashesResult.h \
80
    priv/Global.h
81
OTHER_FILES +=
application/Core/FileManager/priv/FileUpdater/DirWatcher.cpp
25 25

  
26 26
#if defined(Q_OS_WIN32)
27 27
   #include <priv/FileUpdater/DirWatcherWin.h>
28
#elif defined(Q_OS_LINUX)
29
   #include <priv/FileUpdater/DirWatcherLinux.h>
28 30
#endif
29 31

  
30 32
DirWatcher* DirWatcher::getNewWatcher()
......
32 34
#if defined(Q_OS_WIN32)
33 35
   return new DirWatcherWin();
34 36
#else
35
   L_WARN("Cannot create a watcher for the current platform, no implementation.");
36
   return 0;
37
   return new DirWatcherLinux();
37 38
#endif
38 39
}
39 40

  
application/Core/FileManager/priv/FileUpdater/DirWatcherLinux.cpp
1
/**
2
  * D-LAN - A decentralized LAN file sharing software.
3
  * Copyright (C) 2010-2011 Greg Burri <greg.burri@gmail.com>
4
  *
5
  * This program is free software: you can redistribute it and/or modify
6
  * it under the terms of the GNU General Public License as published by
7
  * the Free Software Foundation, either version 3 of the License, or
8
  * (at your option) any later version.
9
  *
10
  * This program is distributed in the hope that it will be useful,
11
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
  * GNU General Public License for more details.
14
  *
15
  * You should have received a copy of the GNU General Public License
16
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
  */
18

  
19
#include <QtCore/QDebug>
20

  
21
#include <QMutexLocker>
22

  
23
#if defined(Q_OS_LINUX)
24
#include <priv/FileUpdater/DirWatcherLinux.h>
25

  
26
using namespace FM;
27

  
28
#include <priv/Exceptions.h>
29
#include <priv/FileUpdater/WaitConditionLinux.h>
30

  
31
/**
32
  * @class FM::DirWatcherLinux
33
  *
34
  * Implementation of 'DirWatcher' for the linux platform.
35
  */
36

  
37
DirWatcherLinux::DirWatcherLinux() :
38
    mutex(QMutex::Recursive)
39
{
40
    this->inotify_fd = inotify_init();
41
    fcntl(this->inotify_fd, F_SETFL, O_NONBLOCK);
42
}
43

  
44
DirWatcherLinux::~DirWatcherLinux()
45
{
46
    QMutexLocker locker(&this->mutex);
47

  
48
    close(this->inotify_fd);
49

  
50
    this->dirs.clear();
51
}
52

  
53
/**
54
  * @exception DirNotFoundException
55
  */
56
bool DirWatcherLinux::addDir(const QString& path)
57
{
58
    QMutexLocker locker(&this->mutex);
59

  
60
    if(this->dirs.contains(path))
61
    {
62
        L_WARN("Try to add an already watched directory: " + path);
63
        return false;
64
    }
65

  
66
    L_USER("Add path: " + path);
67
    int wd = inotify_add_watch(this->inotify_fd, path.toUtf8(), IN_CREATE | IN_DELETE | IN_MOVE | IN_MODIFY );
68
    this->dirs.insert(path, wd);
69
    return true;
70
}
71

  
72
void DirWatcherLinux::rmDir(const QString& path)
73
{
74
    QMutexLocker locker(&this->mutex);
75

  
76
    QMap<QString, int>::iterator it = this->dirs.find(path);
77
    if(it != this->dirs.end())
78
    {
79
        L_USER("Remove path: " + path);
80
        inotify_rm_watch(this->inotify_fd, it.value());
81
        this->dirs.erase(it);
82
    }
83
    else
84
    {
85
        L_WARN("Try to remove an unwatched directory: " + path);
86
    }
87
}
88

  
89
int DirWatcherLinux::nbWatchedDir()
90
{
91
    QMutexLocker locker(&this->mutex);
92
    return this->dirs.size();
93
}
94

  
95
const QList<WatcherEvent> DirWatcherLinux::waitEvent(QList<WaitCondition*> ws)
96
{
97
    return this->waitEvent(-1, ws);
98
}
99

  
100
const QList<WatcherEvent> DirWatcherLinux::waitEvent(int timeout, QList<WaitCondition*> ws)
101
{
102
    QMutexLocker locker(&this->mutex);
103

  
104
    fd_set fds;
105
    int ret;
106
    int size;
107
    struct inotify_event notify_events[16];
108

  
109
    FD_ZERO(&fds);
110
    FD_SET(this->inotify_fd, &fds);
111

  
112
    for(QList<WaitCondition*>::iterator it = ws.begin(); it != ws.end(); it ++)
113
    {
114
        WaitCondition* wc = reinterpret_cast<WaitCondition*>(*it);
115
        FD_SET((int)wc->getHandle(), &fds);
116
    }
117

  
118
    locker.unlock();
119

  
120
    if(timeout != -1)
121
    {
122
        struct timeval tv;
123
        tv.tv_usec = (timeout % 1000) * 1000;
124
        tv.tv_sec = timeout / 1000;
125
        ret = select(FD_SETSIZE, &fds, NULL, NULL, &tv) ;
126
    }else{
127
        ret = select(FD_SETSIZE, &fds, NULL, NULL, 0) ;
128
    }
129

  
130
    locker.relock();
131

  
132
    if (ret > 0) {
133
        if(FD_ISSET(this->inotify_fd, &fds))
134
        {
135
            QList<WatcherEvent> events;
136
            QMap<int, QString> cookies;
137

  
138
            do
139
            {
140
                size = read(this->inotify_fd, notify_events, sizeof(notify_events));
141
                if (size > 0) {
142
                    size /= sizeof(struct inotify_event);
143
                    for(int i = 0; i < size; i++)
144
                    {
145
                        QString path = this->dirs.key(notify_events[i].wd);
146
                        if(!path.isEmpty())
147
                        {
148
                            QString fullpath = path + QString::fromUtf8(notify_events[i].name);
149

  
150
                            switch(notify_events[i].mask)
151
                            {
152
                            case  IN_CREATE :
153
                                events << WatcherEvent(WatcherEvent::NEW, fullpath);
154
                                L_USER(QString("CREATE: %1").arg(fullpath));
155
                                break;
156
                            case IN_DELETE :
157
                                events << WatcherEvent(WatcherEvent::DELETED, fullpath);
158
                                L_USER(QString("DELETED: %1").arg(fullpath));
159
                                break;
160
                            case IN_MOVED_FROM :
161
                                cookies.insert(notify_events[i].cookie, fullpath);
162
                                break;
163
                            case IN_MOVED_TO :
164
                                if(cookies.contains(notify_events[i].cookie))
165
                                {
166
                                    QString old = cookies.take(notify_events[i].cookie);
167
                                    L_USER(QString("MOVE %1 -> %2").arg(old).arg(fullpath));
168
                                    events << WatcherEvent(WatcherEvent::MOVE, old, fullpath);
169
                                }
170
                                else
171
                                {
172
                                    events << WatcherEvent(WatcherEvent::NEW, fullpath);
173
                                    //TRICK: why only "new" file are not used?
174
                                    events << WatcherEvent(WatcherEvent::CONTENT_CHANGED, fullpath);
175
                                    L_USER(QString("CREATE: %1").arg(fullpath));
176
                                }
177
                                break;
178
                            case IN_MODIFY:
179
                                events << WatcherEvent(WatcherEvent::CONTENT_CHANGED, fullpath);
180
                                L_USER(QString("MODIFIED: %1").arg(fullpath));
181
                                break;
182
                            }
183
                        }
184
                    }
185
                }
186
            }while(size >0);
187

  
188
            for(QMap<int, QString>::iterator it = cookies.begin(); it != cookies.end(); ++it)
189
            {
190
                QString fullpath = it.value();
191
                events << WatcherEvent(WatcherEvent::DELETED, fullpath);
192
                L_USER(QString("DELETED: %1").arg(fullpath));
193
            }
194

  
195
            return events;
196
        }
197
        else
198
        {
199
            return QList<WatcherEvent>();
200
        }
201
    }
202
    else if(ret == 0)
203
    {
204
        QList<WatcherEvent> events;
205
        events.append(WatcherEvent(WatcherEvent::TIMEOUT));
206
        return events;
207
    }
208
    else
209
    {
210
        L_ERRO(QString("select(..) failed, error code : %1").arg(errno));
211
    }
212

  
213
    QList<WatcherEvent> events;
214
    events << WatcherEvent(WatcherEvent::UNKNOWN);
215
    return QList<WatcherEvent>();
216
}
217

  
218
#endif
application/Core/FileManager/priv/FileUpdater/DirWatcherLinux.h
1
/**
2
  * D-LAN - A decentralized LAN file sharing software.
3
  * Copyright (C) 2010-2011 Greg Burri <greg.burri@gmail.com>
4
  *
5
  * This program is free software: you can redistribute it and/or modify
6
  * it under the terms of the GNU General Public License as published by
7
  * the Free Software Foundation, either version 3 of the License, or
8
  * (at your option) any later version.
9
  *
10
  * This program is distributed in the hope that it will be useful,
11
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
  * GNU General Public License for more details.
14
  *
15
  * You should have received a copy of the GNU General Public License
16
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
  */
18

  
19
#include <QtCore/QtCore> // Only for the Q_OS_* defines.
20

  
21
#if !defined(FILEMANAGER_DIRWATCHERLINUX_H) and defined(Q_OS_LINUX)
22
#define FILEMANAGER_DIRWATCHERLINUX_H
23

  
24
#include <QMutex>
25

  
26
#include <priv/FileUpdater/DirWatcher.h>
27
#include <priv/Log.h>
28

  
29
#include <sys/inotify.h>
30
#include <errno.h>
31

  
32
namespace FM
33
{
34
   static const int NOTIFY_BUFFER_SIZE = 2048;
35
   static const int MAX_WAIT_CONDITION = 4;
36

  
37
   class DirWatcherLinux : public DirWatcher
38
   {
39
   public:
40
      DirWatcherLinux();
41
      ~DirWatcherLinux();
42

  
43
      bool addDir(const QString& path);
44
      void rmDir(const QString& path);
45
      int nbWatchedDir();
46
      const QList<WatcherEvent> waitEvent(QList<WaitCondition*> ws = QList<WaitCondition*>());
47
      const QList<WatcherEvent> waitEvent(int timeout, QList<WaitCondition*> ws = QList<WaitCondition*>());
48

  
49
   private:
50
      QMap<QString, int> dirs; ///< The watched dirs.
51

  
52
      int inotify_fd;
53

  
54
      QMutex mutex;
55
   };
56
}
57

  
58
#endif
application/Core/FileManager/priv/FileUpdater/WaitConditionLinux.cpp
15 15
  * You should have received a copy of the GNU General Public License
16 16
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 17
  */
18
  
18

  
19 19
#include <QtCore/QDebug>
20 20

  
21 21
#if defined(Q_OS_LINUX)
......
23 23
using namespace FM;
24 24

  
25 25
WaitConditionLinux::WaitConditionLinux() :
26
   released(false)
26
    released(false)
27 27
{
28
    this->e_fd = eventfd(0, 0);
29
    fcntl(this->e_fd, F_SETFL, O_NONBLOCK);
28 30
}
29 31

  
30 32
WaitConditionLinux::~WaitConditionLinux()
31 33
{
34
    close(this->e_fd);
32 35
}
33 36

  
34 37
void WaitConditionLinux::release()
35
{
36
   this->mutex.lock();
37
   this->released = true;
38
   this->waitCondition.wakeOne();
39
   this->mutex.unlock();      
38
{    
39
    char buffer[8];
40
    int ret;
41
    memset(buffer, 1, 8);
42
    ret = write(this->e_fd, buffer, 8);
40 43
}
41 44

  
42 45
bool WaitConditionLinux::wait(int timeout)
43 46
{
44
   bool timeouted = false;
47
    fd_set rfds;
48
    char buffer[8];
49
    int ret;
50
    int timeouted;
51

  
52
    FD_ZERO(&rfds);
53
    FD_SET(this->e_fd, &rfds);
45 54

  
46
   this->mutex.lock();
47
   if (!this->released)
48
      timeouted = !this->waitCondition.wait(&this->mutex, timeout == -1 ? ULONG_MAX : timeout);
55
    if(timeout != -1)
56
    {
57
        struct timeval tv;
58
        tv.tv_usec = (timeout % 1000) * 1000;
59
        tv.tv_sec = timeout / 1000;
60
        timeouted = select(this->e_fd + 1, &rfds, NULL, NULL, &tv);
61
    }else{
62
        timeouted = select(this->e_fd + 1, &rfds, NULL, NULL, NULL);
63
    }
49 64

  
50
   this->released = false;
51
   this->mutex.unlock();
52
   return timeouted;
65
    ret = read(this->e_fd, buffer, 8);
66
    return timeouted == 0;
53 67
}
54 68

  
55 69
void* WaitConditionLinux::getHandle()
56 70
{
57
   return 0;
71
    return (void * )this->e_fd;
58 72
}
59 73

  
60 74
#endif
application/Core/FileManager/priv/FileUpdater/WaitConditionLinux.h
21 21
#if !defined(FILEMANAGER_WAITCONDITIONLINUX_H) and defined(Q_OS_LINUX)
22 22
#define FILEMANAGER_WAITCONDITIONLINUX_H
23 23

  
24
#include <QMutex>
25
#include <QWaitCondition>
24
#include <sys/eventfd.h>
25
#include <sys/types.h>
26
#include <unistd.h>
27
#include <fcntl.h>
26 28

  
27 29
#include <priv/FileUpdater/WaitCondition.h>
28 30

  
......
46 48

  
47 49
   private:
48 50
      bool released;
49
      QMutex mutex;
50
      QWaitCondition waitCondition;
51
      int e_fd;
51 52
   };
52 53
}
53 54

  
    (1-1/1)