factor/basis/io/monitors/linux/linux.factor

140 lines
3.7 KiB
Factor
Raw Normal View History

2008-04-11 08:15:26 -04:00
! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: kernel io.backend io.monitors io.monitors.recursive
2009-05-16 11:50:16 -04:00
io.files io.pathnames io.buffers io.ports io.timeouts
io.backend.unix io.encodings.utf8 unix.linux.inotify assocs
namespaces make threads continuations init math math.bitwise
sets alien alien.strings alien.c-types vocabs.loader accessors
system hashtables destructors unix classes.struct literals ;
FROM: namespaces => set ;
IN: io.monitors.linux
2008-04-11 08:15:26 -04:00
2008-04-21 07:13:57 -04:00
SYMBOL: watches
SYMBOL: inotify
TUPLE: linux-monitor < monitor wd inotify watches ;
2008-04-11 08:15:26 -04:00
: <linux-monitor> ( wd path mailbox -- monitor )
linux-monitor new-monitor
2008-04-21 07:13:57 -04:00
inotify get >>inotify
watches get >>watches
2008-04-11 08:15:26 -04:00
swap >>wd ;
: wd>monitor ( wd -- monitor ) watches get at ;
: <inotify> ( -- port/f )
2008-07-03 18:44:44 -04:00
inotify_init dup 0 < [ drop f ] [ <fd> init-fd <input-port> ] if ;
2008-04-11 08:15:26 -04:00
2008-06-09 14:43:31 -04:00
: inotify-fd ( -- fd ) inotify get handle>> handle-fd ;
2008-04-11 08:15:26 -04:00
: check-existing ( wd -- )
watches get key? [
"Cannot open multiple monitors for the same file" throw
] when ;
: (add-watch) ( path mask -- wd )
inotify-fd -rot inotify_add_watch dup io-error dup check-existing ;
: add-watch ( path mask mailbox -- monitor )
[ [ absolute-path ] dip [ (add-watch) ] [ drop ] 2bi ] dip
2008-04-11 08:15:26 -04:00
<linux-monitor> [ ] [ ] [ wd>> ] tri watches get set-at ;
2008-06-09 14:43:31 -04:00
: check-inotify ( -- )
2008-04-11 08:15:26 -04:00
inotify get [
"Calling <monitor> outside with-monitors" throw
] unless ;
M: linux (monitor) ( path recursive? mailbox -- monitor )
swap [
<recursive-monitor>
] [
check-inotify
IN_CHANGE_EVENTS swap add-watch
] if ;
2008-05-15 00:23:12 -04:00
M: linux-monitor dispose* ( monitor -- )
[ [ wd>> ] [ watches>> ] bi delete-at ]
[
dup inotify>> [
2008-05-16 02:44:52 -04:00
[ inotify>> handle>> handle-fd ] [ wd>> ] bi
inotify_rm_watch io-error
] unless-disposed
]
[ call-next-method ]
tri ;
2008-04-11 08:15:26 -04:00
: ignore-flags? ( mask -- ? )
flags{
2008-04-11 08:15:26 -04:00
IN_DELETE_SELF
IN_MOVE_SELF
IN_UNMOUNT
IN_Q_OVERFLOW
IN_IGNORED
} bitand 0 > ;
2008-04-11 08:15:26 -04:00
: parse-action ( mask -- changed )
[
IN_CREATE +add-file+ ?flag
IN_DELETE +remove-file+ ?flag
IN_MODIFY +modify-file+ ?flag
IN_ATTRIB +modify-file+ ?flag
IN_MOVED_FROM +rename-file-old+ ?flag
IN_MOVED_TO +rename-file-new+ ?flag
drop
] { } make members ;
2008-04-11 08:15:26 -04:00
2008-06-27 22:34:18 -04:00
: parse-event-name ( event -- name )
2009-09-08 15:15:25 -04:00
dup len>> zero?
[ drop "" ] [ name>> utf8 alien>string ] if ;
2008-06-27 22:34:18 -04:00
2008-04-11 08:15:26 -04:00
: parse-file-notify ( buffer -- path changed )
2009-09-08 15:15:25 -04:00
dup mask>> ignore-flags? [
2008-04-11 08:15:26 -04:00
drop f f
] [
2009-09-08 15:15:25 -04:00
[ parse-event-name ] [ mask>> parse-action ] bi
2008-04-11 08:15:26 -04:00
] if ;
: events-exhausted? ( i buffer -- ? )
fill>> >= ;
2009-09-08 15:15:25 -04:00
: inotify-event@ ( i buffer -- inotify-event )
ptr>> <displaced-alien> inotify-event memory>struct ;
2008-04-11 08:15:26 -04:00
: next-event ( i buffer -- i buffer )
2dup inotify-event@
2009-09-08 15:15:25 -04:00
len>> inotify-event heap-size +
swap [ + ] dip ;
2008-04-11 08:15:26 -04:00
: parse-file-notifications ( i buffer -- )
2dup events-exhausted? [ 2drop ] [
2009-09-08 15:15:25 -04:00
2dup inotify-event@ dup wd>> wd>monitor
[ parse-file-notify ] dip queue-change
2008-04-11 08:15:26 -04:00
next-event parse-file-notifications
] if ;
: inotify-read-loop ( port -- )
2008-05-16 02:44:52 -04:00
dup check-disposed
2008-05-18 20:02:50 -04:00
dup wait-to-read drop
0 over buffer>> parse-file-notifications
0 over buffer>> buffer-reset
2008-04-11 08:15:26 -04:00
inotify-read-loop ;
: inotify-read-thread ( port -- )
[ inotify-read-loop ] curry ignore-errors ;
M: linux init-monitors
H{ } clone watches set
<inotify> [
[ inotify set ]
[
[ inotify-read-thread ] curry
"Linux monitor thread" spawn drop
] bi
] [
"Linux kernel version is too old" throw
] if* ;
M: linux dispose-monitors
inotify get dispose ;