diff options
Diffstat (limited to 'dep/efsw/src/efsw/FileWatcherInotify.cpp')
-rw-r--r-- | dep/efsw/src/efsw/FileWatcherInotify.cpp | 131 |
1 files changed, 88 insertions, 43 deletions
diff --git a/dep/efsw/src/efsw/FileWatcherInotify.cpp b/dep/efsw/src/efsw/FileWatcherInotify.cpp index 19c20761663..71ae3bcd97d 100644 --- a/dep/efsw/src/efsw/FileWatcherInotify.cpp +++ b/dep/efsw/src/efsw/FileWatcherInotify.cpp @@ -18,6 +18,8 @@ #include <efsw/FileSystem.hpp> #include <efsw/System.hpp> #include <efsw/Debug.hpp> +#include <efsw/Lock.hpp> +#include <efsw/String.hpp> #define BUFF_SIZE ((sizeof(struct inotify_event)+FILENAME_MAX)*1024) @@ -145,9 +147,10 @@ WatchID FileWatcherInotify::addWatch( const std::string& directory, FileWatchLis pWatch->Recursive = recursive; pWatch->Parent = parent; - mWatchesLock.lock(); - mWatches.insert(std::make_pair(wd, pWatch)); - mWatchesLock.unlock(); + { + Lock lock( mWatchesLock ); + mWatches.insert(std::make_pair(wd, pWatch)); + } if ( NULL == pWatch->Parent ) { @@ -159,13 +162,13 @@ WatchID FileWatcherInotify::addWatch( const std::string& directory, FileWatchLis std::map<std::string, FileInfo> files = FileSystem::filesInfoFromPath( pWatch->Directory ); std::map<std::string, FileInfo>::iterator it = files.begin(); - for ( ; it != files.end(); it++ ) + for ( ; it != files.end(); ++it ) { - FileInfo fi = it->second; + const FileInfo& cfi = it->second; - if ( fi.isDirectory() && fi.isReadable() ) + if ( cfi.isDirectory() && cfi.isReadable() ) { - addWatch( fi.Filepath, watcher, recursive, pWatch ); + addWatch( cfi.Filepath, watcher, recursive, pWatch ); } } } @@ -194,7 +197,7 @@ void FileWatcherInotify::removeWatchLocked(WatchID watchid) } } - for ( std::list<WatchID>::iterator eit = eraseWatches.begin(); eit != eraseWatches.end(); eit++ ) + for ( std::list<WatchID>::iterator eit = eraseWatches.begin(); eit != eraseWatches.end(); ++eit ) { removeWatch( *eit ); } @@ -228,7 +231,7 @@ void FileWatcherInotify::removeWatchLocked(WatchID watchid) void FileWatcherInotify::removeWatch(const std::string& directory) { - mWatchesLock.lock(); + Lock lock( mWatchesLock ); WatchMap::iterator iter = mWatches.begin(); @@ -251,7 +254,7 @@ void FileWatcherInotify::removeWatch(const std::string& directory) } } - for ( std::list<WatchID>::iterator eit = eraseWatches.begin(); eit != eraseWatches.end(); eit++ ) + for ( std::list<WatchID>::iterator eit = eraseWatches.begin(); eit != eraseWatches.end(); ++eit ) { removeWatchLocked( *eit ); } @@ -285,26 +288,20 @@ void FileWatcherInotify::removeWatch(const std::string& directory) break; } } - - mWatchesLock.unlock(); } void FileWatcherInotify::removeWatch( WatchID watchid ) { - mWatchesLock.lock(); + Lock lock( mWatchesLock ); WatchMap::iterator iter = mWatches.find( watchid ); if( iter == mWatches.end() ) { - mWatchesLock.unlock(); - return; } removeWatchLocked( watchid ); - - mWatchesLock.unlock(); } void FileWatcherInotify::watch() @@ -316,6 +313,25 @@ void FileWatcherInotify::watch() } } +Watcher * FileWatcherInotify::watcherContainsDirectory( std::string dir ) +{ + FileSystem::dirRemoveSlashAtEnd( dir ); + std::string watcherPath = FileSystem::pathRemoveFileName( dir ); + FileSystem::dirAddSlashAtEnd( watcherPath ); + + for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) + { + Watcher * watcher = it->second; + + if ( watcher->Directory == watcherPath ) + { + return watcher; + } + } + + return NULL; +} + void FileWatcherInotify::run() { static char buff[BUFF_SIZE] = {0}; @@ -333,48 +349,79 @@ void FileWatcherInotify::run() if( select (FD_SETSIZE, &rfds, NULL, NULL, &timeout) > 0 ) { - ssize_t len, i = 0; + ssize_t len; len = read (mFD, buff, BUFF_SIZE); if (len != -1) { + ssize_t i = 0; + while (i < len) { struct inotify_event *pevent = (struct inotify_event *)&buff[i]; - mWatchesLock.lock(); - - wit = mWatches.find( pevent->wd ); - - if ( wit != mWatches.end() ) { - handleAction(wit->second, pevent->name, pevent->mask); + Lock lock( mWatchesLock ); + + wit = mWatches.find( pevent->wd ); - /// Keep track of the IN_MOVED_FROM events to known if the IN_MOVED_TO event is also fired - if ( !wit->second->OldFileName.empty() ) + if ( wit != mWatches.end() ) { - movedOutsideWatches.push_back( wit->second ); + handleAction(wit->second, pevent->name, pevent->mask); + + /// Keep track of the IN_MOVED_FROM events to know if the IN_MOVED_TO event is also fired + if ( !wit->second->OldFileName.empty() ) + { + movedOutsideWatches.push_back( wit->second ); + } } } - mWatchesLock.unlock(); - i += sizeof(struct inotify_event) + pevent->len; } if ( !movedOutsideWatches.empty() ) { /// In case that the IN_MOVED_TO is never fired means that the file was moved to other folder - for ( std::list<WatcherInotify*>::iterator it = movedOutsideWatches.begin(); it != movedOutsideWatches.end(); it++ ) + for ( std::list<WatcherInotify*>::iterator it = movedOutsideWatches.begin(); it != movedOutsideWatches.end(); ++it ) { - if ( !(*it)->OldFileName.empty() ) + Watcher * watch = (*it); + + if ( !watch->OldFileName.empty() ) { - /// So we send a IN_DELETE event for files that where moved outside of our scope - handleAction( *it, (*it)->OldFileName, IN_DELETE ); + /// Check if the file move was a folder already being watched + std::list<Watcher*> eraseWatches; + + for(; wit != mWatches.end(); ++wit) + { + Watcher * oldWatch = wit->second; + + if ( oldWatch != watch && + -1 != String::strStartsWith( watch->Directory + watch->OldFileName + "/", oldWatch->Directory ) ) + { + eraseWatches.push_back( oldWatch ); + } + } + + /// Remove invalid watches + eraseWatches.sort(); + + for ( std::list<Watcher*>::reverse_iterator eit = eraseWatches.rbegin(); eit != eraseWatches.rend(); ++eit ) + { + Watcher * rmWatch = *eit; + + /// Create Delete event for removed watches that have been moved too + if ( Watcher * cntWatch = watcherContainsDirectory( rmWatch->Directory ) ) + { + handleAction( cntWatch, FileSystem::fileNameFromPath( rmWatch->Directory ), IN_DELETE ); + } + + removeWatch( rmWatch->ID ); + } /// Remove the OldFileName - (*it)->OldFileName = ""; + watch->OldFileName = ""; } } @@ -395,7 +442,7 @@ void FileWatcherInotify::checkForNewWatcher( Watcher* watch, std::string fpath ) bool found = false; /// First check if exists - for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); it++ ) + for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) { if ( it->second->Directory == fpath ) { @@ -411,7 +458,7 @@ void FileWatcherInotify::checkForNewWatcher( Watcher* watch, std::string fpath ) } } -void FileWatcherInotify::handleAction( Watcher* watch, const std::string& filename, unsigned long action, std::string oldFilename ) +void FileWatcherInotify::handleAction( Watcher* watch, const std::string& filename, unsigned long action, std::string ) { if ( !watch || !watch->Listener ) { @@ -447,7 +494,7 @@ void FileWatcherInotify::handleAction( Watcher* watch, const std::string& filena FileSystem::dirAddSlashAtEnd( opath ); FileSystem::dirAddSlashAtEnd( fpath ); - for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); it++ ) + for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) { if ( it->second->Directory == opath && it->second->DirInfo.Inode == FileInfo( opath ).Inode ) { @@ -480,7 +527,7 @@ void FileWatcherInotify::handleAction( Watcher* watch, const std::string& filena /// If the file erased is a directory and recursive is enabled, removes the directory erased if ( watch->Recursive ) { - for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); it++ ) + for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) { if ( it->second->Directory == fpath ) { @@ -496,17 +543,15 @@ std::list<std::string> FileWatcherInotify::directories() { std::list<std::string> dirs; - mWatchesLock.lock(); + Lock lock( mWatchesLock ); WatchMap::iterator it = mRealWatches.begin(); - for ( ; it != mRealWatches.end(); it++ ) + for ( ; it != mRealWatches.end(); ++it ) { dirs.push_back( it->second->Directory ); } - mWatchesLock.unlock(); - return dirs; } @@ -515,7 +560,7 @@ bool FileWatcherInotify::pathInWatches( const std::string& path ) /// Search in the real watches, since it must allow adding a watch already watched as a subdir WatchMap::iterator it = mRealWatches.begin(); - for ( ; it != mRealWatches.end(); it++ ) + for ( ; it != mRealWatches.end(); ++it ) { if ( it->second->Directory == path ) { |