diff options
author | Stefan Radomski <radomski@tk.informatik.tu-darmstadt.de> | 2013-03-06 18:23:17 (GMT) |
---|---|---|
committer | Stefan Radomski <radomski@tk.informatik.tu-darmstadt.de> | 2013-03-06 18:23:17 (GMT) |
commit | e1a31a44c946d58a1b4654e5daa2d10d9c6f881d (patch) | |
tree | 7ce434b9bfb30c2de74cfe1f226c2ceda4ee8178 /src/uscxml/plugins/invoker/filesystem | |
parent | 8c4977361f9e7998da298b9648f3ad4be5e772ff (diff) | |
download | uscxml-e1a31a44c946d58a1b4654e5daa2d10d9c6f881d.zip uscxml-e1a31a44c946d58a1b4654e5daa2d10d9c6f881d.tar.gz uscxml-e1a31a44c946d58a1b4654e5daa2d10d9c6f881d.tar.bz2 |
Changed directory monitor to polling behaviour :(
Diffstat (limited to 'src/uscxml/plugins/invoker/filesystem')
4 files changed, 359 insertions, 188 deletions
diff --git a/src/uscxml/plugins/invoker/filesystem/dirmon/DirMonInvoker.cpp b/src/uscxml/plugins/invoker/filesystem/dirmon/DirMonInvoker.cpp index 37be3e0..675135a 100644 --- a/src/uscxml/plugins/invoker/filesystem/dirmon/DirMonInvoker.cpp +++ b/src/uscxml/plugins/invoker/filesystem/dirmon/DirMonInvoker.cpp @@ -25,10 +25,10 @@ bool connect(pluma::Host& host) { #endif DirMonInvoker::DirMonInvoker() : - _reportExisting(true), - _reportHidden(false), - _recurse(false), - _thread(NULL) { + _reportExisting(true), + _reportHidden(false), + _recurse(false), + _thread(NULL) { } DirMonInvoker::~DirMonInvoker() { @@ -55,222 +55,329 @@ void DirMonInvoker::cancel(const std::string sendId) { } void DirMonInvoker::invoke(const InvokeRequest& req) { - if (req.params.find("dir") != req.params.end() && boost::iequals(req.params.find("reportexisting")->second, "false")) + if (req.params.find("dir") == req.params.end()) { + LOG(ERROR) << "No dir param given"; + return; + } + + if (boost::iequals(req.params.find("reportexisting")->second, "false")) _reportExisting = false; - if (req.params.find("recurse") != req.params.end() && boost::iequals(req.params.find("recurse")->second, "true")) + if (req.params.find("recurse") != req.params.end() && + boost::iequals(req.params.find("recurse")->second, "true")) _recurse = true; - if (req.params.find("reporthidden") != req.params.end() && boost::iequals(req.params.find("reporthidden")->second, "true")) + if (req.params.find("reporthidden") != req.params.end() && + boost::iequals(req.params.find("reporthidden")->second, "true")) _reportHidden = true; - - std::string suffixList; - if (req.params.find("suffix") != req.params.end()) { - suffixList = req.params.find("suffix")->second; - } else if (req.params.find("suffixes") != req.params.end()) { - suffixList = req.params.find("suffixes")->second; - } - - if (suffixList.size() > 0) { - // seperate path into components - std::stringstream ss(suffixList); - std::string item; - while(std::getline(ss, item, ' ')) { - if (item.length() == 0) - continue; - _suffixes.insert(item); - } - } - + + std::string suffixList; + if (req.params.find("suffix") != req.params.end()) { + suffixList = req.params.find("suffix")->second; + } else if (req.params.find("suffixes") != req.params.end()) { + suffixList = req.params.find("suffixes")->second; + } + + if (suffixList.size() > 0) { + // seperate path into components + std::stringstream ss(suffixList); + std::string item; + while(std::getline(ss, item, ' ')) { + if (item.length() == 0) + continue; + _suffixes.insert(item); + } + } + std::multimap<std::string, std::string>::const_iterator dirIter = req.params.find("dir"); while(dirIter != req.params.upper_bound("dir")) { URL url(dirIter->second); if (!_interpreter->toAbsoluteURI(url) || !boost::iequals(url.scheme(), "file")) { LOG(ERROR) << "Given directory '" << dirIter->second << "' cannot be transformed to absolute path"; } else { - _watchIds.insert(std::make_pair(url.path(), _fileWatcher.addWatch(url.path(), this, _recurse))); + _dir = url.path(); } - dirIter++; + break; } + + _watcher = new DirectoryWatch(_dir, _recurse); + _watcher->addMonitor(this); + _watcher->updateEntries(true); + _isRunning = true; _thread = new tthread::thread(DirMonInvoker::run, this); } void DirMonInvoker::run(void* instance) { - if (((DirMonInvoker*)instance)->_reportExisting) - ((DirMonInvoker*)instance)->reportExisting(); - - while(((DirMonInvoker*)instance)->_isRunning) - ((DirMonInvoker*)instance)->_fileWatcher.update(); + while(((DirMonInvoker*)instance)->_isRunning) { + ((DirMonInvoker*)instance)->_watcher->updateEntries(); + tthread::this_thread::sleep_for(tthread::chrono::milliseconds(20)); + } } -void DirMonInvoker::reportExisting() { - std::multimap<std::string, FW::WatchID>::iterator watchIter = _watchIds.begin(); - while(watchIter != _watchIds.end()) { - reportExistingIn(watchIter->first, watchIter->second); - watchIter++; +void DirMonInvoker::handleChanges(DirectoryWatch::Action action, const std::string reportedDir, const std::string reportedFilename, struct stat fileStat) { + +// std::cout << action << " on " << reportedFilename << std::endl; + + std::string path; // complete path to the file including filename + std::string relPath; // path relative to monitored directory including filename + std::string dir; // the name of the directory we monitor + std::string relDir; // the directory from dir to the actual directory where we found a file + std::string basename; // filename including suffix + std::string strippedName; // filename without the suffix + std::string extension; // the extension + + dir = reportedDir; + + path = dir + reportedFilename; + boost::algorithm::replace_all(path, "\\", "/"); + boost::algorithm::replace_all(path, "//", "/"); + + assert(boost::algorithm::starts_with(path, dir)); + relPath = path.substr(dir.length()); + assert(boost::equal(path, dir + relPath)); + + size_t lastSep; + if ((lastSep = path.find_last_of(PATH_SEPERATOR)) != std::string::npos) { + lastSep++; + basename = path.substr(lastSep, path.length() - lastSep); + } else { + assert(false); } -} + assert(boost::algorithm::ends_with(relPath, basename)); + + // extension is the suffix and strippedName the basename without the suffix + size_t lastDot; + if ((lastDot = basename.find_last_of(".")) != std::string::npos) { + if (lastDot == 0) { + // hidden file + strippedName = basename; + } else { + extension = basename.substr(lastDot + 1); + strippedName = basename.substr(0, lastDot); + } + } else { + strippedName = basename; + } + + relDir = relPath.substr(0, relPath.length() - basename.length()); + assert(boost::equal(path, dir + relDir + basename)); -void DirMonInvoker::handleFileAction(FW::WatchID watchid, const FW::String& dir, const FW::String& filename, FW::Action action) { - - std::string path; - if (!boost::algorithm::starts_with(filename, dir)) { - path = dir + filename; - } else { - path = filename; - } - - if (_suffixes.size() > 0) { - bool validSuffix = false; - std::set<std::string>::iterator suffixIter = _suffixes.begin(); - while(suffixIter != _suffixes.end()) { - if (boost::algorithm::ends_with(path, *suffixIter)) { - validSuffix = true; - break; - } - suffixIter++; - } - if (!validSuffix) - return; - } + // return if this is a hidden file + if (boost::algorithm::starts_with(basename, ".") && !_reportHidden) + return; + + // ilter suffixes + if (_suffixes.size() > 0) { + bool validSuffix = false; + std::set<std::string>::iterator suffixIter = _suffixes.begin(); + while(suffixIter != _suffixes.end()) { + if (boost::algorithm::ends_with(path, *suffixIter)) { + validSuffix = true; + break; + } + suffixIter++; + } + if (!validSuffix) + return; + } Event event; event.invokeid = _invokeId; + switch (action) { - case FW::Actions::Existing: + case DirectoryWatch::EXISTING: event.name = "file.existing"; break; - case FW::Actions::Add: + case DirectoryWatch::ADDED: event.name = "file.added"; break; - case FW::Actions::Delete: + case DirectoryWatch::DELETED: event.name = "file.deleted"; break; - case FW::Actions::Modified: + case DirectoryWatch::MODIFIED: event.name = "file.modified"; break; default: break; } - // basename is the filename with suffix - std::string basename; - size_t lastSep; - if ((lastSep = path.find_last_of(PATH_SEPERATOR)) != std::string::npos) { - lastSep++; - basename = path.substr(lastSep, path.length() - lastSep); - event.data.compound["file"].compound["name"] = Data(basename, Data::VERBATIM); - } - - // return if this is a hidden file - if (boost::algorithm::starts_with(basename, ".") && !_reportHidden) - return; - - struct stat fileStat; - if (action != FW::Actions::Delete) { - if (stat(path.c_str(), &fileStat) != 0) { - LOG(ERROR) << "Error with stat on directory entry " << path << ": " << strerror(errno); - return; - } else { - event.data.compound["file"].compound["mtime"] = toStr(fileStat.st_mtime); - event.data.compound["file"].compound["ctime"] = toStr(fileStat.st_ctime); - event.data.compound["file"].compound["atime"] = toStr(fileStat.st_atime); - event.data.compound["file"].compound["size"] = toStr(fileStat.st_size); - } - } - - // extension is the suffix and strippedName the basename without the suffix - size_t lastDot; - if ((lastDot = basename.find_last_of(".")) != std::string::npos) { - std::string extension = basename.substr(lastDot + 1); - event.data.compound["file"].compound["extension"] = Data(extension, Data::VERBATIM); - std::string strippedName = basename.substr(0, lastDot); - event.data.compound["file"].compound["strippedName"] = Data(strippedName, Data::VERBATIM); - } - - // relpath is the path to the file relative to the dir - if (boost::algorithm::starts_with(filename, dir)) { - std::string relPath = filename.substr(dir.length()); - event.data.compound["file"].compound["relPath"] = Data(relPath, Data::VERBATIM); - - // relDir is the relpath without the basename - if ((lastSep = relPath.find_last_of(PATH_SEPERATOR)) != std::string::npos) { - lastSep++; - std::string relDir = relPath.substr(0, lastSep); - event.data.compound["file"].compound["relDir"] = Data(relDir, Data::VERBATIM); - } + if (action != DirectoryWatch::DELETED) { + event.data.compound["file"].compound["mtime"] = toStr(fileStat.st_mtime); + event.data.compound["file"].compound["ctime"] = toStr(fileStat.st_ctime); + event.data.compound["file"].compound["atime"] = toStr(fileStat.st_atime); + event.data.compound["file"].compound["size"] = toStr(fileStat.st_size); } + event.data.compound["file"].compound["name"] = Data(basename, Data::VERBATIM); + event.data.compound["file"].compound["extension"] = Data(extension, Data::VERBATIM); + event.data.compound["file"].compound["strippedName"] = Data(strippedName, Data::VERBATIM); + event.data.compound["file"].compound["relPath"] = Data(relPath, Data::VERBATIM); + event.data.compound["file"].compound["relDir"] = Data(relDir, Data::VERBATIM); event.data.compound["file"].compound["path"] = Data(path, Data::VERBATIM); event.data.compound["file"].compound["dir"] = Data(dir, Data::VERBATIM); returnEvent(event); } -bool DirMonInvoker::filter(const std::string filename) { - return true; +void DirectoryWatch::reportAsDeleted() { + std::map<std::string, struct stat>::iterator fileIter = _knownEntries.begin(); + while(fileIter != _knownEntries.end()) { + if (fileIter->second.st_mode & S_IFDIR) { + _knownDirs[fileIter->first]->reportAsDeleted(); + delete _knownDirs[fileIter->first]; + _knownDirs.erase(fileIter->first); + } else { + _monitors_t::iterator monIter = _monitors.begin(); + while(monIter != _monitors.end()) { + (*monIter)->handleChanges(DELETED, _dir, _relDir + PATH_SEPERATOR + fileIter->first, fileIter->second); + monIter++; + } + } + _knownEntries.erase(fileIter->first); + fileIter++; + } + assert(_knownDirs.size() == 0); + assert(_knownEntries.size() == 0); } -void DirMonInvoker::reportExistingIn(const std::string dir, FW::WatchID watchid) { -#ifndef WIN32 - DIR *dp; - dp = opendir(dir.c_str()); - if (dp == NULL) { - LOG(ERROR) << "Error opening directory " << dir << ": " << strerror(errno); +void DirectoryWatch::updateEntries(bool reportAsExisting) { + _monitors_t::iterator monIter; + if (_dir[_dir.length() - 1] == PATH_SEPERATOR) + _dir = _dir.substr(0, _dir.length() - 1); + + // stat directory for modification date + struct stat dirStat; + if (stat((_dir + _relDir).c_str(), &dirStat) != 0) { + LOG(ERROR) << "Error with stat on directory " << _dir << ": " << strerror(errno); return; } - // iterate all entries and see what changed - struct dirent* entry; - while((entry = readdir(dp))) { - std::string dname = entry->d_name; + + if ((unsigned)dirStat.st_mtime >= (unsigned)_lastChecked) { + // there are changes in the directory + std::set<std::string> currEntries; + +#ifndef WIN32 + DIR *dp; + dp = opendir((_dir + _relDir).c_str()); + if (dp == NULL) { + LOG(ERROR) << "Error opening directory " << _dir + _relDir << ": " << strerror(errno); + return; + } + // iterate all entries and see what changed + struct dirent* entry; + while((entry = readdir(dp))) { + std::string dname = entry->d_name; #else - WIN32_FIND_DATA ffd; - HANDLE hFind = INVALID_HANDLE_VALUE; - TCHAR szDir[MAX_PATH]; - StringCchCopy(szDir, MAX_PATH, dir.c_str()); - StringCchCat(szDir, MAX_PATH, TEXT("\\*")); - - hFind = FindFirstFile(szDir, &ffd); - do { - std::string dname = ffd.cFileName; + WIN32_FIND_DATA ffd; + HANDLE hFind = INVALID_HANDLE_VALUE; + TCHAR szDir[MAX_PATH]; + StringCchCopy(szDir, MAX_PATH, _dir.c_str()); + StringCchCat(szDir, MAX_PATH, TEXT("\\*")); + + hFind = FindFirstFile(szDir, &ffd); + do { + string dname = ffd.cFileName; #endif - if (boost::iequals(dname, ".") || boost::iequals(dname, "..")) - continue; + // see if the file was changed + char* filename; + asprintf(&filename, "%s/%s", (_dir + _relDir).c_str(), dname.c_str()); - char* filename = (char*)malloc(dir.size() + dname.size() + 2); - sprintf(filename, "%s/%s", dir.c_str(), dname.c_str()); + struct stat fileStat; + if (stat(filename, &fileStat) != 0) { + LOG(ERROR) << "Error with stat on directory entry: " << filename << ": " << strerror(errno); + free(filename); + continue; + } - struct stat fileStat; - if (stat(filename, &fileStat) != 0) { - LOG(ERROR) << "Error with stat on directory entry " << filename << ": " << strerror(errno); - free(filename); - continue; - } + if (fileStat.st_mode & S_IFDIR) { + if (boost::equals(dname, ".") || boost::equals(dname, "..")) { + free(filename); + continue; // do not report . or .. + } + } - if (fileStat.st_mode & S_IFDIR) { - if (_recurse) { - reportExistingIn(filename, watchid); + currEntries.insert(dname); + + if (_knownEntries.find(dname) != _knownEntries.end()) { + // we have seen this entry before + struct stat oldStat = _knownEntries[dname]; + if (oldStat.st_mtime < fileStat.st_mtime) { + monIter = _monitors.begin(); + while(monIter != _monitors.end()) { + (*monIter)->handleChanges(MODIFIED, _dir, _relDir + PATH_SEPERATOR + dname, fileStat); + monIter++; + } + } } else { - free(filename); - continue; + // we have not yet seen this entry + if (fileStat.st_mode & S_IFDIR) { + _knownDirs[dname] = new DirectoryWatch(_dir, _relDir + PATH_SEPERATOR + dname); + monIter = _monitors.begin(); + while(monIter != _monitors.end()) { + _knownDirs[dname]->addMonitor(*monIter); + monIter++; + } + } else { + monIter = _monitors.begin(); + while(monIter != _monitors.end()) { + if (reportAsExisting) { + (*monIter)->handleChanges(EXISTING, _dir, _relDir + PATH_SEPERATOR + dname, fileStat); + } else { + (*monIter)->handleChanges(ADDED, _dir, _relDir + PATH_SEPERATOR + dname, fileStat); + } + monIter++; + } + } } - } - if (!filter(dname)) { free(filename); - continue; + _knownEntries[dname] = fileStat; // gets copied on insertion +#ifndef WIN32 } - - handleFileAction(watchid, dir, filename, FW::Actions::Existing); + closedir(dp); +#else + } + while (FindNextFile(hFind, &ffd) != 0); + FindClose(hFind); +#endif + // are there any known entries we have not seen this time around? + std::map<std::string, struct stat>::iterator fileIter = _knownEntries.begin(); + while(fileIter != _knownEntries.end()) { + if (currEntries.find(fileIter->first) == currEntries.end()) { + // we used to know this file + if (fileIter->second.st_mode & S_IFDIR) { + if (_recurse) { + _knownDirs[fileIter->first]->reportAsDeleted(); + delete _knownDirs[fileIter->first]; + _knownDirs.erase(fileIter->first); + } + } else { + monIter = _monitors.begin(); + while(monIter != _monitors.end()) { + (*monIter)->handleChanges(DELETED, _dir, _relDir + PATH_SEPERATOR + fileIter->first, fileIter->second); + monIter++; + } + } + _knownEntries.erase(fileIter->first); + } + fileIter++; + } + // remember when we last checked the directory for modifications #ifndef WIN32 - } - closedir(dp); + time(&_lastChecked); #else - } - while (FindNextFile(hFind, &ffd) != 0); - FindClose(hFind); + // TODO: this will fail with sub-millisecond updates to the directory + _lastChecked = dirStat.st_mtime + 1; #endif - + // update all directories + } + if (_recurse) { + std::map<std::string, DirectoryWatch*>::iterator dirIter = _knownDirs.begin(); + while(dirIter != _knownDirs.end()) { + dirIter->second->updateEntries(); + dirIter++; + } + } } }
\ No newline at end of file diff --git a/src/uscxml/plugins/invoker/filesystem/dirmon/DirMonInvoker.h b/src/uscxml/plugins/invoker/filesystem/dirmon/DirMonInvoker.h index 04e670d..3fd9258 100644 --- a/src/uscxml/plugins/invoker/filesystem/dirmon/DirMonInvoker.h +++ b/src/uscxml/plugins/invoker/filesystem/dirmon/DirMonInvoker.h @@ -2,8 +2,8 @@ #define DIRMONINVOKER_H_W09J90F0 #include <uscxml/Interpreter.h> -#include "FileWatcher/FileWatcher.h" #include <map> +#include <sys/stat.h> #ifdef BUILD_AS_PLUGINS #include "uscxml/plugins/Plugins.h" @@ -11,7 +11,48 @@ namespace uscxml { -class DirMonInvoker : public InvokerImpl, public FW::FileWatchListener { +class DirectoryWatchMonitor; + +class DirectoryWatch { +public: + enum Action { + ADDED = 1, + MODIFIED = 2, + DELETED = 4, + EXISTING = 8 + }; + + DirectoryWatch(const std::string& dir, bool recurse = false) : _dir(dir), _recurse(recurse), _lastChecked(0) {} + + void addMonitor(DirectoryWatchMonitor* monitor) { + _monitors.insert(monitor); + } + void removeMonitor(DirectoryWatchMonitor* monitor) { + _monitors.erase(monitor); + } + void updateEntries(bool reportAsExisting = false); + void reportAsDeleted(); + +protected: + DirectoryWatch(const std::string& dir, const std::string& relDir) : _dir(dir), _relDir(relDir), _recurse(true), _lastChecked(0) {} + + std::string _dir; + std::string _relDir; + + bool _recurse; + std::map<std::string, struct stat> _knownEntries; + std::map<std::string, DirectoryWatch*> _knownDirs; + std::set<DirectoryWatchMonitor*> _monitors; + typedef std::set<DirectoryWatchMonitor*> _monitors_t; + time_t _lastChecked; +}; + +class DirectoryWatchMonitor { +public: + virtual void handleChanges(DirectoryWatch::Action action, const std::string dir, const std::string file, struct stat fileStat) = 0; +}; + +class DirMonInvoker : public InvokerImpl, public DirectoryWatchMonitor { public: DirMonInvoker(); virtual ~DirMonInvoker(); @@ -30,10 +71,7 @@ public: virtual void cancel(const std::string sendId); virtual void invoke(const InvokeRequest& req); - void handleFileAction(FW::WatchID watchid, const FW::String& dir, const FW::String& filename, FW::Action action); - void reportExisting(); - void reportExistingIn(const std::string dir, FW::WatchID watchid); - virtual bool filter(const std::string filename); + virtual void handleChanges(DirectoryWatch::Action action, const std::string dir, const std::string file, struct stat fileStat); static void run(void* instance); @@ -41,12 +79,15 @@ protected: bool _reportExisting; bool _reportHidden; bool _recurse; - std::set<std::string> _suffixes; + + std::string _dir; + std::set<std::string> _suffixes; bool _isRunning; tthread::thread* _thread; - FW::FileWatcher _fileWatcher; - std::multimap<std::string, FW::WatchID> _watchIds; + tthread::recursive_mutex _mutex; + + DirectoryWatch* _watcher; }; #ifdef BUILD_AS_PLUGINS diff --git a/src/uscxml/plugins/invoker/filesystem/dirmon/FileWatcher/FileWatcherOSX.cpp b/src/uscxml/plugins/invoker/filesystem/dirmon/FileWatcher/FileWatcherOSX.cpp index e1634b0..a47d635 100644 --- a/src/uscxml/plugins/invoker/filesystem/dirmon/FileWatcher/FileWatcherOSX.cpp +++ b/src/uscxml/plugins/invoker/filesystem/dirmon/FileWatcher/FileWatcherOSX.cpp @@ -35,6 +35,7 @@ #include <stdlib.h> #include <dirent.h> #include <string.h> +#include <iostream> // this is more suited: // https://developer.apple.com/library/mac/#documentation/Darwin/Conceptual/FSEvents_ProgGuide/UsingtheFSEventsFramework/UsingtheFSEventsFramework.html @@ -71,18 +72,20 @@ struct WatchStruct { WatchID mWatchID; String mDirName; FileWatchListener* mListener; + FileWatcherOSX* mWatcher; + bool mRecursive; // index 0 is always the directory KEvent mChangeList[MAX_CHANGE_EVENT_SIZE]; size_t mChangeListCount; - WatchStruct(WatchID watchid, const String& dirname, FileWatchListener* listener) - : mWatchID(watchid), mDirName(dirname), mListener(listener) { + WatchStruct(WatchID watchid, const String& dirname, FileWatchListener* listener, FileWatcherOSX* watcher, bool recursive = false) + : mWatchID(watchid), mDirName(dirname), mListener(listener), mWatcher(watcher), mRecursive(recursive) { mChangeListCount = 0; addAll(); } - void addFile(const String& name, bool imitEvents = true) { + void addFile(const String& name, bool emitEvents = true) { //fprintf(stderr, "ADDED: %s\n", name.c_str()); // create entry @@ -104,18 +107,18 @@ struct WatchStruct { // set the event data at the end of the list EV_SET(&mChangeList[mChangeListCount], fd, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_ONESHOT, - NOTE_DELETE | NOTE_EXTEND | NOTE_WRITE | NOTE_ATTRIB, + NOTE_DELETE | NOTE_EXTEND | NOTE_WRITE | NOTE_ATTRIB | NOTE_RENAME, 0, (void*)entry); // qsort qsort(mChangeList + 1, mChangeListCount, sizeof(KEvent), comparator); // handle action - if(imitEvents) + if(emitEvents) handleAction(name, Actions::Add); } - void removeFile(const String& name, bool imitEvents = true) { + void removeFile(const String& name, bool emitEvents = true) { // bsearch KEvent target; EntryStruct tempEntry(name.c_str(), 0); @@ -140,7 +143,7 @@ struct WatchStruct { qsort(mChangeList + 1, mChangeListCount, sizeof(KEvent), comparator); // handle action - if(imitEvents) + if(emitEvents) handleAction(name, Actions::Delete); } @@ -207,7 +210,7 @@ struct WatchStruct { int fd = open(mDirName.c_str(), O_RDONLY); EV_SET(&mChangeList[0], fd, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_ONESHOT, - NOTE_DELETE | NOTE_EXTEND | NOTE_WRITE | NOTE_ATTRIB, + NOTE_DELETE | NOTE_EXTEND | NOTE_WRITE | NOTE_ATTRIB | NOTE_RENAME, 0, 0); //fprintf(stderr, "ADDED: %s\n", mDirName.c_str()); @@ -222,11 +225,13 @@ struct WatchStruct { while((entry = readdir(dir)) != NULL) { String fname = (mDirName + "/" + String(entry->d_name)); stat(fname.c_str(), &attrib); - if(S_ISREG(attrib.st_mode)) + if(S_ISREG(attrib.st_mode)) { addFile(fname, false); - //else - // fprintf(stderr, "NOT ADDED: %s (%d)\n", fname.c_str(), attrib.st_mode); - + } else if(S_IFDIR && mRecursive && entry->d_name[0] != '.') { + mWatcher->addWatch(fname, mListener, mRecursive); + } else { + fprintf(stderr, "NOT ADDED: %s (%d)\n", fname.c_str(), attrib.st_mode); + } }//end while closedir(dir); @@ -263,19 +268,33 @@ void FileWatcherOSX::update() { if(nev == -1) perror("kevent"); else { + if (event.fflags & NOTE_DELETE) { + fprintf(stderr, "NOTE_DELETE "); + } + if (event.fflags & NOTE_EXTEND) { + fprintf(stderr, "NOTE_EXTEND "); + } + if (event.fflags & NOTE_WRITE) { + fprintf(stderr, "NOTE_WRITE "); + } + if (event.fflags & NOTE_ATTRIB) { + fprintf(stderr, "NOTE_ATTRIB "); + } + if (event.fflags & NOTE_RENAME) { + fprintf(stderr, "NOTE_RENAME "); + } + EntryStruct* entry = 0; if((entry = (EntryStruct*)event.udata) != 0) { - //fprintf(stderr, "File: %s -- ", (char*)entry->mFilename); + fprintf(stderr, " to %s -- \n", (char*)entry->mFilename); if(event.fflags & NOTE_DELETE) { - //fprintf(stderr, "File deleted\n"); //watch->handleAction(entry->mFilename, Action::Delete); watch->removeFile(entry->mFilename); } if(event.fflags & NOTE_EXTEND || event.fflags & NOTE_WRITE || event.fflags & NOTE_ATTRIB) { - //fprintf(stderr, "modified\n"); //watch->rescan(); struct stat attrib; stat(entry->mFilename, &attrib); @@ -283,7 +302,7 @@ void FileWatcherOSX::update() { watch->handleAction(entry->mFilename, FW::Actions::Modified); } } else { - //fprintf(stderr, "Dir: %s -- rescanning\n", watch->mDirName.c_str()); + fprintf(stderr, " in %s -- rescanning\n", watch->mDirName.c_str()); watch->rescan(); } } @@ -295,7 +314,7 @@ void FileWatcherOSX::update() { FileWatcherOSX::FileWatcherOSX() { mDescriptor = kqueue(); mTimeOut.tv_sec = 0; - mTimeOut.tv_nsec = 2000000; + mTimeOut.tv_nsec = 20000000; } //-------- @@ -322,9 +341,12 @@ WatchID FileWatcherOSX::addWatch(const String& directory, FileWatchListener* wat 0, (void*)"testing"); */ - WatchStruct* watch = new WatchStruct(++mLastWatchID, directory, watcher); - mWatches.insert(std::make_pair(mLastWatchID, watch)); - return mLastWatchID; + std::cout << "Adding watch for " << directory << std::endl; + + WatchID currWatch = ++mLastWatchID; + WatchStruct* watch = new WatchStruct(currWatch, directory, watcher, this, recursive); + mWatches.insert(std::make_pair(currWatch, watch)); + return currWatch; } //-------- diff --git a/src/uscxml/plugins/invoker/filesystem/dirmon/FileWatcher/FileWatcherOSX.h b/src/uscxml/plugins/invoker/filesystem/dirmon/FileWatcher/FileWatcherOSX.h index 39f411c..92e3957 100644 --- a/src/uscxml/plugins/invoker/filesystem/dirmon/FileWatcher/FileWatcherOSX.h +++ b/src/uscxml/plugins/invoker/filesystem/dirmon/FileWatcher/FileWatcherOSX.h @@ -54,7 +54,7 @@ public: /// Add a directory watch /// @exception FileNotFoundException Thrown when the requested directory does not exist - WatchID addWatch(const String& directory, FileWatchListener* watcher, bool recursive); + WatchID addWatch(const String& directory, FileWatchListener* watcher, bool recursive = false); /// Remove a directory watch. This is a brute force lazy search O(nlogn). void removeWatch(const String& directory); @@ -78,6 +78,7 @@ private: /// WatchID allocator int mLastWatchID; + friend class WatchStruct; };//end FileWatcherOSX };//namespace FW |