aboutsummaryrefslogtreecommitdiff
path: root/dep/efsw/src/efsw/FileWatcherInotify.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dep/efsw/src/efsw/FileWatcherInotify.cpp')
-rw-r--r--dep/efsw/src/efsw/FileWatcherInotify.cpp131
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 )
{