Haskell: Monitor a file without polling (à la inotify in linux)
Asked Answered
M

3

10

Is there a haskell library function to monitor a file without polling?

With polling i would do someting like this:

monitor file mtime handler = do
    threadDelay n -- sleep `n` ns
    t <- getModificationTime file
    if t > mtime
        then handler >> monitor file t handler
        else monitor file mtime handler

What I want is something like a blocking getModificationTime which will be woken up by the system. Is there something available?

I would be perfectly happy if it was available for posix systems only, but the more portable the better :-)

Edit: I know hinotify, but I'm on a Mac (that's why I mention POSIX).

Morehead answered 30/11, 2012 at 9:47 Comment(2)
A wrapper around hinotity and kqueue depending on platform might be interesting.Illicit
Interesting question. Sorry to me too this, is there anything on Windows?Pennsylvania
A
10

The kqueue package should do this: http://hackage.haskell.org/package/kqueue

Available answered 30/11, 2012 at 10:35 Comment(0)
S
7

There was a GSoC project which resulted in the fsnotify package which uses system-specific libraries, and falls back to polling. It uses hfsevents on Mac.

Spender answered 1/12, 2012 at 17:12 Comment(2)
seems to be a nice library. I tried to build and install it (GHC 7.0.3, Mac OS X 10.6) but it did not work, due to a problem with hfsevents. So I'm going to stick with the above solution.Morehead
It would be great if you could file a bug report with the maintainer of hfsevents so he can fix it.Spender
M
5

The Package suggested by Sjoerd Visscher works like a charm (using GHC 7.0.3 and kqueue 0.1.2.4, Mac OS X 10.6 Snow Leopard).

I compiled a quick sample using it (since I could not find API documentation, but there are some examples up on github):

import Control.Concurrent.MVar
import System.KQueue.HighLevel (watchFile, EventType, Watcher)
import System.Environment (getArgs)

watch :: MVar EventType -> FilePath -> IO Watcher
watch chan file =
    let handler ev = putMVar chan ev
    in  watchFile file handler

listen :: MVar EventType -> IO ()
listen chan = takeMVar chan >>= print >> listen chan

main :: IO ()
main = do
        args <- getArgs
        chan <- newEmptyMVar
        mapM (watch chan) args
        listen chan

This will create a little program which you can pass filepaths on as arguments and monitor these files. The Events are fed back through an MVar and read by the main thread which is basically a loop implemented by listen. The program has to be killed using ^C since it is designed to run forever.

Morehead answered 30/11, 2012 at 22:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.