diff options
Diffstat (limited to 'dep/efsw/src/efsw/FileWatcherInotify.cpp')
| -rw-r--r-- | dep/efsw/src/efsw/FileWatcherInotify.cpp | 97 |
1 files changed, 74 insertions, 23 deletions
diff --git a/dep/efsw/src/efsw/FileWatcherInotify.cpp b/dep/efsw/src/efsw/FileWatcherInotify.cpp index 29be12b6262..cb751ba88ee 100644 --- a/dep/efsw/src/efsw/FileWatcherInotify.cpp +++ b/dep/efsw/src/efsw/FileWatcherInotify.cpp @@ -7,6 +7,7 @@ #include <fcntl.h> #include <stdio.h> #include <string.h> +#include <sys/select.h> #include <sys/stat.h> #include <unistd.h> @@ -69,15 +70,17 @@ FileWatcherInotify::~FileWatcherInotify() { } WatchID FileWatcherInotify::addWatch( const std::string& directory, FileWatchListener* watcher, - bool recursive, const std::vector<WatcherOption>& ) { + bool recursive, const std::vector<WatcherOption>& options ) { if ( !mInitOK ) return Errors::Log::createLastError( Errors::Unspecified, directory ); Lock initLock( mInitLock ); - return addWatch( directory, watcher, recursive, NULL ); + bool syntheticEvents = getOptionValue( options, Options::LinuxProduceSyntheticEvents, 0 ) != 0; + return addWatch( directory, watcher, recursive, syntheticEvents, NULL ); } WatchID FileWatcherInotify::addWatch( const std::string& directory, FileWatchListener* watcher, - bool recursive, WatcherInotify* parent ) { + bool recursive, bool syntheticEvents, WatcherInotify* parent, + bool fromInternalEvent ) { std::string dir( directory ); FileSystem::dirAddSlashAtEnd( dir ); @@ -137,6 +140,7 @@ WatchID FileWatcherInotify::addWatch( const std::string& directory, FileWatchLis pWatch->Directory = dir; pWatch->Recursive = recursive; pWatch->Parent = parent; + pWatch->syntheticEvents = syntheticEvents; { Lock lock( mWatchesLock ); @@ -151,6 +155,18 @@ WatchID FileWatcherInotify::addWatch( const std::string& directory, FileWatchLis if ( pWatch->Recursive ) { std::map<std::string, FileInfo> files = FileSystem::filesInfoFromPath( pWatch->Directory ); + + if ( fromInternalEvent && parent != NULL && syntheticEvents ) { + for ( const auto& file : files ) { + if ( file.second.isRegularFile() || file.second.isDirectory() || + file.second.isLink() ) { + pWatch->Listener->handleFileAction( + pWatch->ID, pWatch->Directory, + FileSystem::fileNameFromPath( file.second.Filepath ), Actions::Add ); + } + } + } + std::map<std::string, FileInfo>::iterator it = files.begin(); for ( ; it != files.end(); ++it ) { @@ -160,7 +176,8 @@ WatchID FileWatcherInotify::addWatch( const std::string& directory, FileWatchLis const FileInfo& cfi = it->second; if ( cfi.isDirectory() && cfi.isReadable() ) { - addWatch( cfi.Filepath, watcher, recursive, pWatch ); + addWatch( cfi.Filepath, watcher, recursive, syntheticEvents, pWatch, + fromInternalEvent ); } } } @@ -244,7 +261,7 @@ void FileWatcherInotify::removeWatch( WatchID watchid ) { void FileWatcherInotify::watch() { if ( NULL == mThread ) { - mThread = new Thread( &FileWatcherInotify::run, this ); + mThread = new Thread( [this] { run(); } ); mThread->launch(); } } @@ -267,10 +284,10 @@ Watcher* FileWatcherInotify::watcherContainsDirectory( std::string dir ) { void FileWatcherInotify::run() { char* buff = new char[BUFF_SIZE]; memset( buff, 0, BUFF_SIZE ); - WatchMap::iterator wit; + WatcherInotify* curWatcher = NULL; WatcherInotify* currentMoveFrom = NULL; - u_int32_t currentMoveCookie = -1; + uint32_t currentMoveCookie = -1; bool lastWasMovedFrom = false; std::string prevOldFileName; @@ -294,16 +311,21 @@ void FileWatcherInotify::run() { struct inotify_event* pevent = (struct inotify_event*)&buff[i]; { + curWatcher = NULL; + { Lock lock( mWatchesLock ); - wit = mWatches.find( pevent->wd ); + auto wit = mWatches.find( pevent->wd ); + + if ( wit != mWatches.end() ) + curWatcher = wit->second; } - if ( wit != mWatches.end() ) { - handleAction( wit->second, (char*)pevent->name, pevent->mask ); + if ( curWatcher ) { + handleAction( curWatcher, (char*)pevent->name, pevent->mask ); - if ( ( pevent->mask & IN_MOVED_TO ) && wit->second == currentMoveFrom && + if ( ( pevent->mask & IN_MOVED_TO ) && curWatcher == currentMoveFrom && pevent->cookie == currentMoveCookie ) { /// make pair success currentMoveFrom = NULL; @@ -316,14 +338,30 @@ void FileWatcherInotify::run() { std::make_pair( currentMoveFrom, prevOldFileName ) ); } - currentMoveFrom = wit->second; + currentMoveFrom = curWatcher; currentMoveCookie = pevent->cookie; } else { /// Keep track of the IN_MOVED_FROM events to know /// if the IN_MOVED_TO event is also fired if ( currentMoveFrom ) { - mMovedOutsideWatches.push_back( - std::make_pair( currentMoveFrom, prevOldFileName ) ); + if ( std::find_if( mMovedOutsideWatches.begin(), + mMovedOutsideWatches.end(), + [currentMoveFrom]( + const std::pair<WatcherInotify*, + std::string>& moved ) { + return moved.first == currentMoveFrom; + } ) == mMovedOutsideWatches.end() ) { + mMovedOutsideWatches.push_back( + std::make_pair( currentMoveFrom, prevOldFileName ) ); + } else { + efDEBUG( "Info: Tried to add watch to the moved outside " + "watches but it was already there, Watch ID: %d - " + "Address: %p - Path: \"%s\" - prevOldFileName: " + "\"%s\"\n", + pevent->wd, currentMoveFrom, + currentMoveFrom->Directory.c_str(), + prevOldFileName.c_str() ); + } } currentMoveFrom = NULL; @@ -343,8 +381,18 @@ void FileWatcherInotify::run() { // Here means no event received // If last event is IN_MOVED_FROM, we assume no IN_MOVED_TO if ( currentMoveFrom ) { - mMovedOutsideWatches.push_back( - std::make_pair( currentMoveFrom, currentMoveFrom->OldFileName ) ); + if ( std::find_if( + mMovedOutsideWatches.begin(), mMovedOutsideWatches.end(), + [currentMoveFrom]( const std::pair<WatcherInotify*, std::string>& moved ) { + return moved.first == currentMoveFrom; + } ) == mMovedOutsideWatches.end() ) { + mMovedOutsideWatches.push_back( + std::make_pair( currentMoveFrom, currentMoveFrom->OldFileName ) ); + } else { + efDEBUG( "Warning: Tried to add watch to the moved outside " + "watches but it was already there, Watch Address: %p\n", + currentMoveFrom ); + } } currentMoveFrom = NULL; @@ -378,8 +426,8 @@ void FileWatcherInotify::run() { continue; } - Watcher* watch = ( *it ).first; - const std::string& oldFileName = ( *it ).second; + Watcher* watch = it->first; + const std::string& oldFileName = it->second; /// Check if the file move was a folder already being watched std::vector<Watcher*> eraseWatches; @@ -387,8 +435,8 @@ void FileWatcherInotify::run() { { Lock lock( mWatchesLock ); - for ( ; wit != mWatches.end(); ++wit ) { - Watcher* oldWatch = wit->second; + for ( auto wit : mWatches ) { + Watcher* oldWatch = wit.second; if ( oldWatch != watch && -1 != String::strStartsWith( watch->Directory + oldFileName + "/", @@ -448,8 +496,9 @@ void FileWatcherInotify::checkForNewWatcher( Watcher* watch, std::string fpath ) } if ( !found ) { - addWatch( fpath, watch->Listener, watch->Recursive, - static_cast<WatcherInotify*>( watch ) ); + WatcherInotify* iWatch = static_cast<WatcherInotify*>( watch ); + addWatch( fpath, watch->Listener, watch->Recursive, iWatch->syntheticEvents, + static_cast<WatcherInotify*>( watch ), true ); } } } @@ -464,7 +513,9 @@ void FileWatcherInotify::handleAction( Watcher* watch, const std::string& filena std::string fpath( watch->Directory + filename ); - if ( ( IN_CLOSE_WRITE & action ) || ( IN_MODIFY & action ) ) { + if ( IN_Q_OVERFLOW & action ) { + watch->Listener->handleMissedFileActions( watch->ID, watch->Directory ); + } else if ( ( IN_CLOSE_WRITE & action ) || ( IN_MODIFY & action ) ) { watch->Listener->handleFileAction( watch->ID, watch->Directory, filename, Actions::Modified ); } else if ( IN_MOVED_TO & action ) { |
