diff options
-rw-r--r-- | Assistant/Watcher.hs | 8 | ||||
-rw-r--r-- | Utility/Kqueue.hs | 13 | ||||
-rw-r--r-- | Utility/libkqueue.c | 55 |
3 files changed, 40 insertions, 36 deletions
diff --git a/Assistant/Watcher.hs b/Assistant/Watcher.hs index 52c3780ab..13c27d080 100644 --- a/Assistant/Watcher.hs +++ b/Assistant/Watcher.hs @@ -84,10 +84,12 @@ watchThread st dstatus changechan = withINotify $ \i -> do } #else #ifdef WITH_KQUEUE -watchThread st dstatus changechan = forever $ do +watchThread st dstatus changechan = do dirs <- scanRecursive "." ignored - changeddir <- waitChange dirs - print $ "detected a change in " ++ show changeddir + kqueue <- initKqueue dirs + forever $ do + changeddir <- waitChange kqueue + print $ "detected a change in " ++ show changeddir #else watchThread = undefined #endif /* WITH_KQUEUE */ diff --git a/Utility/Kqueue.hs b/Utility/Kqueue.hs index a3d8aff2d..6da97d3fa 100644 --- a/Utility/Kqueue.hs +++ b/Utility/Kqueue.hs @@ -11,6 +11,10 @@ module Utility.Kqueue ( scanRecursive, addSubDir, removeSubDir, + + initKqueue, + stopKqueue, + waitChange, ) where @@ -18,7 +22,6 @@ import Common import System.Posix.Types import Foreign.C.Types -import Foreign.C.Error import Foreign.Ptr import Foreign.Marshal import qualified Data.Map as M @@ -52,17 +55,17 @@ foreign import ccall unsafe "libkqueue.h waitchange_kqueue" c_waitchange_kqueue {- Initializes a Kqueue to watch a map of directories. -} initKqueue :: DirMap -> IO Kqueue -initKqueue dirmap = withArrayLen (M.keys dirmap) $ \fdcnt c_fds -> +initKqueue dirmap = withArrayLen (M.keys dirmap) $ \fdcnt c_fds -> do h <- c_init_kqueue (fromIntegral fdcnt) c_fds return $ Kqueue h dirmap {- Stops a Kqueue. Note: Does not directly close the Fds in the dirmap, - so it can be reused. -} -stopKqueue :: Kqueue -> IO +stopKqueue :: Kqueue -> IO () stopKqueue (Kqueue h _) = closeFd h {- Waits for a change on a Kqueue, and returns the directory - - or directories where a change took place. + - where a change took place. - - The kqueue interface does not tell what type of change took place in - the directory; it could be an added file, a deleted file, a renamed @@ -71,7 +74,7 @@ stopKqueue (Kqueue h _) = closeFd h - - Note that if subdirectories have changed, the caller should re-run - initKqueue to get them watched. -} -waitChange :: Kqueue -> IO [FilePath] +waitChange :: Kqueue -> IO (Maybe FilePath) waitChange (Kqueue h dirmap) = do changed <- c_waitchange_kqueue h return $ M.lookup changed dirmap diff --git a/Utility/libkqueue.c b/Utility/libkqueue.c index a919a60c7..999508f7e 100644 --- a/Utility/libkqueue.c +++ b/Utility/libkqueue.c @@ -13,10 +13,35 @@ #include <sys/event.h> #include <sys/time.h> +/* The specified fds are added to the set of fds being watched for changes. + * Fds passed to prior calls still take effect, so it's most efficient to + * not pass the same fds repeatedly. + */ +signed int helper(const int kq, const int fdcnt, const int *fdlist, + struct timespec *timeout) { + int i, nev; + struct kevent evlist[1]; + struct kevent chlist[fdcnt]; + + for (i = 0; i < fdcnt; i++) { + EV_SET(&chlist[i], fdlist[i], EVFILT_VNODE, + EV_ADD | EV_ENABLE | EV_CLEAR, + NOTE_WRITE, + 0, 0); + } + + nev = kevent(kq, chlist, fdcnt, evlist, 1, timeout); + + if (nev == 1) + return evlist[0].ident; + else + return -1; +} + /* Initializes a kqueue, with a list of fds to watch for changes. * Returns the kqueue's handle. */ int init_kqueue(const int fdcnt, const int *fdlist) { - struct nodelay = {0, 0}; + struct timespec nodelay = {0, 0}; int kq; if ((kq = kqueue()) == -1) { @@ -36,31 +61,5 @@ int init_kqueue(const int fdcnt, const int *fdlist) { * Returns the fd that changed, or -1 on error. */ signed int waitchange_kqueue(const int kq) { - helper(kq, 0, NULL, NULL); -} - -/* The specified fds are added to the set of fds being watched for changes. - * Fds passed to prior calls still take effect, so it's most efficient to - * not pass the same fds repeatedly. - */ -signed int helper(const int kq, const int fdcnt, const int *fdlist, cont struct *timeout) { - int i, nev; - struct kevent evlist[1]; - struct kevent chlist[fdcnt]; - - for (i = 0; i < fdcnt; i++) { - EV_SET(&chlist[i], fdlist[i], EVFILT_VNODE, - EV_ADD | EV_ENABLE | EV_CLEAR, - NOTE_WRITE, - 1, - timeout); - } - - nev = kevent(info->kq, info->chlist, info->cnt, info->evlist, - 1, NULL); - - if (nev == 1) - return evlist[0].ident; - else - return -1; + return helper(kq, 0, NULL, NULL); } |