diff --git a/src/dryad.lisp b/src/dryad.lisp index 6552672..0ee8de6 100644 --- a/src/dryad.lisp +++ b/src/dryad.lisp @@ -63,8 +63,7 @@ ;;; passive DRYAD message handlers ;;; -(define-message-handler handler-message-sow - ((dryad dryad) (message message-sow)) +(define-message-handler ((dryad dryad) (message message-sow)) "Adjoin a new node to the problem graph. NOTE: In the basic implementation, these messages must be waiting for the DRYAD on launch." @@ -84,8 +83,7 @@ NOTE: In the basic implementation, these messages must be waiting for the DRYAD (gethash node-address (dryad-sprouted? dryad)) nil) node-address)) -(define-message-handler handler-message-discover - ((dryad dryad) (message message-discover)) +(define-message-handler ((dryad dryad) (message message-discover)) "Handles a DISCOVER message, sent by a BLOSSOM-NODE which expects a list of other BLOSSOM-NODE addresses to which it should send PINGs." (let ((channels (loop :for address :being :the :hash-keys :of (dryad-ids dryad) @@ -98,8 +96,7 @@ NOTE: In the basic implementation, these messages must be waiting for the DRYAD :channels-to-try channels :id (message-discover-id message))))) -(define-message-handler handler-message-sprout - ((dryad dryad) (message message-sprout)) +(define-message-handler ((dryad dryad) (message message-sprout)) "Handles a SPROUT message, indicating that a BLOSSOM-NODE has been matched (for the first time)." (with-slots (address) message (a:when-let ((id (gethash address (dryad-ids dryad)))) @@ -108,8 +105,7 @@ NOTE: In the basic implementation, these messages must be waiting for the DRYAD :id id) (setf (gethash address (dryad-sprouted? dryad)) t)))) -(define-rpc-handler handler-message-wilting - ((dryad dryad) (message message-wilting)) +(define-rpc-handler ((dryad dryad) (message message-wilting)) "Handles a wilting message, indicating that a BLOSSOM-NODE is dying." (with-slots (address) message (let ((id (gethash address (dryad-ids dryad)))) @@ -117,30 +113,16 @@ NOTE: In the basic implementation, these messages must be waiting for the DRYAD (remhash address (dryad-sprouted? dryad)) id))) -(define-rpc-handler handler-message-add-macrovertex - ((dryad dryad) (message message-add-macrovertex)) +(define-rpc-handler ((dryad dryad) (message message-add-macrovertex)) "Handles an add-macrovertex message by keeping track of the provided address." (with-slots (address) message (setf (gethash address (dryad-macrovertices dryad)) t))) -(define-rpc-handler handler-message-remove-macrovertex - ((dryad dryad) (message message-remove-macrovertex)) +(define-rpc-handler ((dryad dryad) (message message-remove-macrovertex)) "Handles a remove-macrovertex message by forgetting about the provided address." (with-slots (address) message (remhash address (dryad-macrovertices dryad)))) -;;; -;;; install the handlers into the dispatch table -;;; - -(define-message-dispatch dryad - (message-sow 'handler-message-sow) - (message-sprout 'handler-message-sprout) - (message-discover 'handler-message-discover) - (message-wilting 'handler-message-wilting) - (message-add-macrovertex 'handler-message-add-macrovertex) - (message-remove-macrovertex 'handler-message-remove-macrovertex)) - ;;; ;;; DRYAD command definitions ;;; diff --git a/src/lock.lisp b/src/lock.lisp index 892530f..dcb3bab 100644 --- a/src/lock.lisp +++ b/src/lock.lisp @@ -25,8 +25,7 @@ ;;; blossom-node handlers ;;; -(define-message-handler handle-message-lock - ((node blossom-node) (message message-lock)) +(define-message-handler ((node blossom-node) (message message-lock)) "Prepares a BLOSSOM-NODE to be locked." (when (blossom-node-wilting node) (send-message (message-reply-channel message) diff --git a/src/node.lisp b/src/node.lisp index 988dced..a31271f 100644 --- a/src/node.lisp +++ b/src/node.lisp @@ -297,8 +297,7 @@ evalutes to (:method ((x string) (y string)) (if (string< x y) x y))) -(define-message-subordinate handle-message-id-query - ((node blossom-node) (message message-id-query)) +(define-message-subordinate ((node blossom-node) (message message-id-query)) "Replies with the minimum ID at this macrovertex." (cond ((null (blossom-node-petals node)) @@ -329,8 +328,7 @@ evalutes to ;; We enable this by changing the tree's pingability, and thus permitting the ;; tree to respond to a safe subset (or to all) of PING requests. -(define-broadcast-handler handle-message-broadcast-pingability - ((node blossom-node) (message message-broadcast-pingability)) +(define-broadcast-handler ((node blossom-node) (message message-broadcast-pingability)) "Changes the pingability of `NODE' (and children / petals) to `PING-TYPE'." (with-slots (ping-type) message (log-entry :entry-type ':changing-pingability @@ -348,8 +346,7 @@ evalutes to ;; NOTE GH-140: these are probably pretty easy to abuse. perhaps it would be ;; better to implement the micromessages after all. -(define-rpc-handler handle-message-set - ((node blossom-node) (message message-set)) +(define-rpc-handler ((node blossom-node) (message message-set)) "Handles a remote SETF request." (with-slots (slots values) message (loop :for slot :in slots @@ -357,15 +354,13 @@ evalutes to :do (setf (slot-value node slot) value)) (values))) -(define-rpc-handler handle-message-push - ((node blossom-node) (message message-push)) +(define-rpc-handler ((node blossom-node) (message message-push)) "Handles a remote PUSH request." (with-slots (slot value) message (push value (slot-value node slot)) (values))) -(define-rpc-handler handle-message-values - ((node blossom-node) (message message-values)) +(define-rpc-handler ((node blossom-node) (message message-values)) "Handles a remote request for data." (with-slots (values) message (loop :for value :in values @@ -378,8 +373,7 @@ evalutes to ;; in the ability to inform a blossom that it's been removed from participating ;; and should halt its process. -(define-message-handler handle-message-sprout-on-blossom - ((node blossom-node) (message message-sprout)) +(define-message-handler ((node blossom-node) (message message-sprout)) "Handles a request that a root node (perhaps not a vertex) alert the DRYAD that it has sprouted." (cond ((blossom-node-petals node) @@ -390,8 +384,7 @@ evalutes to (send-message (blossom-node-dryad node) (make-message-sprout :address (process-public-address node)))))) -(define-message-handler handle-message-wilt - ((node blossom-node) (message message-wilt)) +(define-message-handler ((node blossom-node) (message message-wilt)) ;; sanity check: are we actually allowed to wilt? (when (or (blossom-node-parent node) (blossom-node-pistil node) @@ -404,8 +397,7 @@ evalutes to :address (process-public-address node))) (setf (blossom-node-wilting node) t)) -(define-rpc-handler handle-message-claim-root - ((node blossom-node) (message message-claim-root)) +(define-rpc-handler ((node blossom-node) (message message-claim-root)) "If node is already claimed, return NIL. Otherwise, set claimed? to T and return our public address." (with-slots (claimed?) node (cond @@ -415,77 +407,13 @@ evalutes to (setf claimed? t) (process-public-address node))))) -(define-rpc-handler handle-message-release-root - ((node blossom-node) (message message-release-root)) +(define-rpc-handler ((node blossom-node) (message message-release-root)) "Set claimed? to NIL." (with-slots (claimed?) node (assert claimed? () "Trying to release an unclaimed root!") (setf claimed? nil) t)) -;;; -;;; blossom message dispatch table -;;; - -;; NOTE: the ordering of this table _mostly_ doesn't matter. its only really -;; important feature is that LOCK-REQUEST gets handled with high priority. -(define-message-dispatch blossom-node - (message-soft-adjoin-root 'handle-message-adjoin-root - (typep (blossom-node-pistil blossom-node) - '(or null address))) - (message-adjoin-root 'handle-message-adjoin-root - (and (eql ':ALL (blossom-node-pingable blossom-node)) - (typep (blossom-node-pistil blossom-node) - '(or null address)))) - - (message-lock 'handle-message-lock) - - (message-broadcast-reweight 'handle-message-broadcast-reweight - (process-lockable-locked? blossom-node)) - - (message-percolate 'handle-message-percolate) - - (message-soft-scan 'handle-message-scan - (not (eql ':NONE (blossom-node-pingable blossom-node)))) - (message-scan 'handle-message-scan - (eql ':ALL (blossom-node-pingable blossom-node))) - - (message-broadcast-pingability 'handle-message-broadcast-pingability) - - (message-convergecast-collect-roots 'handle-message-convergecast-collect-roots) - - (message-set 'handle-message-set) - (message-push 'handle-message-push) - (message-values 'handle-message-values) - - (message-root-path 'handle-message-root-path) - (message-attach-parent 'handle-message-attach-parent) - (message-convert-child-to-petal 'handle-message-convert-child-to-petal) - (message-reattach-cycle-child 'handle-message-reattach-cycle-child) - (message-set-up-blossom 'handle-message-set-up-blossom) - - (message-expand 'handle-message-expand) - (message-blossom-parent 'handle-message-blossom-parent - (typep (blossom-node-pistil blossom-node) - '(or null address))) - (message-replace-child 'handle-message-replace-child) - - (message-soft-ping 'handle-message-ping - (not (eql ':NONE (blossom-node-pingable blossom-node)))) - - (message-ping 'handle-message-ping - (eql ':ALL (blossom-node-pingable blossom-node))) - - (message-wilt 'handle-message-wilt) - - (message-sprout 'handle-message-sprout-on-blossom) - - (message-id-query 'handle-message-id-query) - (message-claim-root 'handle-message-claim-root) - (message-release-root 'handle-message-release-root) - (message-broadcast-stash-weight 'handle-message-broadcast-stash-weight) - (message-broadcast-unstash-weight 'handle-message-broadcast-unstash-weight)) - ;;; ;;; basic command definitions for BLOSSOM-NODE ;;; diff --git a/src/operations/augment.lisp b/src/operations/augment.lisp index 22aa170..65e4582 100644 --- a/src/operations/augment.lisp +++ b/src/operations/augment.lisp @@ -82,8 +82,7 @@ ;;; message handlers ;;; -(define-message-handler handle-message-percolate - ((node blossom-node) (message message-percolate)) +(define-message-handler ((node blossom-node) (message message-percolate)) "Performs a step in the path augmentation process." (with-slots (traversal-edge reply-channel) message ;; does the previous node expect me to link to it? diff --git a/src/operations/contract.lisp b/src/operations/contract.lisp index 32a3736..86b9fac 100644 --- a/src/operations/contract.lisp +++ b/src/operations/contract.lisp @@ -312,8 +312,7 @@ If we have a non-null peduncle edge (F -> C above), then we need to tell its sou ;;; message handlers ;;; -(define-message-handler handle-message-root-path - ((node blossom-node) (message message-root-path)) +(define-message-handler ((node blossom-node) (message message-root-path)) "Calculates the path from a blossom through to the tree root (consisting only of toplevel blossoms)." (with-slots (path reply-channel) message (cond @@ -329,8 +328,7 @@ If we have a non-null peduncle edge (F -> C above), then we need to tell its sou (send-message reply-channel (make-message-rpc-done :result path)))))) -(define-rpc-handler handle-message-attach-parent - ((node blossom-node) (message message-attach-parent)) +(define-rpc-handler ((node blossom-node) (message message-attach-parent)) "Attaches a fresh blossom to an existing parent." (with-slots (peduncle-edge reply-channel fresh-blossom) message (assert (not (null peduncle-edge))) @@ -348,8 +346,7 @@ If we have a non-null peduncle edge (F -> C above), then we need to tell its sou fresh-blossom) nil)) -(define-rpc-handler handle-message-convert-child-to-petal - ((node blossom-node) (message message-convert-child-to-petal)) +(define-rpc-handler ((node blossom-node) (message message-convert-child-to-petal)) "Attaches an old child to a new blossom as a petal." (with-slots (reply-channel fresh-blossom) message (prog1 (blossom-node-children node) @@ -359,8 +356,7 @@ If we have a non-null peduncle edge (F -> C above), then we need to tell its sou (blossom-node-match-edge node) nil (blossom-node-children node) nil)))) -(define-rpc-handler handle-message-reattach-cycle-child - ((node blossom-node) (message message-reattach-cycle-child)) +(define-rpc-handler ((node blossom-node) (message message-reattach-cycle-child)) "Attaches an old child to a new blossom as a (non-blossom-)child." (with-slots (reply-channel fresh-blossom) message (setf (blossom-edge-target-node (blossom-node-parent node)) @@ -370,8 +366,7 @@ If we have a non-null peduncle edge (F -> C above), then we need to tell its sou ;; NOTE: this message is really hefty. you could cut it down somewhat by making ;; the fresh blossom responsible for setting _itself_ up. this would also ;; alleviate the obnoxious problem with locking/spawning timing. -(define-rpc-handler handle-message-set-up-blossom - ((node blossom-node) (message message-set-up-blossom)) +(define-rpc-handler ((node blossom-node) (message message-set-up-blossom)) "Sets up a new contracting blossom's slots." (with-slots (peduncle-edge petals petal-children dryad reply-channel) message (loop :for petal-child :in petal-children diff --git a/src/operations/expand.lisp b/src/operations/expand.lisp index 63a807f..ca5e7aa 100644 --- a/src/operations/expand.lisp +++ b/src/operations/expand.lisp @@ -105,8 +105,7 @@ ;;; message handlers ;;; -(define-message-handler handle-message-expand - ((node blossom-node) (message message-expand)) +(define-message-handler ((node blossom-node) (message message-expand)) "Starts the procedure for popping a contracting blossom." (cond ((blossom-node-pistil node) @@ -121,8 +120,9 @@ :match-edge (blossom-node-match-edge node)) (process-continuation node `(EXPAND-BLOSSOM ,(message-reply-channel message)))))) -(define-message-handler handle-message-blossom-parent - ((node blossom-node) (message message-blossom-parent)) +(define-message-handler ((node blossom-node) (message message-blossom-parent) + :guard (typep (blossom-node-pistil node) + '(or null address))) "Calculates the topmost blossom which contains NODE, subject to the possible limitation that we not exceed STOP-BEFORE." (with-slots (reply-channel stop-before) message (cond @@ -141,8 +141,7 @@ (t (send-message (blossom-node-pistil node) message))))) -(define-rpc-handler handle-message-replace-child - ((node blossom-node) (message message-replace-child)) +(define-rpc-handler ((node blossom-node) (message message-replace-child)) "Replaces a child edge targeting a given node by an edge targeting another node." (with-slots (reply-channel old-child new-child) message (dolist (child-edge (blossom-node-children node)) diff --git a/src/operations/multireweight.lisp b/src/operations/multireweight.lisp index 385c284..1df84d2 100644 --- a/src/operations/multireweight.lisp +++ b/src/operations/multireweight.lisp @@ -278,8 +278,7 @@ After collecting the `hold-cluster', we then `CHECK-PRIORITY' to determine if we ;;; message handlers ;;; -(define-convergecast-subordinate handle-message-convergecast-collect-roots - ((node blossom-node) (message message-convergecast-collect-roots)) +(define-convergecast-subordinate ((node blossom-node) (message message-convergecast-collect-roots)) "Check to see if we're held. If not, `RETURN-FROM-CAST' and send back up a NIL. If we are held, add ourselves to the `HOLD-CLUSTER'. Additionally, if we are held by `NEW-ROOTS' that aren't currently in the cluster, forward this message along to them to continue gathering roots. Finally, send the aggregated cluster back to the sender." (with-slots (hold-cluster reply-channel) message ;; If we're not held, abort the convergecast. diff --git a/src/operations/reweight.lisp b/src/operations/reweight.lisp index 485cbd4..975dc18 100644 --- a/src/operations/reweight.lisp +++ b/src/operations/reweight.lisp @@ -321,8 +321,7 @@ ;;; message handlers ;;; -(define-broadcast-handler handle-message-broadcast-stash-weight - ((node blossom-node) (message message-broadcast-stash-weight)) +(define-broadcast-handler ((node blossom-node) (message message-broadcast-stash-weight)) "If the node is negative, sets the `STASHED-WEIGHT' of `NODE' to equal its `INTERNAL-WEIGHT', and regardless instructs `NODE's children to do the same." (with-slots (internal-weight positive? stashed-weight) node (unless positive? @@ -332,8 +331,8 @@ (push-broadcast-frame :targets (mapcar #'blossom-edge-target-node (blossom-node-children node))))) -(define-broadcast-handler handle-message-broadcast-reweight - ((node blossom-node) (message message-broadcast-reweight)) +(define-broadcast-handler ((node blossom-node) (message message-broadcast-reweight) + :guard (process-lockable-locked? node)) "Increments the `INTERNAL-WEIGHT' of `NODE' by the `WEIGHT' of the `MESSAGE', and then instructs `NODE's children to reweight themselves by the additive inverse of `WEIGHT'." (with-slots (weight) message (with-slots (internal-weight) node @@ -348,8 +347,7 @@ (push-broadcast-frame :targets (mapcar #'blossom-edge-target-node (blossom-node-children node)))))) -(define-broadcast-handler handle-message-broadcast-unstash-weight - ((node blossom-node) (message message-broadcast-unstash-weight)) +(define-broadcast-handler ((node blossom-node) (message message-broadcast-unstash-weight)) "If the node is negative, sets the `STASHED-WEIGHT' of `NODE' to NIL, and regardless instructs `NODE's children to do the same." (with-slots (internal-weight positive? stashed-weight) node (unless positive? diff --git a/src/operations/scan.lisp b/src/operations/scan.lisp index 7c62288..7e399c8 100644 --- a/src/operations/scan.lisp +++ b/src/operations/scan.lisp @@ -468,8 +468,7 @@ NOTE: this command is only installed when NODE is a vertex." ;;; weight adjustments on the recipient side. i think this is the only sane ;;; arrangement for a source that is ignorant of the recipient's ID. -(define-message-handler handle-message-ping - ((node blossom-node) (message message-ping)) +(defun handle-message-ping (node message) "Begins the process of responding to a PING message: starts an ADJOIN-ROOT sequence." (with-slots (weight id recipient-child reply-channel root) message (let* ((total-weight (+ weight @@ -487,7 +486,12 @@ NOTE: this command is only installed when NODE is a vertex." :pingability (blossom-node-pingable node) :vv-distance (vertex-vertex-distance (blossom-node-id node) id) :old-weight weight - :new-weight total-weight) + :new-weight total-weight + ;; these normally get automatically appended, but we're outside + ;; the lexical context of a handler + :log-level 0 + :time (now) + :source node) (send-message (process-public-address node) (funcall (if (typep message 'message-soft-ping) #'make-message-soft-adjoin-root @@ -496,8 +500,15 @@ NOTE: this command is only installed when NODE is a vertex." :ping message :pong pong))))) -(define-message-handler handle-message-adjoin-root - ((node blossom-node) (message message-adjoin-root)) +(define-message-handler ((node blossom-node) (message message-ping) + :guard (eql ':ALL (blossom-node-pingable node))) + (handle-message-ping node message)) + +(define-message-handler ((node blossom-node) (message message-soft-ping) + :guard (not (eql ':NONE (blossom-node-pingable node)))) + (handle-message-ping node message)) + +(defun handle-message-adjoin-root (node message) "The workhorse of responding to a PING message: walks up the blossom contractions, then up the maximally-contracted tree, ultimately resulting in a PONG. This handler is responsible for actually assigning a recommended-next-move for the blossom algorithm, which makes up the bulk of the function body." @@ -517,13 +528,18 @@ This handler is responsible for actually assigning a recommended-next-move for t :old-value (message-pong-weight pong) :delta delta :internal-weight internal-weight - :stashed-weight stashed-weight) + :stashed-weight stashed-weight + ;; these normally get automatically appended, but we're + ;; outside the lexical context of a handler + :log-level 0 + :time (now) + :source node) (decf (message-pong-weight pong) delta)))) ;; if we haven't yet made it to toplevel... (when (blossom-node-pistil node) ;; ... keep throwing up pistil. (send-message (blossom-node-pistil node) message) - (finish-handler)) + (return-from handle-message-adjoin-root)) ;; otherwise, record the first toplevel node we see as our parent blossom. ;; CRITICALLY, this does NOT prematurely return. (unless (blossom-edge-target-node last-edge) @@ -534,7 +550,7 @@ This handler is responsible for actually assigning a recommended-next-move for t (when (blossom-node-parent node) (send-message (blossom-edge-target-node (blossom-node-parent node)) message) - (finish-handler)) + (return-from handle-message-adjoin-root)) ;; otherwise, we're at the root. (let ((target-root (process-public-address node)) (recommendation (recommend node ping pong message))) @@ -542,6 +558,17 @@ This handler is responsible for actually assigning a recommended-next-move for t (message-pong-recommendation pong) recommendation) (send-message (message-reply-channel message) pong)))) +(define-message-handler ((node blossom-node) (message message-soft-adjoin-root) + :guard (typep (blossom-node-pistil node) + '(or null address))) + (handle-message-adjoin-root node message)) + +(define-message-handler ((node blossom-node) (message message-adjoin-root) + :guard (and (eql ':ALL (blossom-node-pingable node)) + (typep (blossom-node-pistil node) + '(or null address)))) + (handle-message-adjoin-root node message)) + (defgeneric recommend (node ping pong adjoin-root) (:documentation "Computes an action to propose as part of a PONG.") (:method ((node blossom-node) ping pong adjoin-root) @@ -586,12 +613,20 @@ This handler is responsible for actually assigning a recommended-next-move for t (t (error "Unknown blossom case.")))))) -(define-message-handler handle-message-scan - ((node blossom-node) (message message-scan)) +(defun handle-message-scan + (node message) "Begins a scanning process." (when (blossom-node-wilting node) (when (message-reply-channel message) (send-message (message-reply-channel message) (make-pong node))) - (finish-handler)) + (return-from handle-message-scan)) (process-continuation node `(START-SCAN ,message))) + +(define-message-handler ((node blossom-node) (message message-soft-scan) + :guard (not (eql ':NONE (blossom-node-pingable node)))) + (handle-message-scan node message)) + +(define-message-handler ((node blossom-node) (message message-scan) + :guard (eql ':ALL (blossom-node-pingable node))) + (handle-message-scan node message)) diff --git a/src/supervisor.lisp b/src/supervisor.lisp index ee88024..ce50fe6 100644 --- a/src/supervisor.lisp +++ b/src/supervisor.lisp @@ -38,10 +38,6 @@ :documentation "The address of the host `DRYAD' for the node that spawned us.")) (:documentation "A companion process responsible for coordinating a tree operation.")) -(define-message-dispatch supervisor - ;; nothing. supervisors are bull-headed. - ) - ;;; ;;; supervisor data frame ;;;