Tuesday, February 05, 2008

A simple application using io.monitor: a tail -f replacement

The tail command on Unix shows the end of a file. If you pass it the -f switch it monitors the file for changes and emits any lines written to the end. This is frequently used to watch log files. Traditionally it was implemented by polling but on modern systems it uses file system change notification APIs.

Here is an example that Factor's file system change notification API. Note that I renamed the io.monitor vocabulary to io.monitors. This demo works on Linux and Windows.

We begin with the customary boilerplate:
USING: kernel io io.files io.monitors ;
IN: log-viewer

First, we need a word which reads lines from a stream until EOF and prints them. Note that the stream isn't closed here.
: read-lines ( stream -- )
dup stream-readln dup [ print read-lines ] [ 2drop ] if ;

Next, a recursive word which takes a stream and a monitor; it reads any lines until EOF, waits for the file to change, then calls itself again:
: tail-file-loop ( stream monitor -- )
over read-lines
dup next-change 2drop
tail-file-loop ;

Finally, a word which puts everything together. It takes a file name, opens it for reading, and creates a monitor on its parent directory:
: tail-file ( file -- )
dup <file-reader> swap parent-directory f <monitor>
tail-file-loop ;


Adam said...

when I deleted a file being watched, the file reappeared an was inaccessible until factor was closed.

Slava Pestov said...

Adam: what OS are you using?