bool FileSystemWatcher::watch(const Path &p) { Path path = p; assert(!path.isEmpty()); const Path::Type type = path.type(); switch (type) { case Path::File: path = path.parentDir(); // fall through case Path::Directory: break; default: error("FileSystemWatcher::watch() '%s' doesn't seem to be watchable", path.constData()); return false; } if (!path.endsWith('/')) path += '/'; if (isWatching(path)) return false; mWatcher->watch(path); return true; }
bool FileSystemWatcher::isWatching(const Path& p) const { if (!p.endsWith('/')) return isWatching(p + '/'); std::lock_guard<std::mutex> lock(mWatcher->mutex); return mWatcher->paths.contains(p); }
bool FileSystemWatcher::watch(const Path &p) { Path path = p; assert(!path.isEmpty()); std::lock_guard<std::mutex> lock(mMutex); const Path::Type type = path.type(); uint32_t flags = 0; switch (type) { case Path::File: path = path.parentDir(); // fall through case Path::Directory: flags = NOTE_RENAME|NOTE_DELETE|NOTE_EXTEND|NOTE_WRITE|NOTE_ATTRIB|NOTE_REVOKE; break; default: error("FileSystemWatcher::watch() '%s' doesn't seem to be watchable", path.constData()); return false; } if (!path.endsWith('/')) path += '/'; if (isWatching(path)) return false; int ret = ::open(path.nullTerminated(), O_RDONLY); //static int cnt = 0; //printf("wanting to watch [%05d] %s : %d\n", ++cnt, path.nullTerminated(), ret); if (ret != -1) { struct kevent change; struct timespec nullts = { 0, 0 }; EV_SET(&change, ret, EVFILT_VNODE, EV_ADD|EV_ENABLE|EV_CLEAR, flags, 0, 0); if (::kevent(mFd, &change, 1, 0, 0, &nullts) == -1) { // bad things have happened error("FileSystemWatcher::watch() kevent failed for '%s' (%d) %s", path.constData(), errno, Rct::strerror().constData()); ::close(ret); return false; } } if (ret == -1) { error("FileSystemWatcher::watch() watch failed for '%s' (%d) %s", path.constData(), errno, Rct::strerror().constData()); return false; } mWatchedByPath[path] = ret; mWatchedById[ret] = path; FSUserData data; data.watcher = this; path.visit([&data](const Path &p) { return scanFiles(p, &data); }); return true; }
void DocumentWatcher::addWatch(Document* document) { QString path = QFileInfo(document->filename()).canonicalFilePath(); if (isWatching(path)) { return; } m_paths.insert(path, document); m_watcher->addPath(path); }
bool WatcherThread::watch(const Path& path) { MutexLocker locker(&mutex); if (isWatching(path)) return false; paths.insert(path); CFRunLoopSourceSignal(source); CFRunLoopWakeUp(loop); return true; }
void DirectoryWatcherManager::addPath(const Poco::Path& path, bool listExistingItemsOnStart, bool sortAlphaNumeric, AbstractPathFilter* pFilter, int eventMask, int scanInterval) { if (isWatching(path)) { Poco::Exception exc("Already Watching Exception", path.toString()); ofNotifyEvent(events.onScanError, exc, this); return; } try { Poco::File file(path); if (!file.exists()) { Poco::FileNotFoundException exc(path.toString()); throw exc; } DirectoryWatcherPtr watcher = DirectoryWatcherPtr(new DirectoryWatcher(path.toString(), eventMask, scanInterval)); watcher->itemAdded += Poco::priorityDelegate(this, &DirectoryWatcherManager::onItemAdded, OF_EVENT_ORDER_AFTER_APP); watcher->itemRemoved += Poco::priorityDelegate(this, &DirectoryWatcherManager::onItemRemoved, OF_EVENT_ORDER_AFTER_APP); watcher->itemModified += Poco::priorityDelegate(this, &DirectoryWatcherManager::onItemModified, OF_EVENT_ORDER_AFTER_APP); watcher->itemMovedFrom += Poco::priorityDelegate(this, &DirectoryWatcherManager::onItemMovedFrom, OF_EVENT_ORDER_AFTER_APP); watcher->itemMovedTo += Poco::priorityDelegate(this, &DirectoryWatcherManager::onItemMovedTo, OF_EVENT_ORDER_AFTER_APP); watcher->scanError += Poco::priorityDelegate(this, &DirectoryWatcherManager::onScanError, OF_EVENT_ORDER_AFTER_APP); mutex.lock(); if(pFilter) { filterList[path] = pFilter; } watchList[path] = watcher; mutex.unlock(); if (listExistingItemsOnStart) { std::vector<Poco::File> files; DirectoryUtils::list(file, files, sortAlphaNumeric, pFilter); std::vector<Poco::File>::iterator iter = files.begin(); while(iter != files.end()) { DirectoryWatcher::DirectoryEvent event(*iter, DirectoryWatcher::DW_ITEM_ADDED); ofNotifyEvent(events.onItemAdded,event,this); ++iter; } } } catch (const Poco::FileNotFoundException& exc) { ofNotifyEvent(events.onScanError, exc, this); } }
bool FileSystemWatcher::isWatching(const Path& p) const { if (!p.endsWith('/')) return isWatching(p + '/'); return mWatchedByPath.contains(p); }
bool FSEventsService::hasErrored() { struct stat root; return !isWatching() || stat(mPath.c_str(), &root) < 0; }
bool FileSystemWatcher::watch(const Path &p) { Path path = p; assert(!path.isEmpty()); MutexLocker lock(&mMutex); const Path::Type type = path.type(); uint32_t flags = 0; switch (type) { case Path::File: path = path.parentDir(); // fall through case Path::Directory: flags = NOTE_RENAME|NOTE_DELETE|NOTE_EXTEND|NOTE_WRITE|NOTE_ATTRIB|NOTE_REVOKE; break; default: error("FileSystemWatcher::watch() '%s' doesn't not seem to be watchable", path.constData()); return false; } if (!path.endsWith('/')) path += '/'; if (isWatching(path)) return false; int ret = ::open(path.nullTerminated(), O_RDONLY); //static int cnt = 0; //printf("wanting to watch [%05d] %s : %d\n", ++cnt, path.nullTerminated(), ret); if (ret != -1) { struct kevent change; struct timespec nullts = { 0, 0 }; EV_SET(&change, ret, EVFILT_VNODE, EV_ADD|EV_ENABLE|EV_CLEAR, flags, 0, 0); if (::kevent(mFd, &change, 1, 0, 0, &nullts) == -1) { // bad things have happened error("FileSystemWatcher::watch() kevent failed for '%s' (%d) %s", path.constData(), errno, strerror(errno)); ::close(ret); return false; } } if (ret == -1) { error("FileSystemWatcher::watch() watch failed for '%s' (%d) %s", path.constData(), errno, strerror(errno)); return false; } mWatchedByPath[path] = ret; mWatchedById[ret] = path; FSUserData data; data.watcher = this; path.visit(scanFiles, &data); // did we watch any parent directories of what we've already watched? // if so, unwatch the subdirectories int wd; struct kevent change; struct timespec nullts = { 0, 0 }; for (Set<Path>::const_iterator it = data.modified.begin(); it != data.modified.end(); ++it) { if (mWatchedByPath.remove(*it, &wd)) { EV_SET(&change, wd, EVFILT_VNODE, EV_DELETE, 0, 0, 0); if (::kevent(mFd, &change, 1, 0, 0, &nullts) == -1) { // bad stuff error("FileSystemWatcher::watch() kevent (for existing path) failed for '%s' (%d) %s", it->constData(), errno, strerror(errno)); } ::close(wd); mWatchedById.remove(wd); } } return true; }