diff options
Diffstat (limited to 'src/3rdParty/efsw/FileWatcherWin32.cpp')
-rw-r--r--[-rwxr-xr-x] | src/3rdParty/efsw/FileWatcherWin32.cpp | 524 |
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 | ||
9 | namespace efsw { | 9 | namespace efsw { |
10 | 10 | ||
11 | FileWatcherWin32::FileWatcherWin32( FileWatcher* parent ) : | 11 | FileWatcherWin32::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 | ||
18 | FileWatcherWin32::~FileWatcherWin32() { | 18 | FileWatcherWin32::~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 | } | |
32 | WatchID FileWatcherWin32::addWatch( const std::string& directory, FileWatchListener* watcher, | 32 | |
33 | bool recursive ) { | 33 | WatchID 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 ); | |
76 | void FileWatcherWin32::removeWatch( const std::string& directory ) { | 76 | |
77 | Lock lock( mWatchesLock ); | 77 | return watchid; |
78 | 78 | } | |
79 | Watches::iterator iter = mWatches.begin(); | 79 | |
80 | 80 | void 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; | |
89 | void FileWatcherWin32::removeWatch( WatchID watchid ) { | 89 | } |
90 | Lock lock( mWatchesLock ); | 90 | } |
91 | 91 | } | |
92 | Watches::iterator iter = mWatches.begin(); | 92 | |
93 | 93 | void 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; | |
103 | void FileWatcherWin32::removeWatch( WatcherStructWin32* watch ) { | 103 | } |
104 | Lock lock( mWatchesLock ); | 104 | } |
105 | 105 | } | |
106 | DestroyWatch( watch ); | 106 | |
107 | mWatches.erase( watch ); | 107 | void FileWatcherWin32::removeWatch( WatcherStructWin32* watch ) { |
108 | } | 108 | Lock lock( mWatchesLock ); |
109 | 109 | ||
110 | void 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 | } | 114 | void FileWatcherWin32::watch() { |
115 | } | 115 | if ( NULL == mThread ) { |
116 | 116 | mThread = new Thread( &FileWatcherWin32::run, this ); | |
117 | void FileWatcherWin32::removeAllWatches() { | 117 | mThread->launch(); |
118 | Lock lock( mWatchesLock ); | 118 | } |
119 | 119 | } | |
120 | Watches::iterator iter = mWatches.begin(); | 120 | |
121 | 121 | void 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 | } | |
129 | void FileWatcherWin32::run() { | 129 | |
130 | do { | 130 | mWatches.clear(); |
131 | if ( mInitOK && !mWatches.empty() ) { | 131 | } |
132 | DWORD numOfBytes = 0; | 132 | |
133 | OVERLAPPED* ov = NULL; | 133 | void 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 | } | |
154 | void 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: | 159 | void 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 ); | |
231 | std::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 | 239 | std::vector<std::string> FileWatcherWin32::directories() { | |
240 | return dirs; | 240 | std::vector<std::string> dirs; |
241 | } | 241 | |
242 | 242 | Lock lock( mWatchesLock ); | |
243 | bool 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 | } | 253 | bool 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 | ||