aboutsummaryrefslogtreecommitdiff
path: root/src/3rdParty/efsw/FileWatcherKqueue.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdParty/efsw/FileWatcherKqueue.cpp')
-rwxr-xr-xsrc/3rdParty/efsw/FileWatcherKqueue.cpp227
1 files changed, 227 insertions, 0 deletions
diff --git a/src/3rdParty/efsw/FileWatcherKqueue.cpp b/src/3rdParty/efsw/FileWatcherKqueue.cpp
new file mode 100755
index 0000000..9c86755
--- /dev/null
+++ b/src/3rdParty/efsw/FileWatcherKqueue.cpp
@@ -0,0 +1,227 @@
1#include <efsw/FileWatcherKqueue.hpp>
2
3#if EFSW_PLATFORM == EFSW_PLATFORM_KQUEUE || EFSW_PLATFORM == EFSW_PLATFORM_FSEVENTS
4
5#include <dirent.h>
6#include <efsw/Debug.hpp>
7#include <efsw/FileSystem.hpp>
8#include <efsw/Lock.hpp>
9#include <efsw/System.hpp>
10#include <efsw/WatcherGeneric.hpp>
11#include <errno.h>
12#include <fcntl.h>
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <sys/stat.h>
17#include <sys/time.h>
18#include <unistd.h>
19
20namespace efsw {
21
22FileWatcherKqueue::FileWatcherKqueue( FileWatcher* parent ) :
23 FileWatcherImpl( parent ),
24 mLastWatchID( 0 ),
25 mThread( NULL ),
26 mFileDescriptorCount( 1 ),
27 mAddingWatcher( false ) {
28 mTimeOut.tv_sec = 0;
29 mTimeOut.tv_nsec = 0;
30 mInitOK = true;
31}
32
33FileWatcherKqueue::~FileWatcherKqueue() {
34 WatchMap::iterator iter = mWatches.begin();
35
36 for ( ; iter != mWatches.end(); ++iter ) {
37 efSAFE_DELETE( iter->second );
38 }
39
40 mWatches.clear();
41
42 mInitOK = false;
43
44 efSAFE_DELETE( mThread );
45}
46
47WatchID FileWatcherKqueue::addWatch( const std::string& directory, FileWatchListener* watcher,
48 bool recursive ) {
49 static bool s_ug = false;
50
51 std::string dir( directory );
52
53 FileSystem::dirAddSlashAtEnd( dir );
54
55 FileInfo fi( dir );
56
57 if ( !fi.isDirectory() ) {
58 return Errors::Log::createLastError( Errors::FileNotFound, dir );
59 } else if ( !fi.isReadable() ) {
60 return Errors::Log::createLastError( Errors::FileNotReadable, dir );
61 } else if ( pathInWatches( dir ) ) {
62 return Errors::Log::createLastError( Errors::FileRepeated, directory );
63 }
64
65 std::string curPath;
66 std::string link( FileSystem::getLinkRealPath( dir, curPath ) );
67
68 if ( "" != link ) {
69 if ( pathInWatches( link ) ) {
70 return Errors::Log::createLastError( Errors::FileRepeated, directory );
71 } else if ( !linkAllowed( curPath, link ) ) {
72 return Errors::Log::createLastError( Errors::FileOutOfScope, dir );
73 } else {
74 dir = link;
75 }
76 }
77
78 /// Check first if are enough file descriptors available to create another kqueue watcher,
79 /// otherwise it creates a generic watcher
80 if ( availablesFD() ) {
81 mAddingWatcher = true;
82
83 WatcherKqueue* watch = new WatcherKqueue( ++mLastWatchID, dir, watcher, recursive, this );
84
85 {
86 Lock lock( mWatchesLock );
87 mWatches.insert( std::make_pair( mLastWatchID, watch ) );
88 }
89
90 watch->addAll();
91
92 // if failed to open the directory... erase the watcher
93 if ( !watch->initOK() ) {
94 int le = watch->lastErrno();
95
96 mWatches.erase( watch->ID );
97
98 efSAFE_DELETE( watch );
99
100 mLastWatchID--;
101
102 // Probably the folder has too many files, create a generic watcher
103 if ( EACCES != le ) {
104 WatcherGeneric* genericWatch =
105 new WatcherGeneric( ++mLastWatchID, dir, watcher, this, recursive );
106
107 Lock lock( mWatchesLock );
108 mWatches.insert( std::make_pair( mLastWatchID, genericWatch ) );
109 } else {
110 return Errors::Log::createLastError( Errors::Unspecified, link );
111 }
112 }
113
114 mAddingWatcher = false;
115 } else {
116 if ( !s_ug ) {
117 efDEBUG( "Started using generic watcher, file descriptor limit reached: %ld\n",
118 mFileDescriptorCount );
119 s_ug = true;
120 }
121
122 WatcherGeneric* watch = new WatcherGeneric( ++mLastWatchID, dir, watcher, this, recursive );
123
124 Lock lock( mWatchesLock );
125 mWatches.insert( std::make_pair( mLastWatchID, watch ) );
126 }
127
128 return mLastWatchID;
129}
130
131void FileWatcherKqueue::removeWatch( const std::string& directory ) {
132 Lock lock( mWatchesLock );
133
134 WatchMap::iterator iter = mWatches.begin();
135
136 for ( ; iter != mWatches.end(); ++iter ) {
137 if ( directory == iter->second->Directory ) {
138 removeWatch( iter->first );
139 return;
140 }
141 }
142}
143
144void FileWatcherKqueue::removeWatch( WatchID watchid ) {
145 Lock lock( mWatchesLock );
146
147 WatchMap::iterator iter = mWatches.find( watchid );
148
149 if ( iter == mWatches.end() )
150 return;
151
152 Watcher* watch = iter->second;
153
154 mWatches.erase( iter );
155
156 efSAFE_DELETE( watch );
157}
158
159bool FileWatcherKqueue::isAddingWatcher() const {
160 return mAddingWatcher;
161}
162
163void FileWatcherKqueue::watch() {
164 if ( NULL == mThread ) {
165 mThread = new Thread( &FileWatcherKqueue::run, this );
166 mThread->launch();
167 }
168}
169
170void FileWatcherKqueue::run() {
171 do {
172 {
173 Lock lock( mWatchesLock );
174
175 for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) {
176 it->second->watch();
177 }
178 }
179
180 System::sleep( 500 );
181 } while ( mInitOK );
182}
183
184void FileWatcherKqueue::handleAction( Watcher* watch, const std::string& filename,
185 unsigned long action, std::string oldFilename ) {}
186
187std::list<std::string> FileWatcherKqueue::directories() {
188 std::list<std::string> dirs;
189
190 Lock lock( mWatchesLock );
191
192 WatchMap::iterator it = mWatches.begin();
193
194 for ( ; it != mWatches.end(); ++it ) {
195 dirs.push_back( it->second->Directory );
196 }
197
198 return dirs;
199}
200
201bool FileWatcherKqueue::pathInWatches( const std::string& path ) {
202 WatchMap::iterator it = mWatches.begin();
203
204 for ( ; it != mWatches.end(); ++it ) {
205 if ( it->second->Directory == path ) {
206 return true;
207 }
208 }
209
210 return false;
211}
212
213void FileWatcherKqueue::addFD() {
214 mFileDescriptorCount++;
215}
216
217void FileWatcherKqueue::removeFD() {
218 mFileDescriptorCount--;
219}
220
221bool FileWatcherKqueue::availablesFD() {
222 return mFileDescriptorCount <= (Int64)System::getMaxFD() - 500;
223}
224
225} // namespace efsw
226
227#endif