yet more v4-isms
svn: r11684
This commit is contained in:
parent
0c0630d50d
commit
5541890dd5
|
@ -191,10 +191,8 @@
|
|||
;; This code will hack textualization of text boxes
|
||||
|
||||
(define (insert-to-editor editor . xs)
|
||||
(for-each (lambda (x)
|
||||
(send editor insert
|
||||
(if (string? x) x (make-object editor-snip% x))))
|
||||
xs))
|
||||
(for ([x xs])
|
||||
(send editor insert (if (string? x) x (make-object editor-snip% x)))))
|
||||
|
||||
;; support for "text-box%"
|
||||
(define text-box-sc
|
||||
|
@ -284,10 +282,9 @@
|
|||
'(ok-cancel caution)))))
|
||||
(error* "Aborting...")))
|
||||
;; This will create copies of the original files
|
||||
;; (for-each (lambda (file)
|
||||
;; (with-output-to-file (car file)
|
||||
;; (lambda () (display (cadr file)) (flush-output))))
|
||||
;; files)
|
||||
;; (for ([file files])
|
||||
;; (with-output-to-file (car file)
|
||||
;; (lambda () (display (cadr file)) (flush-output))))
|
||||
(let* ([pfx-len (string-length markup-prefix)]
|
||||
[line-len (- maxwidth pfx-len)]
|
||||
[=s (lambda (n) (if (<= 0 n) (make-string n #\=) ""))]
|
||||
|
@ -301,14 +298,12 @@
|
|||
(display ===)
|
||||
(newline))
|
||||
(parameterize ([current-output-port (open-output-bytes)])
|
||||
(for-each (lambda (file)
|
||||
(sep (car file))
|
||||
(parameterize ([current-input-port
|
||||
(open-input-bytes (cadr file))]
|
||||
[current-processed-file (car file)])
|
||||
(input->process->output
|
||||
maxwidth textualize? untabify? prefix-re)))
|
||||
files)
|
||||
(for ([file files])
|
||||
(sep (car file))
|
||||
(parameterize ([current-input-port (open-input-bytes (cadr file))]
|
||||
[current-processed-file (car file)])
|
||||
(input->process->output
|
||||
maxwidth textualize? untabify? prefix-re)))
|
||||
(get-output-bytes (current-output-port))))))
|
||||
|
||||
;; ============================================================================
|
||||
|
@ -394,10 +389,9 @@
|
|||
[user-post (id 'user-post)]
|
||||
[(body ...) (syntax-case #'(body ...) ()
|
||||
[() #'(void)] [_ #'(body ...)])])
|
||||
(for-each (lambda (x)
|
||||
(unless (memq (car x) got)
|
||||
(raise-syntax-error #f "unknown keyword" stx (cadr x))))
|
||||
keyvals)
|
||||
(for ([x keyvals])
|
||||
(unless (memq (car x) got)
|
||||
(raise-syntax-error #f "unknown keyword" stx (cadr x))))
|
||||
#'(begin
|
||||
(provide checker)
|
||||
(define checker
|
||||
|
@ -476,10 +470,8 @@
|
|||
(set-run-status "creating text file")
|
||||
(with-output-to-file text-file #:exists 'truncate
|
||||
(lambda ()
|
||||
(for-each (lambda (user)
|
||||
(prefix-line
|
||||
(user-substs user student-line)))
|
||||
users)
|
||||
(for ([user users])
|
||||
(prefix-line (user-substs user student-line)))
|
||||
(for-each prefix-line/substs extra-lines)
|
||||
(for-each prefix-line/substs
|
||||
(or (thread-cell-ref added-lines) '()))
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
(error (apply format fmt args)))
|
||||
|
||||
(define (write+flush port . xs)
|
||||
(for-each (lambda (x) (write x port) (newline port)) xs)
|
||||
(for ([x xs]) (write x port) (newline port))
|
||||
(flush-output port))
|
||||
|
||||
(define-struct alist (name [l #:mutable]))
|
||||
|
@ -87,20 +87,18 @@
|
|||
;; SUCCESS, or things that are newer in the main submission
|
||||
;; directory are kept (but subdirs in SUCCESS will are copied as
|
||||
;; is))
|
||||
(for-each
|
||||
(lambda (f)
|
||||
(define dir/f (build-path dir f))
|
||||
(cond [(not (or (file-exists? f) (directory-exists? f)))
|
||||
;; f is in dir but not in the working directory
|
||||
(copy-directory/files dir/f f)]
|
||||
[(or (<= (file-or-directory-modify-seconds f)
|
||||
(file-or-directory-modify-seconds dir/f))
|
||||
(and (file-exists? f) (file-exists? dir/f)
|
||||
(not (= (file-size f) (file-size dir/f)))))
|
||||
;; f is newer in dir than in the working directory
|
||||
(delete-directory/files f)
|
||||
(copy-directory/files dir/f f)]))
|
||||
(directory-list dir)))))
|
||||
(for ([f (directory-list dir)])
|
||||
(define dir/f (build-path dir f))
|
||||
(cond [(not (or (file-exists? f) (directory-exists? f)))
|
||||
;; f is in dir but not in the working directory
|
||||
(copy-directory/files dir/f f)]
|
||||
[(or (<= (file-or-directory-modify-seconds f)
|
||||
(file-or-directory-modify-seconds dir/f))
|
||||
(and (file-exists? f) (file-exists? dir/f)
|
||||
(not (= (file-size f) (file-size dir/f)))))
|
||||
;; f is newer in dir than in the working directory
|
||||
(delete-directory/files f)
|
||||
(copy-directory/files dir/f f)])))))
|
||||
|
||||
(define cleanup-sema (make-semaphore 1))
|
||||
(define (cleanup-submission dir)
|
||||
|
@ -118,14 +116,12 @@
|
|||
|
||||
(define (cleanup-all-submissions)
|
||||
(log-line "Cleaning up all submission directories")
|
||||
(for-each (lambda (pset)
|
||||
(when (directory-exists? pset) ; just in case
|
||||
(parameterize ([current-directory pset])
|
||||
(for-each (lambda (sub)
|
||||
(when (directory-exists? sub) ; filter non-dirs
|
||||
(cleanup-submission sub)))
|
||||
(directory-list)))))
|
||||
(get-conf 'all-dirs)))
|
||||
(for ([pset (get-conf 'all-dirs)]
|
||||
#:when (directory-exists? pset)) ; just in case
|
||||
(parameterize ([current-directory pset])
|
||||
(for ([sub (directory-list)]
|
||||
#:when (directory-exists? sub)) ; filter non-dirs
|
||||
(cleanup-submission sub)))))
|
||||
|
||||
;; On startup, we scan all submissions, then repeat at random intervals (only
|
||||
;; if clients connected in that time), and check often for changes in the
|
||||
|
@ -193,15 +189,11 @@
|
|||
;; we have a submission, need to create a directory if needed, make
|
||||
;; sure that no users submitted work with someone else
|
||||
(unless (directory-exists? dirname)
|
||||
(for-each
|
||||
(lambda (dir)
|
||||
(for-each
|
||||
(lambda (d)
|
||||
(when (member d users)
|
||||
(error* "bad submission: ~a has an existing submission (~a)"
|
||||
d dir)))
|
||||
(regexp-split #rx" *[+] *" (path->string dir))))
|
||||
(directory-list))
|
||||
(for* ([dir (directory-list)]
|
||||
[d (regexp-split #rx" *[+] *" (path->string dir))])
|
||||
(when (member d users)
|
||||
(error* "bad submission: ~a has an existing submission (~a)"
|
||||
d dir)))
|
||||
(make-directory dirname))
|
||||
(parameterize ([current-directory dirname]
|
||||
[current-messenger
|
||||
|
@ -378,9 +370,9 @@
|
|||
(error* "the username \"checker.ss\" is reserved"))
|
||||
(when (get-user-data username)
|
||||
(error* "username already exists: `~a'" username))
|
||||
(for-each (lambda (str info)
|
||||
(check-field str (cadr info) (car info) (caddr info)))
|
||||
extra-fields (get-conf 'extra-fields))
|
||||
(for ([str extra-fields]
|
||||
[info (get-conf 'extra-fields)])
|
||||
(check-field str (cadr info) (car info) (caddr info)))
|
||||
(wait-for-lock "+newuser+")
|
||||
(log-line "create user: ~a" username)
|
||||
(hook 'user-create `([username ,username] [fields ,extra-fields]))
|
||||
|
@ -405,9 +397,9 @@
|
|||
(error* "changing information not allowed: ~a" username))
|
||||
(when (equal? new-data old-data)
|
||||
(error* "no fields changed: ~a" username))
|
||||
(for-each (lambda (str info)
|
||||
(check-field str (cadr info) (car info) (caddr info)))
|
||||
(cdr new-data) (get-conf 'extra-fields))
|
||||
(for ([str (cdr new-data)]
|
||||
[info (get-conf 'extra-fields)])
|
||||
(check-field str (cadr info) (car info) (caddr info)))
|
||||
(log-line "change info for ~a ~s -> ~s" username old-data new-data)
|
||||
(unless (equal? (cdr new-data) (cdr old-data)) ; not for password change
|
||||
(hook 'user-change `([username ,username]
|
||||
|
|
|
@ -1,18 +1,17 @@
|
|||
(module hooker mzscheme
|
||||
(require "config.ss" "logger.ss" "reloadable.ss")
|
||||
#lang scheme/base
|
||||
|
||||
(provide hook)
|
||||
(require "config.ss" "logger.ss" "reloadable.ss")
|
||||
|
||||
(define hook-file #f)
|
||||
(define hook-proc #f)
|
||||
(provide hook)
|
||||
|
||||
(define (hook what alist)
|
||||
(let ([file (get-conf 'hook-file)])
|
||||
(when file
|
||||
(unless (equal? file hook-file)
|
||||
(set! hook-file file)
|
||||
(set! hook-proc (auto-reload-procedure `(file ,(path->string file))
|
||||
'hook)))
|
||||
(hook-proc what (current-session) alist))))
|
||||
(define hook-file #f)
|
||||
(define hook-proc #f)
|
||||
|
||||
)
|
||||
(define (hook what alist)
|
||||
(let ([file (get-conf 'hook-file)])
|
||||
(when file
|
||||
(unless (equal? file hook-file)
|
||||
(set! hook-file file)
|
||||
(set! hook-proc (auto-reload-procedure `(file ,(path->string file))
|
||||
'hook)))
|
||||
(hook-proc what (current-session) alist))))
|
||||
|
|
|
@ -1,64 +1,63 @@
|
|||
(module lock mzscheme
|
||||
(require mzlib/list)
|
||||
#lang scheme/base
|
||||
|
||||
(provide wait-for-lock)
|
||||
(provide wait-for-lock)
|
||||
|
||||
;; wait-for-lock : string -> void
|
||||
;; Gets a lock on `user' for the calling thread; the lock lasts until the
|
||||
;; calling thread terminates. If the lock was actually acquired, then on
|
||||
;; release the cleanup-thunk will be executed (unless it is #f), even if it
|
||||
;; was released when the acquiring thread crashed.
|
||||
;; *** Warning: It's vital that a clean-up thunk doesn't raise an exception,
|
||||
;; since this will kill the lock thread which will lock down everything
|
||||
(define (wait-for-lock user . cleanup-thunk)
|
||||
(let ([s (make-semaphore)])
|
||||
(channel-put req-ch
|
||||
(make-req (thread-dead-evt (current-thread)) user s
|
||||
(and (pair? cleanup-thunk) (car cleanup-thunk))))
|
||||
(semaphore-wait s)))
|
||||
;; wait-for-lock : string -> void
|
||||
;; Gets a lock on `user' for the calling thread; the lock lasts until the
|
||||
;; calling thread terminates. If the lock was actually acquired, then on
|
||||
;; release the cleanup-thunk will be executed (unless it is #f), even if it
|
||||
;; was released when the acquiring thread crashed.
|
||||
;; *** Warning: It's vital that a clean-up thunk doesn't raise an exception,
|
||||
;; since this will kill the lock thread which will lock down everything
|
||||
(define (wait-for-lock user . cleanup-thunk)
|
||||
(let ([s (make-semaphore)])
|
||||
(channel-put req-ch
|
||||
(make-req (thread-dead-evt (current-thread)) user s
|
||||
(and (pair? cleanup-thunk) (car cleanup-thunk))))
|
||||
(semaphore-wait s)))
|
||||
|
||||
(define req-ch (make-channel))
|
||||
(define req-ch (make-channel))
|
||||
|
||||
(define-struct req (thread-dead-evt user sema cleanup-thunk))
|
||||
(define-struct req (thread-dead-evt user sema cleanup-thunk))
|
||||
|
||||
(thread
|
||||
(lambda ()
|
||||
(let loop ([locks null]
|
||||
[reqs null])
|
||||
(let-values ([(locks reqs)
|
||||
;; Try to satisfy lock requests:
|
||||
(let loop ([reqs (reverse reqs)]
|
||||
[locks locks]
|
||||
[new-reqs null])
|
||||
(if (null? reqs)
|
||||
(values locks new-reqs)
|
||||
(let ([req (car reqs)]
|
||||
[rest (cdr reqs)])
|
||||
(if (assoc (req-user req) locks)
|
||||
;; Lock not available:
|
||||
(loop rest locks (cons req new-reqs))
|
||||
;; Lock is available, so take it:
|
||||
(begin (semaphore-post (req-sema req))
|
||||
(loop (cdr reqs)
|
||||
(cons (cons (req-user req) req) locks)
|
||||
new-reqs))))))])
|
||||
(sync
|
||||
(handle-evt req-ch (lambda (req) (loop locks (cons req reqs))))
|
||||
;; Release a lock whose thread is gone:
|
||||
(apply choice-evt
|
||||
(map (lambda (name+req)
|
||||
(handle-evt
|
||||
(req-thread-dead-evt (cdr name+req))
|
||||
(lambda (v)
|
||||
;; releasing a lock => run cleanup
|
||||
(cond [(req-cleanup-thunk (cdr name+req))
|
||||
=> (lambda (t) (t))])
|
||||
(loop (remq name+req locks) reqs))))
|
||||
locks))
|
||||
;; Throw away a request whose thread is gone:
|
||||
(apply choice-evt
|
||||
(map (lambda (req)
|
||||
(handle-evt
|
||||
(req-thread-dead-evt req)
|
||||
(lambda (v) (loop locks (remq req reqs)))))
|
||||
reqs))))))))
|
||||
(thread
|
||||
(lambda ()
|
||||
(let loop ([locks null]
|
||||
[reqs null])
|
||||
(let-values ([(locks reqs)
|
||||
;; Try to satisfy lock requests:
|
||||
(let loop ([reqs (reverse reqs)]
|
||||
[locks locks]
|
||||
[new-reqs null])
|
||||
(if (null? reqs)
|
||||
(values locks new-reqs)
|
||||
(let ([req (car reqs)]
|
||||
[rest (cdr reqs)])
|
||||
(if (assoc (req-user req) locks)
|
||||
;; Lock not available:
|
||||
(loop rest locks (cons req new-reqs))
|
||||
;; Lock is available, so take it:
|
||||
(begin (semaphore-post (req-sema req))
|
||||
(loop (cdr reqs)
|
||||
(cons (cons (req-user req) req) locks)
|
||||
new-reqs))))))])
|
||||
(sync
|
||||
(handle-evt req-ch (lambda (req) (loop locks (cons req reqs))))
|
||||
;; Release a lock whose thread is gone:
|
||||
(apply choice-evt
|
||||
(map (lambda (name+req)
|
||||
(handle-evt
|
||||
(req-thread-dead-evt (cdr name+req))
|
||||
(lambda (v)
|
||||
;; releasing a lock => run cleanup
|
||||
(cond [(req-cleanup-thunk (cdr name+req))
|
||||
=> (lambda (t) (t))])
|
||||
(loop (remq name+req locks) reqs))))
|
||||
locks))
|
||||
;; Throw away a request whose thread is gone:
|
||||
(apply choice-evt
|
||||
(map (lambda (req)
|
||||
(handle-evt
|
||||
(req-thread-dead-evt req)
|
||||
(lambda (v) (loop locks (remq req reqs)))))
|
||||
reqs)))))))
|
||||
|
|
|
@ -1,48 +1,46 @@
|
|||
(module reloadable mzscheme
|
||||
#lang scheme/base
|
||||
|
||||
(require syntax/moddep "logger.ss")
|
||||
(require syntax/moddep "logger.ss")
|
||||
|
||||
(provide reload-module)
|
||||
(define (reload-module modspec path)
|
||||
;; the path argument is not needed (could use resolve-module-path here),
|
||||
;; but its always known when this function is called
|
||||
(let* ([name ((current-module-name-resolver) modspec #f #f)])
|
||||
(log-line "(re)loading module from ~a" modspec)
|
||||
(parameterize ([current-module-declare-name name]
|
||||
[compile-enforce-module-constants #f])
|
||||
(namespace-require '(only mzscheme module #%top-interaction))
|
||||
(load/use-compiled path))))
|
||||
(provide reload-module)
|
||||
(define (reload-module modspec path)
|
||||
;; the path argument is not needed (could use resolve-module-path here), but
|
||||
;; its always known when this function is called
|
||||
(let* ([name ((current-module-name-resolver) modspec #f #f)])
|
||||
(log-line "(re)loading module from ~a" modspec)
|
||||
(parameterize ([current-module-declare-name name]
|
||||
[compile-enforce-module-constants #f])
|
||||
(namespace-require '(only mzscheme module #%top-interaction))
|
||||
(load/use-compiled path))))
|
||||
|
||||
;; pulls out a value from a module, reloading the module if its source file
|
||||
;; was modified
|
||||
(provide auto-reload-value)
|
||||
(define module-times (make-hash-table 'equal))
|
||||
(define (auto-reload-value modspec valname)
|
||||
(let* ([path (resolve-module-path modspec #f)]
|
||||
[last (hash-table-get module-times path #f)]
|
||||
[cur (file-or-directory-modify-seconds path)])
|
||||
(unless (equal? cur last)
|
||||
(hash-table-put! module-times path cur)
|
||||
(reload-module modspec path))
|
||||
(dynamic-require modspec valname)))
|
||||
;; pulls out a value from a module, reloading the module if its source file was
|
||||
;; modified
|
||||
(provide auto-reload-value)
|
||||
(define module-times (make-hash))
|
||||
(define (auto-reload-value modspec valname)
|
||||
(let* ([path (resolve-module-path modspec #f)]
|
||||
[last (hash-ref module-times path #f)]
|
||||
[cur (file-or-directory-modify-seconds path)])
|
||||
(unless (equal? cur last)
|
||||
(hash-set! module-times path cur)
|
||||
(reload-module modspec path))
|
||||
(dynamic-require modspec valname)))
|
||||
|
||||
(define poll-freq 2000.0) ; poll at most once every two seconds
|
||||
(define poll-freq 2000.0) ; poll at most once every two seconds
|
||||
|
||||
;; pulls out a procedure from a module, and returns a wrapped procedure that
|
||||
;; automatically reloads the module if the file was changed whenever the
|
||||
;; procedure is used
|
||||
(provide auto-reload-procedure)
|
||||
(define (auto-reload-procedure modspec procname)
|
||||
(let ([path (resolve-module-path modspec #f)] [date #f] [proc #f] [poll #f])
|
||||
(define (reload)
|
||||
(unless (and proc (< (- (current-inexact-milliseconds) poll) poll-freq))
|
||||
(set! poll (current-inexact-milliseconds))
|
||||
(let ([cur (file-or-directory-modify-seconds path)])
|
||||
(unless (equal? cur date)
|
||||
(set! date cur)
|
||||
(reload-module modspec path)
|
||||
(set! proc (dynamic-require modspec procname))))))
|
||||
(reload)
|
||||
(lambda xs (reload) (apply proc xs))))
|
||||
|
||||
)
|
||||
;; pulls out a procedure from a module, and returns a wrapped procedure that
|
||||
;; automatically reloads the module if the file was changed whenever the
|
||||
;; procedure is used
|
||||
(provide auto-reload-procedure)
|
||||
(define (auto-reload-procedure modspec procname)
|
||||
(let ([path (resolve-module-path modspec #f)] [date #f] [proc #f] [poll #f])
|
||||
(define (reload)
|
||||
(unless (and proc (< (- (current-inexact-milliseconds) poll) poll-freq))
|
||||
(set! poll (current-inexact-milliseconds))
|
||||
(let ([cur (file-or-directory-modify-seconds path)])
|
||||
(unless (equal? cur date)
|
||||
(set! date cur)
|
||||
(reload-module modspec path)
|
||||
(set! proc (dynamic-require modspec procname))))))
|
||||
(reload)
|
||||
(lambda xs (reload) (apply proc xs))))
|
||||
|
|
|
@ -1,21 +1,19 @@
|
|||
(module run-status mzscheme
|
||||
#lang scheme/base
|
||||
|
||||
(provide current-run-status-box set-run-status
|
||||
current-messenger message)
|
||||
(provide current-run-status-box set-run-status
|
||||
current-messenger message)
|
||||
|
||||
;; current-run-status-box is used to let the client know where we are in the
|
||||
;; submission process.
|
||||
(define current-run-status-box (make-parameter #f))
|
||||
;; current-run-status-box is used to let the client know where we are in the
|
||||
;; submission process.
|
||||
(define current-run-status-box (make-parameter #f))
|
||||
|
||||
;; current-messenger is a function that will send a message to the client.
|
||||
(define current-messenger (make-parameter #f))
|
||||
(define (message . args)
|
||||
(let ([messenger (current-messenger)])
|
||||
(and messenger (apply messenger args))))
|
||||
;; current-messenger is a function that will send a message to the client.
|
||||
(define current-messenger (make-parameter #f))
|
||||
(define (message . args)
|
||||
(let ([messenger (current-messenger)])
|
||||
(and messenger (apply messenger args))))
|
||||
|
||||
;; Set the current-run-status-box and send a message.
|
||||
(define (set-run-status s)
|
||||
(let ([b (current-run-status-box)])
|
||||
(when b (set-box! b s) (message s))))
|
||||
|
||||
)
|
||||
;; Set the current-run-status-box and send a message.
|
||||
(define (set-run-status s)
|
||||
(let ([b (current-run-status-box)])
|
||||
(when b (set-box! b s) (message s))))
|
||||
|
|
Loading…
Reference in New Issue
Block a user