2023-06-23 20:56:09 -06:00
|
|
|
package graphvent
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
2023-07-27 18:08:43 -06:00
|
|
|
"fmt"
|
2023-06-23 20:56:09 -06:00
|
|
|
)
|
|
|
|
|
2023-07-28 00:04:18 -06:00
|
|
|
// A Listener extension provides a channel that can receive signals on a different thread
|
2023-07-25 21:43:15 -06:00
|
|
|
type ListenerExt struct {
|
2023-07-26 11:56:10 -06:00
|
|
|
Buffer int
|
2023-07-26 15:08:14 -06:00
|
|
|
Chan chan Signal
|
2023-07-24 16:04:56 -06:00
|
|
|
}
|
|
|
|
|
2023-07-28 00:04:18 -06:00
|
|
|
// Create a new listener extension with a given buffer size
|
2023-07-26 11:56:10 -06:00
|
|
|
func NewListenerExt(buffer int) *ListenerExt {
|
|
|
|
return &ListenerExt{
|
|
|
|
Buffer: buffer,
|
2023-07-26 15:08:14 -06:00
|
|
|
Chan: make(chan Signal, buffer),
|
2023-07-24 16:04:56 -06:00
|
|
|
}
|
2023-06-23 22:19:43 -06:00
|
|
|
}
|
|
|
|
|
2023-07-28 00:04:18 -06:00
|
|
|
// Simple load function, unmarshal the buffer int from json
|
2023-07-26 11:56:10 -06:00
|
|
|
func LoadListenerExt(ctx *Context, data []byte) (Extension, error) {
|
|
|
|
var j int
|
|
|
|
err := json.Unmarshal(data, &j)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return NewListenerExt(j), nil
|
|
|
|
}
|
|
|
|
|
2023-07-26 15:40:33 -06:00
|
|
|
func (listener *ListenerExt) Type() ExtType {
|
2023-07-25 21:43:15 -06:00
|
|
|
return ListenerExtType
|
2023-06-23 22:19:43 -06:00
|
|
|
}
|
|
|
|
|
2023-07-28 00:04:18 -06:00
|
|
|
// Send the signal to the channel, logging an overflow if it occurs
|
2023-07-27 15:27:14 -06:00
|
|
|
func (ext *ListenerExt) Process(ctx *Context, princ_id NodeID, node *Node, signal Signal) {
|
|
|
|
ctx.Log.Logf("signal", "LISTENER_PROCESS: %s - %+v", node.ID, signal)
|
2023-07-25 21:43:15 -06:00
|
|
|
select {
|
|
|
|
case ext.Chan <- signal:
|
|
|
|
default:
|
2023-07-27 15:27:14 -06:00
|
|
|
ctx.Log.Logf("listener", "LISTENER_OVERFLOW: %s", node.ID)
|
2023-07-25 21:43:15 -06:00
|
|
|
}
|
2023-07-27 15:27:14 -06:00
|
|
|
return
|
2023-07-09 14:30:30 -06:00
|
|
|
}
|
|
|
|
|
2023-07-28 00:04:18 -06:00
|
|
|
// ReqState holds the multiple states of a requirement
|
|
|
|
type ReqState struct {
|
|
|
|
Link string `json:"link"`
|
|
|
|
Lock string `json:"lock"`
|
|
|
|
}
|
|
|
|
|
|
|
|
// A LockableExt allows a node to be linked to other nodes(via LinkSignal) and locked/unlocked(via LockSignal)
|
|
|
|
type LockableExt struct {
|
|
|
|
Owner *NodeID
|
|
|
|
PendingOwner *NodeID
|
|
|
|
Requirements map[NodeID]ReqState
|
|
|
|
Dependencies map[NodeID]string
|
|
|
|
}
|
|
|
|
|
|
|
|
type LockableExtJSON struct {
|
|
|
|
Owner *NodeID `json:"owner"`
|
|
|
|
PendingOwner *NodeID `json:"pending_owner"`
|
|
|
|
Requirements map[string]ReqState `json:"requirements"`
|
|
|
|
Dependencies map[string]string `json:"dependencies"`
|
|
|
|
}
|
|
|
|
|
2023-07-27 18:08:43 -06:00
|
|
|
func LoadLockableExt(ctx *Context, data []byte) (Extension, error) {
|
2023-07-28 00:04:18 -06:00
|
|
|
var j LockableExtJSON
|
|
|
|
err := json.Unmarshal(data, &j)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
requirements, err := LoadIDMap(j.Requirements)
|
2023-07-27 18:08:43 -06:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2023-07-28 00:04:18 -06:00
|
|
|
dependencies, err := LoadIDMap(j.Dependencies)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2023-07-27 18:08:43 -06:00
|
|
|
|
2023-07-28 00:04:18 -06:00
|
|
|
return &LockableExt{
|
|
|
|
Owner: j.Owner,
|
|
|
|
PendingOwner: j.PendingOwner,
|
|
|
|
Requirements: requirements,
|
|
|
|
Dependencies: dependencies,
|
|
|
|
}, nil
|
2023-07-24 16:04:56 -06:00
|
|
|
}
|
|
|
|
|
2023-07-27 18:08:43 -06:00
|
|
|
func (ext *ListenerExt) Serialize() ([]byte, error) {
|
|
|
|
return json.MarshalIndent(ext.Buffer, "", " ")
|
2023-06-23 20:56:09 -06:00
|
|
|
}
|
|
|
|
|
2023-07-25 21:43:15 -06:00
|
|
|
func (ext *LockableExt) Type() ExtType {
|
|
|
|
return LockableExtType
|
2023-06-28 21:49:23 -06:00
|
|
|
}
|
|
|
|
|
2023-07-25 21:43:15 -06:00
|
|
|
func (ext *LockableExt) Serialize() ([]byte, error) {
|
2023-07-28 00:04:18 -06:00
|
|
|
return json.MarshalIndent(&LockableExtJSON{
|
|
|
|
Owner: ext.Owner,
|
|
|
|
PendingOwner: ext.PendingOwner,
|
|
|
|
Requirements: IDMap(ext.Requirements),
|
|
|
|
Dependencies: IDMap(ext.Dependencies),
|
|
|
|
}, "", " ")
|
2023-07-26 00:18:11 -06:00
|
|
|
}
|
|
|
|
|
2023-07-27 18:37:06 -06:00
|
|
|
func NewLockableExt() *LockableExt {
|
2023-07-26 11:56:10 -06:00
|
|
|
return &LockableExt{
|
2023-07-27 18:37:06 -06:00
|
|
|
Owner: nil,
|
2023-07-27 19:53:43 -06:00
|
|
|
PendingOwner: nil,
|
2023-07-27 22:25:00 -06:00
|
|
|
Requirements: map[NodeID]ReqState{},
|
2023-07-27 18:37:06 -06:00
|
|
|
Dependencies: map[NodeID]string{},
|
2023-07-26 11:56:10 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-28 00:04:18 -06:00
|
|
|
// Send the signal to unlock a node from itself
|
2023-07-27 22:25:00 -06:00
|
|
|
func UnlockLockable(ctx *Context, node *Node) error {
|
|
|
|
return ctx.Send(node.ID, node.ID, NewLockSignal("unlock"))
|
2023-07-27 18:08:43 -06:00
|
|
|
}
|
|
|
|
|
2023-07-28 00:04:18 -06:00
|
|
|
// Send the signal to lock a node from itself
|
2023-07-27 18:37:06 -06:00
|
|
|
func LockLockable(ctx *Context, node *Node) error {
|
|
|
|
return ctx.Send(node.ID, node.ID, NewLockSignal("lock"))
|
|
|
|
}
|
|
|
|
|
2023-07-28 00:04:18 -06:00
|
|
|
// Setup a node to send the initial requirement link signal, then send the signal
|
2023-07-27 18:08:43 -06:00
|
|
|
func LinkRequirement(ctx *Context, dependency *Node, requirement NodeID) error {
|
|
|
|
dep_ext, err := GetExt[*LockableExt](dependency)
|
2023-07-26 00:18:11 -06:00
|
|
|
if err != nil {
|
2023-07-27 18:08:43 -06:00
|
|
|
return err
|
2023-06-23 20:56:09 -06:00
|
|
|
}
|
|
|
|
|
2023-07-27 18:08:43 -06:00
|
|
|
_, exists := dep_ext.Requirements[requirement]
|
|
|
|
if exists == true {
|
|
|
|
return fmt.Errorf("%s is already a requirement of %s", requirement, dependency.ID)
|
|
|
|
}
|
2023-06-30 13:25:35 -06:00
|
|
|
|
2023-07-27 18:08:43 -06:00
|
|
|
_, exists = dep_ext.Dependencies[requirement]
|
|
|
|
if exists == true {
|
|
|
|
return fmt.Errorf("%s is a dependency of %s, cannot link as requirement", requirement, dependency.ID)
|
|
|
|
}
|
2023-07-27 16:21:27 -06:00
|
|
|
|
2023-07-27 22:25:00 -06:00
|
|
|
dep_ext.Requirements[requirement] = ReqState{"linking", "unlocked"}
|
2023-07-27 23:05:19 -06:00
|
|
|
return ctx.Send(dependency.ID, requirement, NewLinkSignal("link_as_req"))
|
2023-07-27 18:08:43 -06:00
|
|
|
}
|
2023-07-27 16:21:27 -06:00
|
|
|
|
2023-07-28 00:04:18 -06:00
|
|
|
// Handle a LockSignal and update the extensions owner/requirement states
|
2023-07-27 18:37:06 -06:00
|
|
|
func (ext *LockableExt) HandleLockSignal(ctx *Context, source NodeID, node *Node, signal StateSignal) {
|
|
|
|
ctx.Log.Logf("lockable", "LOCK_SIGNAL: %s->%s %+v", source, node.ID, signal)
|
|
|
|
state := signal.State
|
|
|
|
switch state {
|
2023-07-27 22:25:00 -06:00
|
|
|
case "unlock":
|
|
|
|
if ext.Owner == nil {
|
|
|
|
ctx.Send(node.ID, source, NewLockSignal("already_unlocked"))
|
|
|
|
} else if source != *ext.Owner {
|
|
|
|
ctx.Send(node.ID, source, NewLockSignal("not_owner"))
|
|
|
|
} else if ext.PendingOwner == nil {
|
|
|
|
ctx.Send(node.ID, source, NewLockSignal("already_unlocking"))
|
|
|
|
} else {
|
|
|
|
if len(ext.Requirements) == 0 {
|
|
|
|
ext.Owner = nil
|
|
|
|
ext.PendingOwner = nil
|
|
|
|
ctx.Send(node.ID, source, NewLockSignal("unlocked"))
|
|
|
|
} else {
|
|
|
|
ext.PendingOwner = nil
|
|
|
|
for id, state := range(ext.Requirements) {
|
|
|
|
if state.Link == "linked" {
|
|
|
|
if state.Lock != "locked" {
|
|
|
|
panic("NOT_LOCKED")
|
|
|
|
}
|
|
|
|
state.Lock = "unlocking"
|
|
|
|
ext.Requirements[id] = state
|
|
|
|
ctx.Send(node.ID, id, NewLockSignal("unlock"))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if source != node.ID {
|
|
|
|
ctx.Send(node.ID, source, NewLockSignal("unlocking"))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case "unlocking":
|
|
|
|
state, exists := ext.Requirements[source]
|
|
|
|
if exists == false {
|
|
|
|
ctx.Send(node.ID, source, NewLockSignal("not_requirement"))
|
|
|
|
} else if state.Link != "linked" {
|
|
|
|
ctx.Send(node.ID, source, NewLockSignal("node_not_linked"))
|
|
|
|
} else if state.Lock != "unlocking" {
|
|
|
|
ctx.Send(node.ID, source, NewLockSignal("not_unlocking"))
|
|
|
|
}
|
|
|
|
|
|
|
|
case "unlocked":
|
2023-07-27 19:53:43 -06:00
|
|
|
if source == node.ID {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2023-07-27 22:25:00 -06:00
|
|
|
state, exists := ext.Requirements[source]
|
|
|
|
if exists == false {
|
|
|
|
ctx.Send(node.ID, source, NewLockSignal("not_requirement"))
|
|
|
|
} else if state.Link != "linked" {
|
|
|
|
ctx.Send(node.ID, source, NewLockSignal("not_linked"))
|
|
|
|
} else if state.Lock != "unlocking" {
|
|
|
|
ctx.Send(node.ID, source, NewLockSignal("not_unlocking"))
|
|
|
|
} else {
|
|
|
|
state.Lock = "unlocked"
|
|
|
|
ext.Requirements[source] = state
|
|
|
|
|
|
|
|
if ext.PendingOwner == nil {
|
|
|
|
linked := 0
|
|
|
|
unlocked := 0
|
|
|
|
for _, s := range(ext.Requirements) {
|
|
|
|
if s.Link == "linked" {
|
|
|
|
linked += 1
|
|
|
|
}
|
|
|
|
if s.Lock == "unlocked" {
|
|
|
|
unlocked += 1
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if linked == unlocked {
|
|
|
|
previous_owner := *ext.Owner
|
|
|
|
ext.Owner = nil
|
|
|
|
ctx.Send(node.ID, previous_owner, NewLockSignal("unlocked"))
|
2023-07-27 19:53:43 -06:00
|
|
|
}
|
|
|
|
}
|
2023-07-27 22:25:00 -06:00
|
|
|
}
|
|
|
|
case "locked":
|
|
|
|
if source == node.ID {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
state, exists := ext.Requirements[source]
|
|
|
|
if exists == false {
|
|
|
|
ctx.Send(node.ID, source, NewLockSignal("not_requirement"))
|
|
|
|
} else if state.Link != "linked" {
|
|
|
|
ctx.Send(node.ID, source, NewLockSignal("not_linked"))
|
|
|
|
} else if state.Lock != "locking" {
|
|
|
|
ctx.Send(node.ID, source, NewLockSignal("not_locking"))
|
2023-07-27 19:53:43 -06:00
|
|
|
} else {
|
2023-07-27 22:25:00 -06:00
|
|
|
state.Lock = "locked"
|
|
|
|
ext.Requirements[source] = state
|
|
|
|
|
|
|
|
if ext.PendingOwner != nil {
|
|
|
|
linked := 0
|
|
|
|
locked := 0
|
|
|
|
for _, s := range(ext.Requirements) {
|
|
|
|
if s.Link == "linked" {
|
|
|
|
linked += 1
|
|
|
|
}
|
|
|
|
if s.Lock == "locked" {
|
|
|
|
locked += 1
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if linked == locked {
|
|
|
|
ext.Owner = ext.PendingOwner
|
|
|
|
ctx.Send(node.ID, *ext.Owner, NewLockSignal("locked"))
|
|
|
|
}
|
|
|
|
}
|
2023-07-27 19:53:43 -06:00
|
|
|
}
|
2023-07-27 22:25:00 -06:00
|
|
|
case "locking":
|
|
|
|
state, exists := ext.Requirements[source]
|
|
|
|
if exists == false {
|
|
|
|
ctx.Send(node.ID, source, NewLockSignal("not_requirement"))
|
|
|
|
} else if state.Link != "linked" {
|
|
|
|
ctx.Send(node.ID, source, NewLockSignal("node_not_linked"))
|
|
|
|
} else if state.Lock != "locking" {
|
|
|
|
ctx.Send(node.ID, source, NewLockSignal("not_locking"))
|
2023-07-27 19:53:43 -06:00
|
|
|
}
|
2023-07-27 22:25:00 -06:00
|
|
|
|
2023-07-27 19:53:43 -06:00
|
|
|
case "lock":
|
|
|
|
if ext.Owner != nil {
|
|
|
|
ctx.Send(node.ID, source, NewLockSignal("already_locked"))
|
2023-07-27 22:25:00 -06:00
|
|
|
} else if ext.PendingOwner != nil {
|
|
|
|
ctx.Send(node.ID, source, NewLockSignal("already_locking"))
|
|
|
|
} else {
|
|
|
|
owner := source
|
2023-07-27 19:53:43 -06:00
|
|
|
if len(ext.Requirements) == 0 {
|
|
|
|
ext.Owner = &owner
|
2023-07-27 22:25:00 -06:00
|
|
|
ext.PendingOwner = ext.Owner
|
2023-07-27 19:53:43 -06:00
|
|
|
ctx.Send(node.ID, source, NewLockSignal("locked"))
|
|
|
|
} else {
|
2023-07-27 22:25:00 -06:00
|
|
|
ext.PendingOwner = &owner
|
2023-07-27 19:53:43 -06:00
|
|
|
for id, state := range(ext.Requirements) {
|
2023-07-27 22:25:00 -06:00
|
|
|
if state.Link == "linked" {
|
|
|
|
if state.Lock != "unlocked" {
|
|
|
|
panic("NOT_UNLOCKED")
|
|
|
|
}
|
|
|
|
state.Lock = "locking"
|
|
|
|
ext.Requirements[id] = state
|
2023-07-27 19:53:43 -06:00
|
|
|
ctx.Send(node.ID, id, NewLockSignal("lock"))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if source != node.ID {
|
2023-07-27 22:25:00 -06:00
|
|
|
ctx.Send(node.ID, source, NewLockSignal("locking"))
|
2023-07-27 19:53:43 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-07-27 18:37:06 -06:00
|
|
|
default:
|
|
|
|
ctx.Log.Logf("lockable", "LOCK_ERR: unkown state %s", state)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-28 00:04:18 -06:00
|
|
|
// Handle LinkSignal, updating the extensions requirements and dependencies as necessary
|
|
|
|
// TODO: Add unlink
|
2023-07-27 18:37:06 -06:00
|
|
|
func (ext *LockableExt) HandleLinkSignal(ctx *Context, source NodeID, node *Node, signal StateSignal) {
|
2023-07-27 18:08:43 -06:00
|
|
|
ctx.Log.Logf("lockable", "LINK_SIGNAL: %s->%s %+v", source, node.ID, signal)
|
|
|
|
state := signal.State
|
|
|
|
switch state {
|
2023-07-27 23:05:19 -06:00
|
|
|
case "link_as_dep":
|
|
|
|
state, exists := ext.Requirements[source]
|
|
|
|
if exists == true && state.Link == "linked" {
|
|
|
|
ctx.Send(node.ID, source, NewLinkSignal("already_req"))
|
|
|
|
} else if state.Link == "linking" {
|
|
|
|
state.Link = "linked"
|
|
|
|
ext.Requirements[source] = state
|
|
|
|
ctx.Send(node.ID, source, NewLinkSignal("linked_as_dep"))
|
|
|
|
} else if ext.PendingOwner != ext.Owner {
|
|
|
|
if ext.Owner == nil {
|
|
|
|
ctx.Send(node.ID, source, NewLinkSignal("locking"))
|
|
|
|
} else {
|
|
|
|
ctx.Send(node.ID, source, NewLinkSignal("unlocking"))
|
2023-07-27 18:08:43 -06:00
|
|
|
}
|
|
|
|
} else {
|
2023-07-27 23:05:19 -06:00
|
|
|
ext.Requirements[source] = ReqState{"linking", "unlocked"}
|
|
|
|
ctx.Send(node.ID, source, NewLinkSignal("link_as_req"))
|
2023-07-27 18:08:43 -06:00
|
|
|
}
|
2023-07-27 23:05:19 -06:00
|
|
|
|
|
|
|
case "link_as_req":
|
|
|
|
state, exists := ext.Dependencies[source]
|
|
|
|
if exists == true && state == "linked" {
|
|
|
|
ctx.Send(node.ID, source, NewLinkSignal("already_dep"))
|
|
|
|
} else if state == "linking" {
|
|
|
|
ext.Dependencies[source] = "linked"
|
|
|
|
ctx.Send(node.ID, source, NewLinkSignal("linked_as_req"))
|
|
|
|
} else if ext.PendingOwner != ext.Owner {
|
|
|
|
if ext.Owner == nil {
|
|
|
|
ctx.Send(node.ID, source, NewLinkSignal("locking"))
|
|
|
|
} else {
|
|
|
|
ctx.Send(node.ID, source, NewLinkSignal("unlocking"))
|
2023-07-27 18:08:43 -06:00
|
|
|
}
|
|
|
|
} else {
|
2023-07-27 23:05:19 -06:00
|
|
|
ext.Dependencies[source] = "linking"
|
|
|
|
ctx.Send(node.ID, source, NewLinkSignal("link_as_dep"))
|
2023-07-27 18:08:43 -06:00
|
|
|
}
|
2023-07-27 23:05:19 -06:00
|
|
|
case "linked_as_dep":
|
|
|
|
state, exists := ext.Dependencies[source]
|
|
|
|
if exists == false {
|
|
|
|
ctx.Send(node.ID, source, NewLinkSignal("not_linking"))
|
|
|
|
} else if state == "linked" {
|
|
|
|
} else if state == "linking" {
|
|
|
|
ext.Dependencies[source] = "linked"
|
|
|
|
ctx.Send(node.ID, source, NewLinkSignal("linked_as_req"))
|
2023-07-27 18:16:37 -06:00
|
|
|
}
|
2023-07-27 23:05:19 -06:00
|
|
|
ctx.Log.Logf("lockable", "%s is a dependency of %s", node.ID, source)
|
2023-07-27 18:16:37 -06:00
|
|
|
|
2023-07-27 23:05:19 -06:00
|
|
|
case "linked_as_req":
|
|
|
|
state, exists := ext.Requirements[source]
|
|
|
|
if exists == false {
|
|
|
|
ctx.Send(node.ID, source, NewLinkSignal("not_linking"))
|
|
|
|
} else if state.Link == "linked" {
|
|
|
|
} else if state.Link == "linking" {
|
|
|
|
state.Link = "linked"
|
|
|
|
ext.Requirements[source] = state
|
|
|
|
ctx.Send(node.ID, source, NewLinkSignal("linked_as_dep"))
|
2023-07-27 18:16:37 -06:00
|
|
|
}
|
2023-07-27 23:05:19 -06:00
|
|
|
ctx.Log.Logf("lockable", "%s is a requirement of %s", node.ID, source)
|
2023-07-27 18:16:37 -06:00
|
|
|
|
2023-07-27 18:08:43 -06:00
|
|
|
default:
|
|
|
|
ctx.Log.Logf("lockable", "LINK_ERROR: unknown state %s", state)
|
|
|
|
}
|
2023-07-27 16:21:27 -06:00
|
|
|
}
|
|
|
|
|
2023-07-28 00:04:18 -06:00
|
|
|
// LockableExts process Up/Down signals by forwarding them to owner, dependency, and requirement nodes
|
|
|
|
// LockSignal and LinkSignal Direct signals are processed to update the requirement/dependency/lock state
|
2023-07-27 15:27:14 -06:00
|
|
|
func (ext *LockableExt) Process(ctx *Context, source NodeID, node *Node, signal Signal) {
|
|
|
|
ctx.Log.Logf("signal", "LOCKABLE_PROCESS: %s", node.ID)
|
2023-07-22 20:21:17 -06:00
|
|
|
|
|
|
|
switch signal.Direction() {
|
|
|
|
case Up:
|
2023-07-27 12:20:49 -06:00
|
|
|
owner_sent := false
|
2023-07-27 19:53:43 -06:00
|
|
|
for dependency, state := range(ext.Dependencies) {
|
|
|
|
if state == "linked" {
|
|
|
|
err := ctx.Send(node.ID, dependency, signal)
|
|
|
|
if err != nil {
|
|
|
|
ctx.Log.Logf("signal", "LOCKABLE_SIGNAL_ERR: %s->%s - %e", node.ID, dependency, err)
|
|
|
|
}
|
2023-07-27 15:27:14 -06:00
|
|
|
|
2023-07-27 19:53:43 -06:00
|
|
|
if ext.Owner != nil {
|
|
|
|
if dependency == *ext.Owner {
|
|
|
|
owner_sent = true
|
|
|
|
}
|
2023-07-22 20:21:17 -06:00
|
|
|
}
|
|
|
|
}
|
2023-07-27 12:20:49 -06:00
|
|
|
}
|
2023-07-27 15:27:14 -06:00
|
|
|
|
2023-07-27 12:20:49 -06:00
|
|
|
if ext.Owner != nil && owner_sent == false {
|
2023-07-27 15:27:14 -06:00
|
|
|
if *ext.Owner != node.ID {
|
2023-07-27 16:13:43 -06:00
|
|
|
err := ctx.Send(node.ID, *ext.Owner, signal)
|
2023-07-09 14:30:30 -06:00
|
|
|
if err != nil {
|
2023-07-27 15:27:14 -06:00
|
|
|
ctx.Log.Logf("signal", "LOCKABLE_SIGNAL_ERR: %s->%s - %e", node.ID, *ext.Owner, err)
|
2023-07-09 14:30:30 -06:00
|
|
|
}
|
|
|
|
}
|
2023-07-27 12:20:49 -06:00
|
|
|
}
|
|
|
|
case Down:
|
2023-07-27 19:53:43 -06:00
|
|
|
for requirement, state := range(ext.Requirements) {
|
2023-07-27 22:25:00 -06:00
|
|
|
if state.Link == "linked" {
|
2023-07-27 19:53:43 -06:00
|
|
|
err := ctx.Send(node.ID, requirement, signal)
|
|
|
|
if err != nil {
|
|
|
|
ctx.Log.Logf("signal", "LOCKABLE_SIGNAL_ERR: %s->%s - %e", node.ID, requirement, err)
|
|
|
|
}
|
2023-07-27 12:20:49 -06:00
|
|
|
}
|
|
|
|
}
|
2023-07-22 20:21:17 -06:00
|
|
|
case Direct:
|
2023-07-27 18:08:43 -06:00
|
|
|
switch signal.Type() {
|
|
|
|
case LinkSignalType:
|
2023-07-27 18:37:06 -06:00
|
|
|
ext.HandleLinkSignal(ctx, source, node, signal.(StateSignal))
|
|
|
|
case LockSignalType:
|
|
|
|
ext.HandleLockSignal(ctx, source, node, signal.(StateSignal))
|
2023-07-27 16:21:27 -06:00
|
|
|
default:
|
|
|
|
}
|
2023-07-22 20:21:17 -06:00
|
|
|
default:
|
2023-07-24 17:07:27 -06:00
|
|
|
}
|
2023-07-25 21:43:15 -06:00
|
|
|
}
|
|
|
|
|