Skip to content
Permalink
Browse files

Merge pull request #36 from dougbinks/master

File watcher fixes.
  • Loading branch information...
dougbinks committed Oct 21, 2013
2 parents 4024b58 + 00e0676 commit 485b9686329e89f79f0be5c132ba056a34d349c6
@@ -75,6 +75,7 @@ void FileChangeNotifier::Watch( const FileSystemUtils::Path& filename, IFileChan
{ {
FileSystemUtils::Path fixedFilename = filename.DelimitersToOSDefault(); // Note this doesn't handle ../ FileSystemUtils::Path fixedFilename = filename.DelimitersToOSDefault(); // Note this doesn't handle ../


fixedFilename = fixedFilename.GetCleanPath();
fixedFilename.ToOSCanonicalCase(); fixedFilename.ToOSCanonicalCase();


m_pFileMonitor->Watch(fixedFilename, this); m_pFileMonitor->Watch(fixedFilename, this);
@@ -195,11 +195,15 @@ namespace FW
//-------- //--------
WatchID FileWatcherWin32::addWatch(const String& directory, FileWatchListener* watcher, bool recursive) WatchID FileWatcherWin32::addWatch(const String& directory, FileWatchListener* watcher, bool recursive)
{ {
WatchID watchid = ++mLastWatchID;

WatchStruct* watch = CreateWatch(directory.c_str(), recursive, WatchStruct* watch = CreateWatch(directory.c_str(), recursive,
FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_FILE_NAME); FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_FILE_NAME);


#ifdef WIN32_FW_USE_FINDFIRST_API
WatchID watchid = (unsigned long)fw.add( directory.m_string );
#else
WatchID watchid = ++mLastWatchID;
#endif

if(watch) if(watch)
{ {
watch->mWatchid = watchid; watch->mWatchid = watchid;
@@ -209,11 +213,10 @@ namespace FW
strcpy(watch->mDirName, directory.c_str()); strcpy(watch->mDirName, directory.c_str());
} }


mWatches.insert(std::make_pair(watchid, watch));


#ifdef WIN32_FW_USE_FINDFIRST_API mWatches.insert(std::make_pair(watchid, watch));
fw.add( directory.m_string );
#endif


return watchid; return watchid;
} }
@@ -267,17 +270,22 @@ namespace FW


for( size_t c = 0; c != events.size(); ++c ) for( size_t c = 0; c != events.size(); ++c )
{ {
WatchMap::iterator iter = mWatches.find(events[c].id);
if(iter == mWatches.end())
continue;


switch(events[c].ty) switch(events[c].ty)
{ {
case FileWatcherWin32_AltImpl::CHANGE_SIZE: case FileWatcherWin32_AltImpl::CHANGE_SIZE:
{ {
std::string old_name; std::string old_name;
DWORD fni; DWORD fni;
std::string new_name = fw.get_event_filename( mWatches[c + 1]->mDirName, events[c].id, events[c].ty, fni, old_name ); std::string new_name = fw.get_event_filename( iter->second->mDirName, events[c].id, events[c].ty, fni, old_name );


if( !new_name.empty() ) if( !new_name.empty() )
{ {
handleAction(mWatches[c + 1], new_name.c_str(), fni ); handleAction(iter->second, new_name.c_str(), fni );
} }


break; break;
@@ -286,33 +294,34 @@ namespace FW
{ {
std::string old_name; std::string old_name;
DWORD fni; DWORD fni;
std::string new_name = fw.get_event_filename( mWatches[c + 1]->mDirName, events[c].id, events[c].ty, fni, old_name ); std::string new_name = fw.get_event_filename( iter->second->mDirName, events[c].id, events[c].ty, fni, old_name );


if( !new_name.empty() ) if( !new_name.empty() )
{ {
//changed from-to //changed from-to
if( !old_name.empty() ) if( !old_name.empty() )
{ {
handleAction(mWatches[c + 1], old_name.c_str(), FILE_ACTION_RENAMED_OLD_NAME ); handleAction(iter->second, old_name.c_str(), FILE_ACTION_RENAMED_OLD_NAME );
handleAction(mWatches[c + 1], new_name.c_str(), FILE_ACTION_RENAMED_NEW_NAME ); handleAction(iter->second, new_name.c_str(), FILE_ACTION_RENAMED_NEW_NAME );
} }
else else
{ {
handleAction(mWatches[c + 1], new_name.c_str(), fni ); handleAction(iter->second, new_name.c_str(), fni );
} }
} }


break; break;
} }
case FileWatcherWin32_AltImpl::CHANGE_CREATION: case FileWatcherWin32_AltImpl::CHANGE_LAST_WRITE:
case FileWatcherWin32_AltImpl::CHANGE_CREATION:
{ {
std::string old_name; std::string old_name;
DWORD fni; DWORD fni;
std::string new_name = fw.get_event_filename( mWatches[c + 1]->mDirName, events[c].id, events[c].ty, fni, old_name ); std::string new_name = fw.get_event_filename( iter->second->mDirName, events[c].id, events[c].ty, fni, old_name );


if( !new_name.empty() ) if( !new_name.empty() )
{ {
handleAction(mWatches[c + 1], new_name.c_str(), fni ); handleAction(iter->second, new_name.c_str(), fni );
} }


break; break;
@@ -33,25 +33,29 @@
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#include <Windows.h> #include <Windows.h>


static int fw_types[] = { FILE_NOTIFY_CHANGE_CREATION, FILE_NOTIFY_CHANGE_SIZE, FILE_NOTIFY_CHANGE_FILE_NAME };
namespace FW namespace FW
{ {
const static int fw_types[] = { FILE_NOTIFY_CHANGE_LAST_WRITE, FILE_NOTIFY_CHANGE_CREATION, FILE_NOTIFY_CHANGE_SIZE, FILE_NOTIFY_CHANGE_FILE_NAME };
const static size_t NUMTYPES = sizeof(fw_types)/sizeof(int);

class FileWatcherWin32_AltImpl class FileWatcherWin32_AltImpl
{ {
struct filedata struct filedata
{ {
std::string fname; std::string fname;
LARGE_INTEGER fsize; LARGE_INTEGER fsize;
FILETIME ftime; FILETIME ftime;
filedata( std::string n = std::string(), LARGE_INTEGER s = LARGE_INTEGER(), FILETIME t = FILETIME() ) FILETIME fwritetime;
filedata( std::string n = std::string(), LARGE_INTEGER s = LARGE_INTEGER(), FILETIME t = FILETIME(), FILETIME tw = FILETIME())
{ {
fname = n; fname = n;
fsize = s; fsize = s;
ftime = t; ftime = t;
fwritetime = tw;
} }
}; };


std::vector< HANDLE > handles[3]; std::vector< HANDLE > handles[NUMTYPES];
std::vector< std::vector< filedata > > dir_contents; std::vector< std::vector< filedata > > dir_contents;


void get_dir_contents( const std::string& path, std::vector< filedata >& contents ) void get_dir_contents( const std::string& path, std::vector< filedata >& contents )
@@ -73,9 +77,10 @@ namespace FW
fsize.LowPart = fd.nFileSizeLow; fsize.LowPart = fd.nFileSizeLow;
fsize.HighPart = fd.nFileSizeHigh; fsize.HighPart = fd.nFileSizeHigh;
FILETIME ftime; FILETIME ftime;
ftime.dwLowDateTime = fd.ftCreationTime.dwLowDateTime; ftime = fd.ftCreationTime;
ftime.dwHighDateTime = fd.ftCreationTime.dwHighDateTime; FILETIME fwritetime;
contents.push_back(filedata( fd.cFileName, fsize, ftime )); fwritetime = fd.ftLastWriteTime;
contents.push_back(filedata( fd.cFileName, fsize, ftime, fwritetime ));
} }
} }
while(FindNextFileA(dir_lister, &fd) != 0); while(FindNextFileA(dir_lister, &fd) != 0);
@@ -86,7 +91,7 @@ namespace FW


~FileWatcherWin32_AltImpl() ~FileWatcherWin32_AltImpl()
{ {
for( int c = 0; c < 3; ++c ) for( int c = 0; c < NUMTYPES; ++c )
{ {
for( size_t d = 0; d != handles[c].size(); ++d ) for( size_t d = 0; d != handles[c].size(); ++d )
{ {
@@ -97,7 +102,7 @@ namespace FW


enum type enum type
{ {
CHANGE_CREATION = 0, CHANGE_SIZE, CHANGE_FILE_NAME, CHANGE_NONE CHANGE_LAST_WRITE = 0, CHANGE_CREATION, CHANGE_SIZE, CHANGE_FILE_NAME, CHANGE_NONE
}; };


struct fw_event struct fw_event
@@ -115,12 +120,12 @@ namespace FW
{ {
size_t id = handles[0].size(); size_t id = handles[0].size();


for( int c = 0; c < 3; ++c ) for( int c = 0; c < NUMTYPES; ++c )
{ {
handles[c].push_back( FindFirstChangeNotificationA( path.c_str(), false, fw_types[c] ) ); handles[c].push_back( FindFirstChangeNotificationA( path.c_str(), false, fw_types[c] ) );
} }


for( int c = 0; c < 3; ++c ) for( int c = 0; c < NUMTYPES; ++c )
{ {
if( handles[c][id] == INVALID_HANDLE_VALUE ) if( handles[c][id] == INVALID_HANDLE_VALUE )
{ {
@@ -137,7 +142,7 @@ namespace FW


bool watch(std::vector<fw_event>& ids) bool watch(std::vector<fw_event>& ids)
{ {
for( int c = 0; c < 3; ++c ) for( int c = 0; c < NUMTYPES; ++c )
{ {
DWORD status = WaitForMultipleObjects(handles[c].size(), &handles[c][0], false, 0); DWORD status = WaitForMultipleObjects(handles[c].size(), &handles[c][0], false, 0);


@@ -166,7 +171,30 @@ namespace FW


switch(ty) switch(ty)
{ {
//change in file creation time //change in file write time
//find the not matching write time
case CHANGE_LAST_WRITE:
{
for( auto c = contents.begin(); c != contents.end(); ++c )
{
for( auto d = dir_contents[id].begin(); d != dir_contents[id].end(); ++d )
{
if( c->fname == d->fname &&
( c->fwritetime.dwLowDateTime != d->fwritetime.dwLowDateTime ||
c->fwritetime.dwHighDateTime != d->fwritetime.dwHighDateTime )
)
{
//make sure we 'neutralize' the event
d->fwritetime.dwLowDateTime = c->fwritetime.dwLowDateTime;
d->fwritetime.dwHighDateTime = c->fwritetime.dwHighDateTime;
fni = FILE_ACTION_MODIFIED;
return d->fname;
}
}
}
break;
}
//change in file creation time
//find the not matching creation time //find the not matching creation time
case CHANGE_CREATION: case CHANGE_CREATION:
{ {
@@ -175,8 +203,8 @@ namespace FW
for( auto d = dir_contents[id].begin(); d != dir_contents[id].end(); ++d ) for( auto d = dir_contents[id].begin(); d != dir_contents[id].end(); ++d )
{ {
if( c->fname == d->fname && if( c->fname == d->fname &&
c->ftime.dwLowDateTime != d->ftime.dwLowDateTime || ( c->ftime.dwLowDateTime != d->ftime.dwLowDateTime ||
c->ftime.dwHighDateTime != d->ftime.dwHighDateTime c->ftime.dwHighDateTime != d->ftime.dwHighDateTime )
) )
{ {
//make sure we 'neutralize' the event //make sure we 'neutralize' the event
@@ -272,7 +300,7 @@ namespace FW
{ {
if( c->fname == d->fname && if( c->fname == d->fname &&
( c->fsize.LowPart != d->fsize.LowPart || ( c->fsize.LowPart != d->fsize.LowPart ||
c->fsize.HighPart != d->fsize.HighPart ) c->fsize.HighPart != d->fsize.HighPart )
) )
{ {
//make sure we 'neutralize' the event //make sure we 'neutralize' the event
@@ -316,7 +344,7 @@ namespace FW


void remove( size_t id ) void remove( size_t id )
{ {
for( int c = 0; c < 3; ++c ) for( int c = 0; c < NUMTYPES; ++c )
{ {
auto it = handles[c].begin(); auto it = handles[c].begin();
auto it2 = dir_contents.begin(); auto it2 = dir_contents.begin();

0 comments on commit 485b968

Please sign in to comment.
You can’t perform that action at this time.