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 ../
fixedFilename = fixedFilename.GetCleanPath();
fixedFilename.ToOSCanonicalCase();
m_pFileMonitor->Watch(fixedFilename, this);
@@ -195,11 +195,15 @@ namespace FW
//--------
WatchID FileWatcherWin32::addWatch(const String& directory, FileWatchListener* watcher, bool recursive)
{
WatchID watchid = ++mLastWatchID;
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);
#ifdef WIN32_FW_USE_FINDFIRST_API
WatchID watchid = (unsigned long)fw.add( directory.m_string );
#else
WatchID watchid = ++mLastWatchID;
#endif
if(watch)
{
watch->mWatchid = watchid;
@@ -209,11 +213,10 @@ namespace FW
strcpy(watch->mDirName, directory.c_str());
}
mWatches.insert(std::make_pair(watchid, watch));
#ifdef WIN32_FW_USE_FINDFIRST_API
fw.add( directory.m_string );
#endif
mWatches.insert(std::make_pair(watchid, watch));
return watchid;
}
@@ -267,17 +270,22 @@ namespace FW
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)
{
case FileWatcherWin32_AltImpl::CHANGE_SIZE:
{
std::string old_name;
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() )
{
handleAction(mWatches[c + 1], new_name.c_str(), fni );
handleAction(iter->second, new_name.c_str(), fni );
}
break;
@@ -286,33 +294,34 @@ namespace FW
{
std::string old_name;
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() )
{
//changed from-to
if( !old_name.empty() )
{
handleAction(mWatches[c + 1], 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, old_name.c_str(), FILE_ACTION_RENAMED_OLD_NAME );
handleAction(iter->second, new_name.c_str(), FILE_ACTION_RENAMED_NEW_NAME );
}
else
{
handleAction(mWatches[c + 1], new_name.c_str(), fni );
handleAction(iter->second, new_name.c_str(), fni );
}
}
break;
}
case FileWatcherWin32_AltImpl::CHANGE_CREATION:
case FileWatcherWin32_AltImpl::CHANGE_LAST_WRITE:
case FileWatcherWin32_AltImpl::CHANGE_CREATION:
{
std::string old_name;
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() )
{
handleAction(mWatches[c + 1], new_name.c_str(), fni );
handleAction(iter->second, new_name.c_str(), fni );
}
break;
@@ -33,25 +33,29 @@
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
static int fw_types[] = { FILE_NOTIFY_CHANGE_CREATION, FILE_NOTIFY_CHANGE_SIZE, FILE_NOTIFY_CHANGE_FILE_NAME };
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
{
struct filedata
{
std::string fname;
LARGE_INTEGER fsize;
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;
fsize = s;
ftime = t;
fwritetime = tw;
}
};
std::vector< HANDLE > handles[3];
std::vector< HANDLE > handles[NUMTYPES];
std::vector< std::vector< filedata > > dir_contents;
void get_dir_contents( const std::string& path, std::vector< filedata >& contents )
@@ -73,9 +77,10 @@ namespace FW
fsize.LowPart = fd.nFileSizeLow;
fsize.HighPart = fd.nFileSizeHigh;
FILETIME ftime;
ftime.dwLowDateTime = fd.ftCreationTime.dwLowDateTime;
ftime.dwHighDateTime = fd.ftCreationTime.dwHighDateTime;
contents.push_back(filedata( fd.cFileName, fsize, ftime ));
ftime = fd.ftCreationTime;
FILETIME fwritetime;
fwritetime = fd.ftLastWriteTime;
contents.push_back(filedata( fd.cFileName, fsize, ftime, fwritetime ));
}
}
while(FindNextFileA(dir_lister, &fd) != 0);
@@ -86,7 +91,7 @@ namespace FW
~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 )
{
@@ -97,7 +102,7 @@ namespace FW
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
@@ -115,12 +120,12 @@ namespace FW
{
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] ) );
}
for( int c = 0; c < 3; ++c )
for( int c = 0; c < NUMTYPES; ++c )
{
if( handles[c][id] == INVALID_HANDLE_VALUE )
{
@@ -137,7 +142,7 @@ namespace FW
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);
@@ -166,7 +171,30 @@ namespace FW
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
case CHANGE_CREATION:
{
@@ -175,8 +203,8 @@ namespace FW
for( auto d = dir_contents[id].begin(); d != dir_contents[id].end(); ++d )
{
if( c->fname == d->fname &&
c->ftime.dwLowDateTime != d->ftime.dwLowDateTime ||
c->ftime.dwHighDateTime != d->ftime.dwHighDateTime
( c->ftime.dwLowDateTime != d->ftime.dwLowDateTime ||
c->ftime.dwHighDateTime != d->ftime.dwHighDateTime )
)
{
//make sure we 'neutralize' the event
@@ -272,7 +300,7 @@ namespace FW
{
if( c->fname == d->fname &&
( c->fsize.LowPart != d->fsize.LowPart ||
c->fsize.HighPart != d->fsize.HighPart )
c->fsize.HighPart != d->fsize.HighPart )
)
{
//make sure we 'neutralize' the event
@@ -316,7 +344,7 @@ namespace FW
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 it2 = dir_contents.begin();

0 comments on commit 485b968

Please sign in to comment.