Keep track of metaroles; add debug names

This commit is contained in:
Tony Garnock-Jones 2012-05-03 15:09:08 -04:00
parent 8f10b2ad4d
commit 21cc52f4b0
2 changed files with 104 additions and 50 deletions

View File

@ -62,7 +62,8 @@
[(set-member? active-handles local-addr) active-handles]
[else
(transition (set-add active-handles local-addr)
(spawn (udp-socket-manager local-addr)))])]))
(spawn (udp-socket-manager local-addr)
#:debug-name (list 'udp-socket local-addr)))])]))
(role 'handle-mapping-reaper
(topic-subscriber (handle-mapping (wild) (wild)) #:virtual? #t)
#:state active-handles
@ -96,7 +97,8 @@
(when (eq? state 'socket-is-open)
(spawn (lambda (dummy-pid)
(udp-close s)
(transition 'dummy (kill))))))
(transition 'dummy (kill)))
#:debug-name (list 'udp-socket-closer local-addr))))
[(udp-packet (== local-addr) (udp-address remote-host remote-port) body)
(udp-send-to s remote-host remote-port body)
state])

148
os2.rkt
View File

@ -93,7 +93,8 @@
;; A QuasiQueue<X> is a list of Xs in *reversed* order.
(struct vm (processes ;; Hash<PID, Process>
(struct vm (name ;; Any - for debugging complex VM trees
processes ;; Hash<PID, Process>
endpoints ;; Hash<EID, Endpoint>
next-process-id ;; PID
pending-actions ;; QuasiQueue<(cons PID Action)>
@ -104,9 +105,10 @@
;; topic) in a conversation.
(struct endpoint (id topics handlers) #:transparent)
;; A Process is an Exists State . (process PID State Set<EID>),
;; representing a VM process and its collection of active endpoints.
(struct process (id state endpoints) #:transparent)
;; A Process is an Exists State . (process Any PID State Set<EID>
;; Set<EID>), representing a VM process and its collection of active
;; endpoints at this level and at the VM's container's level.
(struct process (name id state endpoints meta-endpoints) #:transparent)
;; A Topic is a (topic Role Pattern Boolean), describing an Endpoint's
;; role in a conversation.
@ -137,8 +139,8 @@
;; (send-message Any Role)
(struct send-message (body role) #:prefab)
;;
;; (spawn BootK Maybe<TrapK<PID>>)
(struct spawn (main k) #:prefab)
;; (spawn BootK Maybe<TrapK<PID>> Any)
(struct spawn (main k debug-name) #:prefab)
;;
;; (kill Maybe<PID> Any)
(struct kill (pid reason) #:prefab)
@ -194,7 +196,7 @@
(define make-add-role add-role) ;; no special treatment required at present
(define (make-delete-role pre-eid [reason #f]) (delete-role pre-eid reason))
(define (make-send-message body [role 'publisher]) (send-message body role))
(define (make-spawn main [k #f]) (spawn main k))
(define (make-spawn main [k #f] #:debug-name [debug-name #f]) (spawn main k debug-name))
(define (make-kill [pid #f] #:reason [reason #f]) (kill pid reason))
(define (extend-transition t . more-actions)
@ -248,11 +250,12 @@
;;---------------------------------------------------------------------------
;; Core virtualizable virtual machine.
(define (make-vm boot)
(vm (hash)
(define (make-vm name boot)
(vm name
(hash)
(hash)
0
(list (cons -1 (spawn boot #f)))))
(list (cons -1 (spawn boot #f 'primordial-process)))))
(define (run-vm state)
(let loop ((remaining-actions (reverse (vm-pending-actions state)))
@ -267,22 +270,32 @@
[(cons (cons pid action) rest)
(match action
[(at-meta-level preaction)
(define transformed-preaction (transform-meta-action pid preaction))
(loop rest state (cons transformed-preaction outbound-actions))]
(let-values (((transformed-preaction state) (transform-meta-action pid preaction state)))
(loop rest state (cons transformed-preaction outbound-actions)))]
[(yield k)
(loop rest (run-ready state pid k) outbound-actions)]
[preaction
(loop rest (perform-action pid preaction state) outbound-actions)])])))
(let-values (((new-outbound-actions-rev state) (perform-action pid preaction state)))
(loop rest state (append new-outbound-actions-rev outbound-actions)))])])))
(define (vm-idle? state)
(null? (vm-pending-actions state)))
(define (collect-dead-processes state)
;; dns-read-driver is being collected because it only has a metarole.%%%
(define (process-alive? pid p)
(or (not (set-empty? (process-endpoints p)))
(not (set-empty? (process-meta-endpoints p)))
(ormap (lambda (entry) (= (car entry) pid))
(vm-pending-actions state))))
(struct-copy vm state
[processes (for/hash ([(pid p) (in-hash (vm-processes state))]
#:when (or (not (set-empty? (process-endpoints p)))
(ormap (lambda (entry) (= (car entry) pid))
(vm-pending-actions state))))
#:when (or (process-alive? pid p)
(begin (printf "~a PID ~v (~a) garbage-collected~n"
(vm-name state)
pid
(process-name p))
#f)))
(values pid p))]))
(define (send-to-user failure-proc f . args)
@ -299,11 +312,16 @@
(define (perform-action pid preaction state)
(match preaction
[(add-role pre-eid topics hs) (do-subscribe pid pre-eid (ensure-topic-union topics) hs state)]
[(delete-role pre-eid reason) (do-unsubscribe pid pre-eid reason state)]
[(send-message body role) (route-and-deliver role body state)]
[(spawn main k) (do-spawn pid main k state)]
[(kill pid-to-kill reason) (do-kill (or pid-to-kill pid) reason state)]))
[(add-role pre-eid topics hs)
(values '() (do-subscribe pid pre-eid (ensure-topic-union topics) hs state))]
[(delete-role pre-eid reason)
(values '() (do-unsubscribe pid pre-eid reason state))]
[(send-message body role)
(values '() (route-and-deliver role body state))]
[(spawn main k debug-name)
(values '() (do-spawn pid main k debug-name state))]
[(kill pid-to-kill reason)
(do-kill (or pid-to-kill pid) reason state)]))
(define (do-subscribe pid pre-eid topics hs state)
(cond
@ -322,9 +340,15 @@
(define ((add-process-eid new-eid) p)
(struct-copy process p [endpoints (set-add (process-endpoints p) new-eid)]))
(define ((add-process-meta-eid new-eid) p)
(struct-copy process p [meta-endpoints (set-add (process-meta-endpoints p) new-eid)]))
(define ((remove-process-eid old-eid) p)
(struct-copy process p [endpoints (set-remove (process-endpoints p) old-eid)]))
(define ((remove-process-meta-eid old-eid) p)
(struct-copy process p [meta-endpoints (set-remove (process-meta-endpoints p) old-eid)]))
(define (install-endpoint state new-eid new-endpoint)
(struct-copy vm state [endpoints (hash-set (vm-endpoints state) new-eid new-endpoint)]))
@ -394,36 +418,52 @@
(match-define (endpoint (eid pid _) _ (handlers _ _ message-handler)) e)
(run-trapk state pid message-handler message-topic body)))
(define (do-spawn spawning-pid main k state)
(define (do-spawn spawning-pid main k debug-name state)
(define new-pid (vm-next-process-id state))
(define new-name (or debug-name new-pid))
(match-define (transition initial-state initial-actions)
(cond
[(procedure? main) (send-to-user (lambda (e) (transition #f (kill #f e))) main new-pid)]
[(transition? main) main]))
(define initial-process (process new-pid initial-state (set)))
(define initial-process (process new-name new-pid initial-state (set) (set)))
(define spawned-state
(struct-copy vm (enqueue-actions state new-pid initial-actions)
[processes (hash-set (vm-processes state) new-pid initial-process)]
[next-process-id (+ new-pid 1)]))
(printf "~a PID ~v (~a) started~n" (vm-name state) new-pid new-name)
(run-trapk spawned-state spawning-pid k new-pid))
(define (print-kill pid-to-kill reason)
(define (print-kill vm-name pid-to-kill process-name reason)
(cond
[(eq? reason #f) (printf "PID ~v exited normally~n" pid-to-kill)]
[(eq? reason #f) (printf "~a PID ~v (~a) exited normally~n"
vm-name
pid-to-kill
process-name)]
[(exn? reason) ((error-display-handler)
(format "PID ~v exited with exception~n~a" pid-to-kill (exn-message reason))
(format "~a PID ~v (~a) exited with exception~n~a"
vm-name
pid-to-kill
process-name
(exn-message reason))
reason)]
[else (printf "PID ~v exited with reason: ~a~n" pid-to-kill reason)]))
[else (printf "~a PID ~v (~a) exited with reason: ~a~n"
vm-name
pid-to-kill
process-name
reason)]))
(define (do-kill pid-to-kill reason state)
(cond
[(hash-has-key? (vm-processes state) pid-to-kill)
(print-kill pid-to-kill reason)
(define dying-endpoints (process-endpoints (hash-ref (vm-processes state) pid-to-kill)))
(let* ((state (for/fold ([state state]) ([eid (in-set dying-endpoints)])
(do-unsubscribe pid-to-kill (eid-pre-eid eid) reason state))))
(struct-copy vm state [processes (hash-remove (vm-processes state) pid-to-kill)]))]
[else state]))
(define dying-process (hash-ref (vm-processes state) pid-to-kill))
(print-kill (vm-name state) pid-to-kill (process-name dying-process) reason)
(let* ((state (for/fold ([state state]) ([eid (in-set (process-endpoints dying-process))])
(do-unsubscribe pid-to-kill (eid-pre-eid eid) reason state)))
(new-outbound-actions (for/list ([eid (in-set (process-meta-endpoints dying-process))])
(delete-role eid reason))))
(values new-outbound-actions
(struct-copy vm state [processes (hash-remove (vm-processes state) pid-to-kill)])))]
[else (values '() state)]))
(define (run-trapk state pid trap-k . args)
(if trap-k
@ -472,28 +512,40 @@
[pending-actions (append (reverse flat-actions) (vm-pending-actions state))]))
(define (((wrap-trapk pid trapk) . args) state)
(apply run-trapk state pid trapk args))
(if (hash-has-key? (vm-processes state) pid)
(run-vm (apply run-trapk state pid trapk args))
state))
(define (transform-meta-action pid preaction)
(define (transform-meta-action pid preaction state)
(match preaction
[(add-role pre-eid topics hs)
(add-role (eid pid pre-eid)
topics
(handlers (wrap-trapk pid (handlers-presence hs))
(wrap-trapk pid (handlers-absence hs))
(wrap-trapk pid (handlers-message hs))))]
(define new-eid (eid pid pre-eid))
(values (add-role new-eid
topics
(handlers (wrap-trapk pid (handlers-presence hs))
(wrap-trapk pid (handlers-absence hs))
(wrap-trapk pid (handlers-message hs))))
(if (hash-has-key? (vm-processes state) pid)
(generic-update-process state pid (add-process-meta-eid new-eid))
state))]
[(delete-role pre-eid reason)
(delete-role (eid pid pre-eid) reason)]
[(? send-message? p) p]
[(spawn main k)
(spawn main (wrap-trapk pid k))]
[(? kill? p) p]))
(define old-eid (eid pid pre-eid))
(values (delete-role old-eid reason)
(if (hash-has-key? (vm-processes state) pid)
(generic-update-process state pid (remove-process-meta-eid old-eid))
state))]
[(? send-message? p)
(values p state)]
[(spawn main k debug-name)
(values (spawn main (wrap-trapk pid k) debug-name) state)]
[(? kill? p)
(values p state)]))
(define (nested-vm boot)
(lambda (self-pid) (run-vm (make-vm boot))))
(define (nested-vm name boot)
(lambda (self-pid) (run-vm (make-vm name boot))))
(define (ground-vm boot)
(let loop ((state (make-vm boot)))
(let loop ((state (make-vm 'ground-vm boot)))
(match (run-vm state)
[(transition state actions)
(define is-blocking?