summaryrefslogtreecommitdiffstats
path: root/src/uscxml/plugins/invoker/filesystem/dirmon/FileWatcher/FileWatcherOSX.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/uscxml/plugins/invoker/filesystem/dirmon/FileWatcher/FileWatcherOSX.cpp')
-rw-r--r--src/uscxml/plugins/invoker/filesystem/dirmon/FileWatcher/FileWatcherOSX.cpp386
1 files changed, 0 insertions, 386 deletions
diff --git a/src/uscxml/plugins/invoker/filesystem/dirmon/FileWatcher/FileWatcherOSX.cpp b/src/uscxml/plugins/invoker/filesystem/dirmon/FileWatcher/FileWatcherOSX.cpp
deleted file mode 100644
index a47d635..0000000
--- a/src/uscxml/plugins/invoker/filesystem/dirmon/FileWatcher/FileWatcherOSX.cpp
+++ /dev/null
@@ -1,386 +0,0 @@
-/**
- Copyright (c) 2009 James Wynn (james@jameswynn.com)
-
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
-
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE.
-
- James Wynn james@jameswynn.com
-*/
-
-#include <FileWatcher/FileWatcherOSX.h>
-
-#if FILEWATCHER_PLATFORM == FILEWATCHER_PLATFORM_KQUEUE
-
-#include <sys/event.h>
-#include <sys/time.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <stdio.h>
-#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
-
-namespace FW {
-
-#define MAX_CHANGE_EVENT_SIZE 2000
-
-typedef struct kevent KEvent;
-
-struct EntryStruct {
- EntryStruct(const char* filename, time_t mtime = 0)
- : mFilename(filename), mModifiedTime(mtime) {
- }
- ~EntryStruct() {
- delete[] mFilename;
- }
- const char* mFilename;
- time_t mModifiedTime;
-};
-
-int comparator(const void* ke1, const void* ke2) {
- /*KEvent* kevent1 = (KEvent*) ke1;
- KEvent* kevent2 = (KEvent*) ke2;
-
- EntryStruct* event1 = (EntryStruct*)kevent1->udata;
- EntryStruct* event2 = (EntryStruct*)kevent2->udata;
- return strcmp(event1->mFilename, event2->mFilename);
- */
- return strcmp(((EntryStruct*)(((KEvent*)(ke1))->udata))->mFilename, ((EntryStruct*)(((KEvent*)(ke2))->udata))->mFilename);
-}
-
-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, FileWatcherOSX* watcher, bool recursive = false)
- : mWatchID(watchid), mDirName(dirname), mListener(listener), mWatcher(watcher), mRecursive(recursive) {
- mChangeListCount = 0;
- addAll();
- }
-
- void addFile(const String& name, bool emitEvents = true) {
- //fprintf(stderr, "ADDED: %s\n", name.c_str());
-
- // create entry
- struct stat attrib;
- stat(name.c_str(), &attrib);
-
- int fd = open(name.c_str(), O_RDONLY);
-
- if(fd == -1)
- throw FileNotFoundException(name);
-
- ++mChangeListCount;
-
- char* namecopy = new char[name.length() + 1];
- strncpy(namecopy, name.c_str(), name.length());
- namecopy[name.length()] = 0;
- EntryStruct* entry = new EntryStruct(namecopy, attrib.st_mtime);
-
- // 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_RENAME,
- 0, (void*)entry);
-
- // qsort
- qsort(mChangeList + 1, mChangeListCount, sizeof(KEvent), comparator);
-
- // handle action
- if(emitEvents)
- handleAction(name, Actions::Add);
- }
-
- void removeFile(const String& name, bool emitEvents = true) {
- // bsearch
- KEvent target;
- EntryStruct tempEntry(name.c_str(), 0);
- target.udata = &tempEntry;
- KEvent* ke = (KEvent*)bsearch(&target, &mChangeList, mChangeListCount + 1, sizeof(KEvent), comparator);
- if(!ke)
- throw FileNotFoundException(name);
-
- tempEntry.mFilename = 0;
-
- // delete
- close(ke->ident);
- delete((EntryStruct*)ke->udata);
- memset(ke, 0, sizeof(KEvent));
-
- // move end to current
- memcpy(ke, &mChangeList[mChangeListCount], sizeof(KEvent));
- memset(&mChangeList[mChangeListCount], 0, sizeof(KEvent));
- --mChangeListCount;
-
- // qsort
- qsort(mChangeList + 1, mChangeListCount, sizeof(KEvent), comparator);
-
- // handle action
- if(emitEvents)
- handleAction(name, Actions::Delete);
- }
-
- // called when the directory is actually changed
- // means a file has been added or removed
- // rescans the watched directory adding/removing files and sending notices
- void rescan() {
- // if new file, call addFile
- // if missing file, call removeFile
- // if timestamp modified, call handleAction(filename, ACTION_MODIFIED);
- DIR* dir = opendir(mDirName.c_str());
- if(!dir)
- return;
-
- struct dirent* dentry;
- KEvent* ke = &mChangeList[1];
- EntryStruct* entry = 0;
- struct stat attrib;
-
- while((dentry = readdir(dir)) != NULL) {
- String fname = mDirName + "/" + dentry->d_name;
- stat(fname.c_str(), &attrib);
- if(!S_ISREG(attrib.st_mode))
- continue;
-
- if(ke <= &mChangeList[mChangeListCount]) {
- entry = (EntryStruct*)ke->udata;
- int result = strcmp(entry->mFilename, fname.c_str());
- //fprintf(stderr, "[%s cmp %s]\n", entry->mFilename, fname.c_str());
- if(result == 0) {
- stat(entry->mFilename, &attrib);
- time_t timestamp = attrib.st_mtime;
-
- if(entry->mModifiedTime != timestamp) {
- entry->mModifiedTime = timestamp;
- handleAction(entry->mFilename, Actions::Modified);
- }
- ke++;
- } else if(result < 0) {
- // f1 was deleted
- removeFile(entry->mFilename);
- ke++;
- } else {
- // f2 was created
- addFile(fname);
- ke++;
- }
- } else {
- // just add
- addFile(fname);
- ke++;
- }
- }//end while
-
- closedir(dir);
- };
-
- void handleAction(const String& filename, FW::Action action) {
- mListener->handleFileAction(mWatchID, mDirName, filename, action);
- }
-
- void addAll() {
- // add base dir
- 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_RENAME,
- 0, 0);
-
- //fprintf(stderr, "ADDED: %s\n", mDirName.c_str());
-
- // scan directory and call addFile(name, false) on each file
- DIR* dir = opendir(mDirName.c_str());
- if(!dir)
- throw FileNotFoundException(mDirName);
-
- struct dirent* entry;
- struct stat attrib;
- while((entry = readdir(dir)) != NULL) {
- String fname = (mDirName + "/" + String(entry->d_name));
- stat(fname.c_str(), &attrib);
- if(S_ISREG(attrib.st_mode)) {
- addFile(fname, false);
- } 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);
- }
-
- void removeAll() {
- KEvent* ke = NULL;
-
- // go through list removing each file and sending an event
- for(int i = 0; i < mChangeListCount; ++i) {
- ke = &mChangeList[i];
- //handleAction(name, Action::Delete);
- EntryStruct* entry = (EntryStruct*)ke->udata;
-
- handleAction(entry->mFilename, Actions::Delete);
-
- // delete
- close(ke->ident);
- delete((EntryStruct*)ke->udata);
- }
- }
-};
-
-void FileWatcherOSX::update() {
- int nev = 0;
- struct kevent event;
-
- WatchMap::iterator iter = mWatches.begin();
- WatchMap::iterator end = mWatches.end();
- for(; iter != end; ++iter) {
- WatchStruct* watch = iter->second;
-
- while((nev = kevent(mDescriptor, (KEvent*)&(watch->mChangeList), watch->mChangeListCount + 1, &event, 1, &mTimeOut)) != 0) {
- 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, " to %s -- \n", (char*)entry->mFilename);
-
- if(event.fflags & NOTE_DELETE) {
- //watch->handleAction(entry->mFilename, Action::Delete);
- watch->removeFile(entry->mFilename);
- }
- if(event.fflags & NOTE_EXTEND ||
- event.fflags & NOTE_WRITE ||
- event.fflags & NOTE_ATTRIB) {
- //watch->rescan();
- struct stat attrib;
- stat(entry->mFilename, &attrib);
- entry->mModifiedTime = attrib.st_mtime;
- watch->handleAction(entry->mFilename, FW::Actions::Modified);
- }
- } else {
- fprintf(stderr, " in %s -- rescanning\n", watch->mDirName.c_str());
- watch->rescan();
- }
- }
- }
- }
-}
-
-//--------
-FileWatcherOSX::FileWatcherOSX() {
- mDescriptor = kqueue();
- mTimeOut.tv_sec = 0;
- mTimeOut.tv_nsec = 20000000;
-}
-
-//--------
-FileWatcherOSX::~FileWatcherOSX() {
- WatchMap::iterator iter = mWatches.begin();
- WatchMap::iterator end = mWatches.end();
- for(; iter != end; ++iter) {
- delete iter->second;
- }
- mWatches.clear();
-
- close(mDescriptor);
-}
-
-//--------
-WatchID FileWatcherOSX::addWatch(const String& directory, FileWatchListener* watcher, bool recursive) {
- /* int fd = open(directory.c_str(), O_RDONLY);
- if(fd == -1)
- perror("open");
-
- EV_SET(&change, fd, EVFILT_VNODE,
- EV_ADD | EV_ENABLE | EV_ONESHOT,
- NOTE_DELETE | NOTE_EXTEND | NOTE_WRITE | NOTE_ATTRIB,
- 0, (void*)"testing");
- */
-
- 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;
-}
-
-//--------
-void FileWatcherOSX::removeWatch(const String& directory) {
- WatchMap::iterator iter = mWatches.begin();
- WatchMap::iterator end = mWatches.end();
- for(; iter != end; ++iter) {
- if(directory == iter->second->mDirName) {
- removeWatch(iter->first);
- return;
- }
- }
-}
-
-//--------
-void FileWatcherOSX::removeWatch(WatchID watchid) {
- WatchMap::iterator iter = mWatches.find(watchid);
-
- if(iter == mWatches.end())
- return;
-
- WatchStruct* watch = iter->second;
- mWatches.erase(iter);
-
- //inotify_rm_watch(mFD, watchid);
-
- delete watch;
- watch = 0;
-}
-
-//--------
-void FileWatcherOSX::handleAction(WatchStruct* watch, const String& filename, unsigned long action) {
-}
-
-};//namespace FW
-
-#endif//FILEWATCHER_PLATFORM_KQUEUE