/
establish_link.go
116 lines (103 loc) · 2.98 KB
/
establish_link.go
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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
package bifrost_entitygraph
import (
"sync"
"github.com/aperturerobotics/bifrost/link"
"github.com/aperturerobotics/controllerbus/directive"
"github.com/aperturerobotics/entitygraph/entity"
)
// establishLinkHandler handles EstablishLink values
type establishLinkHandler struct {
// c is the controller
c *Reporter
// ref is the reference
ref directive.Reference
// mtx guards vals
mtx sync.Mutex
// vals are values
vals map[uint32]establishLinkHandlerVal
}
// establishLinkHandlerVal is the value tuple
type establishLinkHandlerVal struct {
linkObj, remoteNodObj entity.Entity
remoteTptObj, remoteTptAssocObj entity.Entity
}
// newEstablishLinkHandler constructs a new establishLinkHandler
func newEstablishLinkHandler(c *Reporter) *establishLinkHandler {
return &establishLinkHandler{
c: c,
vals: make(map[uint32]establishLinkHandlerVal),
}
}
// HandleValueAdded is called when a value is added to the directive.
func (e *establishLinkHandler) HandleValueAdded(inst directive.Instance, val directive.AttachedValue) {
vl, ok := val.GetValue().(link.Link)
if !ok {
e.c.le.Warn("EstablishLink value was not a Link")
return
}
valID := val.GetValueID()
entObj := NewLinkEntity(vl)
nodObj := NewPeerEntity(vl.GetRemotePeer())
remoteTptObj, remoteTptAssocObj := NewTransportEntity(vl.GetRemoteTransportUUID(), vl.GetRemotePeer())
e.mtx.Lock()
_, exists := e.vals[valID]
if !exists {
e.vals[valID] = establishLinkHandlerVal{
remoteNodObj: nodObj,
linkObj: entObj,
remoteTptAssocObj: remoteTptAssocObj,
remoteTptObj: remoteTptObj,
}
}
e.mtx.Unlock()
if !exists {
e.c.store.AddEntityObj(entObj)
e.c.store.AddEntityObj(nodObj)
e.c.store.AddEntityObj(remoteTptAssocObj)
e.c.store.AddEntityObj(remoteTptObj)
}
}
// HandleValueRemoved is called when a value is removed from the directive.
func (e *establishLinkHandler) HandleValueRemoved(inst directive.Instance, val directive.AttachedValue) {
e.mtx.Lock()
ent, exists := e.vals[val.GetValueID()]
if exists {
delete(e.vals, val.GetValueID())
}
e.mtx.Unlock()
if exists {
e.c.store.RemoveEntityObj(ent.linkObj)
e.c.store.RemoveEntityObj(ent.remoteNodObj)
e.c.store.RemoveEntityObj(ent.remoteTptAssocObj)
e.c.store.RemoveEntityObj(ent.remoteTptObj)
}
}
// HandleInstanceDisposed is called when a directive instance is disposed.
// This will occur if Close() is called on the directive instance.
func (e *establishLinkHandler) HandleInstanceDisposed(inst directive.Instance) {
eref := e.ref
if eref == nil {
return
}
e.ref = nil
e.mtx.Lock()
for k, val := range e.vals {
e.c.store.RemoveEntityObj(val.linkObj)
e.c.store.RemoveEntityObj(val.remoteNodObj)
delete(e.vals, k)
}
e.mtx.Unlock()
e.c.mtx.Lock()
for i, ref := range e.c.cleanupRefs {
if ref == eref {
a := e.c.cleanupRefs
a[i] = a[len(a)-1]
a[len(a)-1] = nil
a = a[:len(a)-1]
e.c.cleanupRefs = a
break
}
}
e.c.mtx.Unlock()
}
var _ directive.ReferenceHandler = ((*establishLinkHandler)(nil))