-
Notifications
You must be signed in to change notification settings - Fork 2
/
intensive-watch.rkt
72 lines (60 loc) · 2.22 KB
/
intensive-watch.rkt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#lang racket/base
(require
racket/contract)
(provide
(contract-out
[intensive-watch (->* () (path-on-disk?) thread?)]))
;; ------------------------------------------------------------------
;; Implementation
(require
racket/file
racket/list
"./lists.rkt"
"./filesystem.rkt"
"./threads.rkt")
(define-values (report-activity report-status) (report-iface 'intensive))
(define (create-dedicated-thread path should-signal)
(when should-signal (report-activity 'add path))
(define th (create-path-monitor-thread path))
(report-status 'new-thread th path)
th)
(define (create-path-monitor-thread path)
(if (equal? (file-kind path) 'directory)
(monitor-directory path)
(monitor-file path)))
; Use to return new version of thread pool
(define (respond-to-listing-change old new signal-change?)
(define diff (list-diff old new))
(define added (car diff))
(define removed (cdr diff))
(for ([path added]) (create-dedicated-thread path signal-change?))
(for ([path removed]) (report-activity 'remove path)))
; Monitors only changes.
; Add/remove events come from directory listing diffs.
(define (monitor-file path)
(define (shutdown) (report-status 'thread-done path))
(thread
(lambda () (let loop ()
(with-handlers ([exn:fail? (lambda (ex) (shutdown))])
(sync/enable-break (filesystem-change-evt path))
(if (file-exists? path)
(begin
(report-activity 'change path)
(loop))
(shutdown)))))))
(define (monitor-directory path)
(thread
(λ ()
(let loop ([listing-memo '()] [should-signal #f])
(if (directory-exists? path)
(with-handlers ([exn:fail:filesystem? (lambda (ex) (stop-monitoring-directory path))])
(let ([next-listing (ls path)])
(respond-to-listing-change listing-memo next-listing should-signal)
(sync/enable-break (filesystem-change-evt path))
(loop next-listing #t)))
(stop-monitoring-directory path))))))
(define (stop-monitoring-directory path)
(unless (directory-exists? path) (report-activity 'remove path))
(report-status 'thread-done path))
(define (intensive-watch [path (current-directory)])
(create-dedicated-thread path #f))