aboutsummaryrefslogtreecommitdiff
path: root/src/3rdParty/efsw/FileWatcherWin32.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdParty/efsw/FileWatcherWin32.cpp')
-rw-r--r--[-rwxr-xr-x]src/3rdParty/efsw/FileWatcherWin32.cpp524
1 files changed, 267 insertions, 257 deletions
diff --git a/src/3rdParty/efsw/FileWatcherWin32.cpp b/src/3rdParty/efsw/FileWatcherWin32.cpp
index 963dc98..19b71d7 100755..100644
--- a/src/3rdParty/efsw/FileWatcherWin32.cpp
+++ b/src/3rdParty/efsw/FileWatcherWin32.cpp
@@ -1,257 +1,267 @@
1#include <efsw/FileSystem.hpp> 1#include <efsw/FileSystem.hpp>
2#include <efsw/FileWatcherWin32.hpp> 2#include <efsw/FileWatcherWin32.hpp>
3#include <efsw/Lock.hpp> 3#include <efsw/Lock.hpp>
4#include <efsw/String.hpp> 4#include <efsw/String.hpp>
5#include <efsw/System.hpp> 5#include <efsw/System.hpp>
6 6
7#if EFSW_PLATFORM == EFSW_PLATFORM_WIN32 7#if EFSW_PLATFORM == EFSW_PLATFORM_WIN32
8 8
9namespace efsw { 9namespace efsw {
10 10
11FileWatcherWin32::FileWatcherWin32( FileWatcher* parent ) : 11FileWatcherWin32::FileWatcherWin32( FileWatcher* parent ) :
12 FileWatcherImpl( parent ), mLastWatchID( 0 ), mThread( NULL ) { 12 FileWatcherImpl( parent ), mLastWatchID( 0 ), mThread( NULL ) {
13 mIOCP = CreateIoCompletionPort( INVALID_HANDLE_VALUE, NULL, 0, 1 ); 13 mIOCP = CreateIoCompletionPort( INVALID_HANDLE_VALUE, NULL, 0, 1 );
14 if ( mIOCP && mIOCP != INVALID_HANDLE_VALUE ) 14 if ( mIOCP && mIOCP != INVALID_HANDLE_VALUE )
15 mInitOK = true; 15 mInitOK = true;
16} 16}
17 17
18FileWatcherWin32::~FileWatcherWin32() { 18FileWatcherWin32::~FileWatcherWin32() {
19 mInitOK = false; 19 mInitOK = false;
20 20
21 if ( mIOCP && mIOCP != INVALID_HANDLE_VALUE ) { 21 if ( mIOCP && mIOCP != INVALID_HANDLE_VALUE ) {
22 PostQueuedCompletionStatus( mIOCP, 0, reinterpret_cast<ULONG_PTR>( this ), NULL ); 22 PostQueuedCompletionStatus( mIOCP, 0, reinterpret_cast<ULONG_PTR>( this ), NULL );
23 } 23 }
24 24
25 efSAFE_DELETE( mThread ); 25 efSAFE_DELETE( mThread );
26 26
27 removeAllWatches(); 27 removeAllWatches();
28 28
29 CloseHandle( mIOCP ); 29 if ( mIOCP )
30} 30 CloseHandle( mIOCP );
31 31}
32WatchID FileWatcherWin32::addWatch( const std::string& directory, FileWatchListener* watcher, 32
33 bool recursive ) { 33WatchID FileWatcherWin32::addWatch( const std::string& directory, FileWatchListener* watcher,
34 std::string dir( directory ); 34 bool recursive, const std::vector<WatcherOption> &options ) {
35 35 std::string dir( directory );
36 FileInfo fi( dir ); 36
37 37 FileInfo fi( dir );
38 if ( !fi.isDirectory() ) { 38
39 return Errors::Log::createLastError( Errors::FileNotFound, dir ); 39 if ( !fi.isDirectory() ) {
40 } else if ( !fi.isReadable() ) { 40 return Errors::Log::createLastError( Errors::FileNotFound, dir );
41 return Errors::Log::createLastError( Errors::FileNotReadable, dir ); 41 } else if ( !fi.isReadable() ) {
42 } 42 return Errors::Log::createLastError( Errors::FileNotReadable, dir );
43 43 }
44 FileSystem::dirAddSlashAtEnd( dir ); 44
45 45 FileSystem::dirAddSlashAtEnd( dir );
46 Lock lock( mWatchesLock ); 46
47 47 Lock lock( mWatchesLock );
48 if ( pathInWatches( dir ) ) { 48
49 return Errors::Log::createLastError( Errors::FileRepeated, dir ); 49 if ( pathInWatches( dir ) ) {
50 } 50 return Errors::Log::createLastError( Errors::FileRepeated, dir );
51 51 }
52 WatchID watchid = ++mLastWatchID; 52
53 53 WatchID watchid = ++mLastWatchID;
54 WatcherStructWin32* watch = CreateWatch( 54
55 String::fromUtf8( dir ).toWideString().c_str(), recursive, 55 DWORD bufferSize = static_cast<DWORD>( getOptionValue(options, Option::WinBufferSize, 63 * 1024) );
56 FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_FILE_NAME | 56 DWORD notifyFilter = static_cast<DWORD>( getOptionValue(options, Option::WinNotifyFilter,
57 FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_SIZE, 57 FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_LAST_WRITE |
58 mIOCP ); 58 FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME |
59 59 FILE_NOTIFY_CHANGE_SIZE) );
60 if ( NULL == watch ) { 60
61 return Errors::Log::createLastError( Errors::FileNotFound, dir ); 61 WatcherStructWin32* watch = CreateWatch( String::fromUtf8( dir ).toWideString().c_str(),
62 } 62 recursive, bufferSize, notifyFilter, mIOCP );
63 63
64 // Add the handle to the handles vector 64 if ( NULL == watch ) {
65 watch->Watch->ID = watchid; 65 return Errors::Log::createLastError( Errors::FileNotFound, dir );
66 watch->Watch->Watch = this; 66 }
67 watch->Watch->Listener = watcher; 67
68 watch->Watch->DirName = new char[dir.length() + 1]; 68 // Add the handle to the handles vector
69 strcpy( watch->Watch->DirName, dir.c_str() ); 69 watch->Watch->ID = watchid;
70 70 watch->Watch->Watch = this;
71 mWatches.insert( watch ); 71 watch->Watch->Listener = watcher;
72 72 watch->Watch->DirName = new char[dir.length() + 1];
73 return watchid; 73 strcpy( watch->Watch->DirName, dir.c_str() );
74} 74
75 75 mWatches.insert( watch );
76void FileWatcherWin32::removeWatch( const std::string& directory ) { 76
77 Lock lock( mWatchesLock ); 77 return watchid;
78 78}
79 Watches::iterator iter = mWatches.begin(); 79
80 80void FileWatcherWin32::removeWatch( const std::string& directory ) {
81 for ( ; iter != mWatches.end(); ++iter ) { 81 Lock lock( mWatchesLock );
82 if ( directory == ( *iter )->Watch->DirName ) { 82
83 removeWatch( *iter ); 83 Watches::iterator iter = mWatches.begin();
84 break; 84
85 } 85 for ( ; iter != mWatches.end(); ++iter ) {
86 } 86 if ( directory == ( *iter )->Watch->DirName ) {
87} 87 removeWatch( *iter );
88 88 break;
89void FileWatcherWin32::removeWatch( WatchID watchid ) { 89 }
90 Lock lock( mWatchesLock ); 90 }
91 91}
92 Watches::iterator iter = mWatches.begin(); 92
93 93void FileWatcherWin32::removeWatch( WatchID watchid ) {
94 for ( ; iter != mWatches.end(); ++iter ) { 94 Lock lock( mWatchesLock );
95 // Find the watch ID 95
96 if ( ( *iter )->Watch->ID == watchid ) { 96 Watches::iterator iter = mWatches.begin();
97 removeWatch( *iter ); 97
98 return; 98 for ( ; iter != mWatches.end(); ++iter ) {
99 } 99 // Find the watch ID
100 } 100 if ( ( *iter )->Watch->ID == watchid ) {
101} 101 removeWatch( *iter );
102 102 return;
103void FileWatcherWin32::removeWatch( WatcherStructWin32* watch ) { 103 }
104 Lock lock( mWatchesLock ); 104 }
105 105}
106 DestroyWatch( watch ); 106
107 mWatches.erase( watch ); 107void FileWatcherWin32::removeWatch( WatcherStructWin32* watch ) {
108} 108 Lock lock( mWatchesLock );
109 109
110void FileWatcherWin32::watch() { 110 DestroyWatch( watch );
111 if ( NULL == mThread ) { 111 mWatches.erase( watch );
112 mThread = new Thread( &FileWatcherWin32::run, this ); 112}
113 mThread->launch(); 113
114 } 114void FileWatcherWin32::watch() {
115} 115 if ( NULL == mThread ) {
116 116 mThread = new Thread( &FileWatcherWin32::run, this );
117void FileWatcherWin32::removeAllWatches() { 117 mThread->launch();
118 Lock lock( mWatchesLock ); 118 }
119 119}
120 Watches::iterator iter = mWatches.begin(); 120
121 121void FileWatcherWin32::removeAllWatches() {
122 for ( ; iter != mWatches.end(); ++iter ) { 122 Lock lock( mWatchesLock );
123 DestroyWatch( ( *iter ) ); 123
124 } 124 Watches::iterator iter = mWatches.begin();
125 125
126 mWatches.clear(); 126 for ( ; iter != mWatches.end(); ++iter ) {
127} 127 DestroyWatch( ( *iter ) );
128 128 }
129void FileWatcherWin32::run() { 129
130 do { 130 mWatches.clear();
131 if ( mInitOK && !mWatches.empty() ) { 131}
132 DWORD numOfBytes = 0; 132
133 OVERLAPPED* ov = NULL; 133void FileWatcherWin32::run() {
134 ULONG_PTR compKey = 0; 134 do {
135 BOOL res = FALSE; 135 if ( mInitOK && !mWatches.empty() ) {
136 136 DWORD numOfBytes = 0;
137 while ( ( res = GetQueuedCompletionStatus( mIOCP, &numOfBytes, &compKey, &ov, 137 OVERLAPPED* ov = NULL;
138 INFINITE ) ) != FALSE ) { 138 ULONG_PTR compKey = 0;
139 if ( compKey != 0 && compKey == reinterpret_cast<ULONG_PTR>( this ) ) { 139 BOOL res = FALSE;
140 break; 140
141 } else { 141 while ( ( res = GetQueuedCompletionStatus( mIOCP, &numOfBytes, &compKey, &ov,
142 Lock lock( mWatchesLock ); 142 INFINITE ) ) != FALSE ) {
143 WatchCallback( numOfBytes, ov ); 143 if ( compKey != 0 && compKey == reinterpret_cast<ULONG_PTR>( this ) ) {
144 } 144 break;
145 } 145 } else {
146 } else { 146 Lock lock( mWatchesLock );
147 System::sleep( 10 ); 147 if (mWatches.find( (WatcherStructWin32*)ov ) != mWatches.end())
148 } 148 WatchCallback( numOfBytes, ov );
149 } while ( mInitOK ); 149 }
150 150 }
151 removeAllWatches(); 151 } else {
152} 152 System::sleep( 10 );
153 153 }
154void FileWatcherWin32::handleAction( Watcher* watch, const std::string& filename, 154 } while ( mInitOK );
155 unsigned long action, std::string /*oldFilename*/ ) { 155
156 Action fwAction; 156 removeAllWatches();
157 157}
158 switch ( action ) { 158
159 case FILE_ACTION_RENAMED_OLD_NAME: 159void FileWatcherWin32::handleAction( Watcher* watch, const std::string& filename,
160 watch->OldFileName = filename; 160 unsigned long action, std::string /*oldFilename*/ ) {
161 return; 161 Action fwAction;
162 case FILE_ACTION_ADDED: 162
163 fwAction = Actions::Add; 163 switch ( action ) {
164 break; 164 case FILE_ACTION_RENAMED_OLD_NAME:
165 case FILE_ACTION_RENAMED_NEW_NAME: { 165 watch->OldFileName = filename;
166 fwAction = Actions::Moved; 166 return;
167 167 case FILE_ACTION_ADDED:
168 std::string fpath( watch->Directory + filename ); 168 fwAction = Actions::Add;
169 169 break;
170 // Update the directory path 170 case FILE_ACTION_RENAMED_NEW_NAME: {
171 if ( watch->Recursive && FileSystem::isDirectory( fpath ) ) { 171 fwAction = Actions::Moved;
172 // Update the new directory path 172
173 std::string opath( watch->Directory + watch->OldFileName ); 173 std::string fpath( watch->Directory + filename );
174 FileSystem::dirAddSlashAtEnd( opath ); 174
175 FileSystem::dirAddSlashAtEnd( fpath ); 175 // Update the directory path
176 176 if ( watch->Recursive && FileSystem::isDirectory( fpath ) ) {
177 for ( Watches::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) { 177 // Update the new directory path
178 if ( ( *it )->Watch->Directory == opath ) { 178 std::string opath( watch->Directory + watch->OldFileName );
179 ( *it )->Watch->Directory = fpath; 179 FileSystem::dirAddSlashAtEnd( opath );
180 180 FileSystem::dirAddSlashAtEnd( fpath );
181 break; 181
182 } 182 for ( Watches::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) {
183 } 183 if ( ( *it )->Watch->Directory == opath ) {
184 } 184 ( *it )->Watch->Directory = fpath;
185 185
186 std::string folderPath( static_cast<WatcherWin32*>( watch )->DirName ); 186 break;
187 std::string realFilename = filename; 187 }
188 std::size_t sepPos = filename.find_last_of( "/\\" ); 188 }
189 std::string oldFolderPath = 189 }
190 static_cast<WatcherWin32*>( watch )->DirName + 190
191 watch->OldFileName.substr( 0, watch->OldFileName.find_last_of( "/\\" ) ); 191 std::string folderPath( static_cast<WatcherWin32*>( watch )->DirName );
192 192 std::string realFilename = filename;
193 if ( sepPos != std::string::npos ) { 193 std::size_t sepPos = filename.find_last_of( "/\\" );
194 folderPath += filename.substr( 0, sepPos ); 194 std::string oldFolderPath =
195 realFilename = filename.substr( sepPos + 1 ); 195 static_cast<WatcherWin32*>( watch )->DirName +
196 } 196 watch->OldFileName.substr( 0, watch->OldFileName.find_last_of( "/\\" ) );
197 197
198 if ( folderPath == oldFolderPath ) { 198 if ( sepPos != std::string::npos ) {
199 watch->Listener->handleFileAction( 199 folderPath +=
200 watch->ID, folderPath, realFilename, fwAction, 200 filename.substr( 0, sepPos + 1 < filename.size() ? sepPos + 1 : sepPos );
201 FileSystem::fileNameFromPath( watch->OldFileName ) ); 201 realFilename = filename.substr( sepPos + 1 );
202 } else { 202 }
203 watch->Listener->handleFileAction( watch->ID, 203
204 static_cast<WatcherWin32*>( watch )->DirName, 204 if ( folderPath == oldFolderPath ) {
205 filename, fwAction, watch->OldFileName ); 205 watch->Listener->handleFileAction(
206 } 206 watch->ID, folderPath, realFilename, fwAction,
207 return; 207 FileSystem::fileNameFromPath( watch->OldFileName ) );
208 } 208 } else {
209 case FILE_ACTION_REMOVED: 209 watch->Listener->handleFileAction( watch->ID,
210 fwAction = Actions::Delete; 210 static_cast<WatcherWin32*>( watch )->DirName,
211 break; 211 filename, fwAction, watch->OldFileName );
212 case FILE_ACTION_MODIFIED: 212 }
213 fwAction = Actions::Modified; 213 return;
214 break; 214 }
215 default: 215 case FILE_ACTION_REMOVED:
216 return; 216 fwAction = Actions::Delete;
217 }; 217 break;
218 218 case FILE_ACTION_MODIFIED:
219 std::string folderPath( static_cast<WatcherWin32*>( watch )->DirName ); 219 fwAction = Actions::Modified;
220 std::string realFilename = filename; 220 break;
221 std::size_t sepPos = filename.find_last_of( "/\\" ); 221 default:
222 222 return;
223 if ( sepPos != std::string::npos ) { 223 };
224 folderPath += filename.substr( 0, sepPos ); 224
225 realFilename = filename.substr( sepPos + 1 ); 225 std::string folderPath( static_cast<WatcherWin32*>( watch )->DirName );
226 } 226 std::string realFilename = filename;
227 227 std::size_t sepPos = filename.find_last_of( "/\\" );
228 watch->Listener->handleFileAction( watch->ID, folderPath, realFilename, fwAction ); 228
229} 229 if ( sepPos != std::string::npos ) {
230 230 folderPath += filename.substr( 0, sepPos + 1 < filename.size() ? sepPos + 1 : sepPos );
231std::list<std::string> FileWatcherWin32::directories() { 231 realFilename = filename.substr( sepPos + 1 );
232 std::list<std::string> dirs; 232 }
233 233
234 Lock lock( mWatchesLock ); 234 FileSystem::dirAddSlashAtEnd( folderPath );
235 235
236 for ( Watches::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) { 236 watch->Listener->handleFileAction( watch->ID, folderPath, realFilename, fwAction );
237 dirs.push_back( std::string( ( *it )->Watch->DirName ) ); 237}
238 } 238
239 239std::vector<std::string> FileWatcherWin32::directories() {
240 return dirs; 240 std::vector<std::string> dirs;
241} 241
242 242 Lock lock( mWatchesLock );
243bool FileWatcherWin32::pathInWatches( const std::string& path ) { 243
244 Lock lock( mWatchesLock ); 244 dirs.reserve( mWatches.size() );
245 245
246 for ( Watches::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) { 246 for ( Watches::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) {
247 if ( ( *it )->Watch->DirName == path ) { 247 dirs.push_back( std::string( ( *it )->Watch->DirName ) );
248 return true; 248 }
249 } 249
250 } 250 return dirs;
251 251}
252 return false; 252
253} 253bool FileWatcherWin32::pathInWatches( const std::string& path ) {
254 254 Lock lock( mWatchesLock );
255} // namespace efsw 255
256 256 for ( Watches::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) {
257#endif 257 if ( ( *it )->Watch->DirName == path ) {
258 return true;
259 }
260 }
261
262 return false;
263}
264
265} // namespace efsw
266
267#endif