diff options
Diffstat (limited to 'src/uscxml/plugins/invoker/filesystem/dirmon/DirMonInvoker.cpp')
-rw-r--r-- | src/uscxml/plugins/invoker/filesystem/dirmon/DirMonInvoker.cpp | 443 |
1 files changed, 0 insertions, 443 deletions
diff --git a/src/uscxml/plugins/invoker/filesystem/dirmon/DirMonInvoker.cpp b/src/uscxml/plugins/invoker/filesystem/dirmon/DirMonInvoker.cpp deleted file mode 100644 index 63d1628..0000000 --- a/src/uscxml/plugins/invoker/filesystem/dirmon/DirMonInvoker.cpp +++ /dev/null @@ -1,443 +0,0 @@ -/** - * @file - * @author 2012-2013 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de) - * @copyright Simplified BSD - * - * @cond - * This program is free software: you can redistribute it and/or modify - * it under the terms of the FreeBSD license as published by the FreeBSD - * project. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * You should have received a copy of the FreeBSD license along with this - * program. If not, see <http://www.opensource.org/licenses/bsd-license>. - * @endcond - */ - -#include <boost/algorithm/string.hpp> - -#include "DirMonInvoker.h" -#include <glog/logging.h> - -#include "uscxml/config.h" - -#ifdef BUILD_AS_PLUGINS -#include <Pluma/Connector.hpp> -#endif - -#include <sys/stat.h> -#ifndef WIN32 -#include <dirent.h> -#else -#include <strsafe.h> -#endif - -namespace uscxml { - -#ifdef BUILD_AS_PLUGINS -PLUMA_CONNECTOR -bool pluginConnect(pluma::Host& host) { - host.add( new DirMonInvokerProvider() ); - return true; -} -#endif - -DirMonInvoker::DirMonInvoker() : - _reportExisting(true), - _reportHidden(false), - _recurse(false), - _thread(NULL), - _watcher(NULL) { -} - -DirMonInvoker::~DirMonInvoker() { - _isRunning = false; - if (_thread) { - _thread->join(); - delete _thread; - } - if (_watcher) - delete(_watcher); -}; - -boost::shared_ptr<InvokerImpl> DirMonInvoker::create(InterpreterImpl* interpreter) { - boost::shared_ptr<DirMonInvoker> invoker = boost::shared_ptr<DirMonInvoker>(new DirMonInvoker()); - invoker->_interpreter = interpreter; - return invoker; -} - -Data DirMonInvoker::getDataModelVariables() { - tthread::lock_guard<tthread::recursive_mutex> lock(_mutex); - - Data data; - data.compound["dir"] = Data(_dir, Data::VERBATIM); - - std::set<std::string>::iterator suffixIter = _suffixes.begin(); - while(suffixIter != _suffixes.end()) { - data.compound["suffixes"].array.push_back(Data(*suffixIter, Data::VERBATIM)); - suffixIter++; - } - - std::map<std::string, struct stat> entries = _watcher->getAllEntries(); - std::map<std::string, struct stat>::iterator entryIter = entries.begin(); - while(entryIter != entries.end()) { - data.compound["file"].compound[entryIter->first].compound["mtime"] = Data(toStr(entryIter->second.st_mtime), Data::INTERPRETED); - data.compound["file"].compound[entryIter->first].compound["ctime"] = Data(toStr(entryIter->second.st_mtime), Data::INTERPRETED); - data.compound["file"].compound[entryIter->first].compound["atime"] = Data(toStr(entryIter->second.st_mtime), Data::INTERPRETED); - data.compound["file"].compound[entryIter->first].compound["size"] = Data(toStr(entryIter->second.st_mtime), Data::INTERPRETED); - entryIter++; - } - - return data; -} - -void DirMonInvoker::send(const SendRequest& req) { -} - -void DirMonInvoker::cancel(const std::string sendId) { -} - -void DirMonInvoker::invoke(const InvokeRequest& req) { - if (req.params.find("dir") == req.params.end()) { - LOG(ERROR) << "No dir param given"; - return; - } - - if (req.params.find("reportexisting") != req.params.end() && - iequals(req.params.find("reportexisting")->second.atom, "false")) - _reportExisting = false; - if (req.params.find("recurse") != req.params.end() && - iequals(req.params.find("recurse")->second.atom, "true")) - _recurse = true; - if (req.params.find("reporthidden") != req.params.end() && - iequals(req.params.find("reporthidden")->second.atom, "true")) - _reportHidden = true; - - std::string suffixList; - if (req.params.find("suffix") != req.params.end()) { - suffixList = req.params.find("suffix")->second.atom; - } else if (req.params.find("suffixes") != req.params.end()) { - suffixList = req.params.find("suffixes")->second.atom; - } - - 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, Data>::const_iterator dirIter = req.params.find("dir"); - while(dirIter != req.params.upper_bound("dir")) { - // this is simplified - Data might be more elaborate than a simple string atom - URL url(dirIter->second.atom); - if (!url.toAbsolute(_interpreter->getBaseURL(req.elem)) || !iequals(url.scheme(), "file")) { - LOG(ERROR) << "Given directory '" << dirIter->second << "' cannot be transformed to absolute path"; - } else { - _dir = url.path(); - } - 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) { - while(((DirMonInvoker*)instance)->_isRunning) { - { - tthread::lock_guard<tthread::recursive_mutex> lock(((DirMonInvoker*)instance)->_mutex); - ((DirMonInvoker*)instance)->_watcher->updateEntries(); - } - tthread::this_thread::sleep_for(tthread::chrono::milliseconds(20)); - } -} - -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)); - - // 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 DirectoryWatch::EXISTING: - event.name = "file.existing"; - break; - case DirectoryWatch::ADDED: - event.name = "file.added"; - break; - case DirectoryWatch::DELETED: - event.name = "file.deleted"; - break; - case DirectoryWatch::MODIFIED: - event.name = "file.modified"; - break; - default: - break; - } - - if (action != DirectoryWatch::DELETED) { - event.data.compound["file"].compound["mtime"] = Data(toStr(fileStat.st_mtime), Data::INTERPRETED); - event.data.compound["file"].compound["ctime"] = Data(toStr(fileStat.st_ctime), Data::INTERPRETED); - event.data.compound["file"].compound["atime"] = Data(toStr(fileStat.st_atime), Data::INTERPRETED); - event.data.compound["file"].compound["size"] = Data(toStr(fileStat.st_size), Data::INTERPRETED); - } - - 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); -} - -DirectoryWatch::~DirectoryWatch() { - std::map<std::string, DirectoryWatch*>::iterator dirIter = _knownDirs.begin(); - while(dirIter != _knownDirs.end()) { - delete(dirIter->second); - dirIter++; - } - -} - -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++); -// fileIter++; - } - assert(_knownDirs.size() == 0); - assert(_knownEntries.size() == 0); -} - -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; - } - - if ((unsigned)dirStat.st_mtime >= (unsigned)_lastChecked) { -// std::cout << "dirStat.st_mtime: " << dirStat.st_mtime << " / _lastChecked: " << _lastChecked << std::endl; - - // 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; -#endif - - // see if the file was changed - std::string filename = _dir + _relDir + "/" + dname; -// asprintf(&filename, "%s/%s", (_dir + _relDir).c_str(), dname.c_str()); - - struct stat fileStat; - if (stat(filename.c_str(), &fileStat) != 0) { - LOG(ERROR) << "Error with stat on directory entry: " << filename << ": " << strerror(errno); - continue; - } - - if (fileStat.st_mode & S_IFDIR) { - if (boost::equals(dname, ".") || boost::equals(dname, "..")) { - continue; // do not report . or .. - } - } - - 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 { - // 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++; - } - } - } - - _knownEntries[dname] = fileStat; // gets copied on insertion -#ifndef WIN32 - } - 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++); - } else { - fileIter++; - } - } - // remember when we last checked the directory for modifications -#ifndef WIN32 - time(&_lastChecked); -#else - // 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 |