Skip to content

Commit

Permalink
move collection of file change events into FileChangeEvent module
Browse files Browse the repository at this point in the history
  • Loading branch information
jjallaire committed Aug 18, 2011
1 parent 7be5796 commit b7839a1
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 143 deletions.
21 changes: 18 additions & 3 deletions src/cpp/core/include/core/FileInfo.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,27 @@ class FileInfo
std::time_t lastWriteTime_;
};

inline bool compareFileInfoPaths(const FileInfo& fileInfo1,
const FileInfo& fileInfo2)
inline int fileInfoPathCompare(const FileInfo& a, const FileInfo& b)
{
return fileInfo1.absolutePath() < fileInfo2.absolutePath();
// use stcoll because that is what alphasort (comp function passed to
// scandir) uses for its sorting)
int result = ::strcoll(a.absolutePath().c_str(), b.absolutePath().c_str());

if (result != 0)
return result;

if (a.isDirectory() == b.isDirectory())
return 0;

return a.isDirectory() ? -1 : 1;
}

inline bool fileInfoPathLessThan(const FileInfo& a, const FileInfo& b)
{
return fileInfoPathCompare(a, b) < 0;
}


inline bool fileInfoHasPath(const FileInfo& fileInfo, const std::string& path)
{
return fileInfo.absolutePath() == path;
Expand Down
86 changes: 86 additions & 0 deletions src/cpp/core/include/core/system/FileChangeEvent.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@

#include <string>
#include <iostream>
#include <vector>

#include <boost/function.hpp>

#include <core/FileInfo.hpp>

Expand Down Expand Up @@ -82,6 +85,89 @@ inline std::ostream& operator << (std::ostream& ostr,

return ostr;
}

template<typename PreviousIterator, typename CurrentIterator>
void collectFileChangeEvents(PreviousIterator prevBegin,
PreviousIterator prevEnd,
CurrentIterator currBegin,
CurrentIterator currEnd,
const boost::function<bool(const FileInfo&)>& filter,
std::vector<FileChangeEvent>* pEvents)
{
// sort the ranges
std::vector<FileInfo> prev;
std::copy(prevBegin, prevEnd, std::back_inserter(prev));
std::sort(prev.begin(), prev.end(), fileInfoPathLessThan);
std::vector<FileInfo> curr;
std::copy(currBegin, currEnd, std::back_inserter(curr));
std::sort(curr.begin(), curr.end(), fileInfoPathLessThan);

// initalize the iterators
std::vector<FileInfo>::iterator prevIt = prev.begin();
std::vector<FileInfo>::iterator currIt = curr.begin();

FileInfo noFile;
while (prevIt != prev.end() || currIt != curr.end())
{
const FileInfo& prevFile = prevIt != prev.end() ? *prevIt : noFile;
const FileInfo& currFile = currIt != curr.end() ? *currIt : noFile;

int comp;
if (prevFile.empty())
comp = 1;
else if (currFile.empty())
comp = -1;
else
comp = fileInfoPathCompare(prevFile, currFile);

if (comp == 0)
{
if (currFile.lastWriteTime() != prevFile.lastWriteTime())
{
if (filter && filter(currFile))
{
pEvents->push_back(FileChangeEvent(FileChangeEvent::FileModified,
currFile));
}
}
prevIt++;
currIt++;
}
else if (comp < 0)
{
if (filter && filter(prevFile))
{
pEvents->push_back(FileChangeEvent(FileChangeEvent::FileRemoved,
prevFile));
}
prevIt++;
}
else // comp > 1
{
if (filter && filter(currFile))
{
pEvents->push_back(FileChangeEvent(FileChangeEvent::FileAdded,
currFile));
}
currIt++;
}
}
}

template<typename PreviousIterator, typename CurrentIterator>
void collectFileChangeEvents(PreviousIterator prevBegin,
PreviousIterator prevEnd,
CurrentIterator currBegin,
CurrentIterator currEnd,
std::vector<FileChangeEvent>* pEvents)
{
collectFileChangeEvents(prevBegin,
prevEnd,
currBegin,
currEnd,
boost::function<bool(const FileInfo&)>(),
pEvents);
}

} // namespace system
} // namespace core
Expand Down
75 changes: 12 additions & 63 deletions src/cpp/core/system/DirectoryMonitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@

#include <algorithm>

#include <boost/bind.hpp>

#include <core/Log.hpp>
#include <core/Error.hpp>
#include <core/FilePath.hpp>
Expand Down Expand Up @@ -43,7 +45,7 @@ Error fileListing(const FilePath& filePath, std::vector<FileInfo>* pFiles)
}

// sort the listing
std::sort(pFiles->begin(), pFiles->end(), compareFileInfoPaths);
std::sort(pFiles->begin(), pFiles->end(), fileInfoPathLessThan);

return Success();
}
Expand Down Expand Up @@ -132,68 +134,15 @@ Error DirectoryMonitor::checkForEvents(std::vector<FileChangeEvent>* pEvents)
if (error)
return error ;

// find removed files
std::vector<FileInfo> removedFiles ;
std::set_difference(pImpl_->previousListing.begin(),
pImpl_->previousListing.end(),
currentListing.begin(),
currentListing.end(),
std::back_inserter(removedFiles),
compareFileInfoPaths);
// enque removed events
for (std::vector<FileInfo>::const_iterator it = removedFiles.begin();
it != removedFiles.end();
++it)
{
if (shouldFireEventForFile(*it))
pEvents->push_back(FileChangeEvent(FileChangeEvent::FileRemoved, *it));
}

// find added files
std::vector<FileInfo> addedFiles;
std::set_difference(currentListing.begin(),
currentListing.end(),
pImpl_->previousListing.begin(),
pImpl_->previousListing.end(),
std::back_inserter(addedFiles),
compareFileInfoPaths);

// enque add events
for (std::vector<FileInfo>::const_iterator it = addedFiles.begin();
it != addedFiles.end();
++it)
{
if (shouldFireEventForFile(*it))
pEvents->push_back(FileChangeEvent(FileChangeEvent::FileAdded, *it));
}

// get the subset of files in both lists and then compare for modification
std::vector<FileInfo> commonCurrentFiles, commonPrevFiles;
std::set_intersection(currentListing.begin(),
currentListing.end(),
pImpl_->previousListing.begin(),
pImpl_->previousListing.end(),
std::back_inserter(commonCurrentFiles),
compareFileInfoPaths);
std::set_intersection(pImpl_->previousListing.begin(),
pImpl_->previousListing.end(),
currentListing.begin(),
currentListing.end(),
std::back_inserter(commonPrevFiles),
compareFileInfoPaths);
// enque modified events
for (std::size_t i=0; i<commonCurrentFiles.size(); i++)
{
if (commonCurrentFiles[i].lastWriteTime() !=
commonPrevFiles[i].lastWriteTime())
{
if (shouldFireEventForFile(commonCurrentFiles[i]))
{
pEvents->push_back(FileChangeEvent(FileChangeEvent::FileModified,
commonCurrentFiles[i]));
}
}
}
// collect events
collectFileChangeEvents(pImpl_->previousListing.begin(),
pImpl_->previousListing.end(),
currentListing.begin(),
currentListing.end(),
boost::bind(&DirectoryMonitor::shouldFireEventForFile,
this,
_1),
pEvents);

// update previous listing
pImpl_->previousListing = currentListing;
Expand Down
77 changes: 0 additions & 77 deletions src/cpp/core/system/file_monitor/MacFileMonitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,83 +129,6 @@ class FileEventContext : boost::noncopyable
Callbacks::FilesChanged onFilesChanged;
};

inline int fileInfoPathCompare(const FileInfo& a, const FileInfo& b)
{
// use stcoll because that is what alphasort (comp function passed to
// scandir) uses for its sorting)
int result = ::strcoll(a.absolutePath().c_str(), b.absolutePath().c_str());

if (result != 0)
return result;

if (a.isDirectory() == b.isDirectory())
return 0;

return a.isDirectory() ? -1 : 1;
}

inline bool fileInfoPathLessThan(const FileInfo& a, const FileInfo& b)
{
return fileInfoPathCompare(a, b) < 0;
}

template<typename PreviousIterator, typename CurrentIterator>
void collectFileChangeEvents(PreviousIterator prevBegin,
PreviousIterator prevEnd,
CurrentIterator currBegin,
CurrentIterator currEnd,
std::vector<FileChangeEvent>* pEvents)
{
// sort the ranges
std::vector<FileInfo> prev;
std::copy(prevBegin, prevEnd, std::back_inserter(prev));
std::sort(prev.begin(), prev.end(), fileInfoPathLessThan);
std::vector<FileInfo> curr;
std::copy(currBegin, currEnd, std::back_inserter(curr));
std::sort(curr.begin(), curr.end(), fileInfoPathLessThan);

// initalize the iterators
std::vector<FileInfo>::iterator prevIt = prev.begin();
std::vector<FileInfo>::iterator currIt = curr.begin();

FileInfo noFile;
while (prevIt != prev.end() || currIt != curr.end())
{
const FileInfo& prevFile = prevIt != prev.end() ? *prevIt : noFile;
const FileInfo& currFile = currIt != curr.end() ? *currIt : noFile;

int comp;
if (prevFile.empty())
comp = 1;
else if (currFile.empty())
comp = -1;
else
comp = fileInfoPathCompare(prevFile, currFile);

if (comp == 0)
{
if (currFile.lastWriteTime() != prevFile.lastWriteTime())
{
pEvents->push_back(FileChangeEvent(FileChangeEvent::FileModified,
currFile));
}
prevIt++;
currIt++;
}
else if (comp < 0)
{
pEvents->push_back(FileChangeEvent(FileChangeEvent::FileRemoved,
prevFile));
prevIt++;
}
else // comp > 1
{
pEvents->push_back(FileChangeEvent(FileChangeEvent::FileAdded,
currFile));
currIt++;
}
}
}

void addEvent(FileChangeEvent::Type type,
const FileInfo& fileInfo,
Expand Down

0 comments on commit b7839a1

Please sign in to comment.