...
1
16
17 package garbagecollector
18
19 import (
20 "fmt"
21 "sync"
22
23 "github.com/go-logr/logr"
24
25 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
26 "k8s.io/apimachinery/pkg/types"
27 )
28
29 type objectReference struct {
30 metav1.OwnerReference
31
32 Namespace string
33 }
34
35
36 func (s objectReference) String() string {
37 return fmt.Sprintf("[%s/%s, namespace: %s, name: %s, uid: %s]", s.APIVersion, s.Kind, s.Namespace, s.Name, s.UID)
38 }
39
40
41 func (s objectReference) MarshalLog() interface{} {
42 return struct {
43 Name string `json:"name"`
44 Namespace string `json:"namespace"`
45 APIVersion string `json:"apiVersion"`
46 UID types.UID `json:"uid"`
47 }{
48 Namespace: s.Namespace,
49 Name: s.Name,
50 APIVersion: s.APIVersion,
51 UID: s.UID,
52 }
53 }
54
55 var _ fmt.Stringer = objectReference{}
56 var _ logr.Marshaler = objectReference{}
57
58
59
60
61
62
63 type node struct {
64 identity objectReference
65
66 dependentsLock sync.RWMutex
67
68
69 dependents map[*node]struct{}
70
71
72 deletingDependents bool
73 deletingDependentsLock sync.RWMutex
74
75 beingDeleted bool
76 beingDeletedLock sync.RWMutex
77
78 virtual bool
79 virtualLock sync.RWMutex
80
81
82 owners []metav1.OwnerReference
83 }
84
85
86 func (n *node) clone() *node {
87 c := &node{
88 identity: n.identity,
89 dependents: make(map[*node]struct{}, len(n.dependents)),
90 deletingDependents: n.deletingDependents,
91 beingDeleted: n.beingDeleted,
92 virtual: n.virtual,
93 owners: make([]metav1.OwnerReference, 0, len(n.owners)),
94 }
95 for dep := range n.dependents {
96 c.dependents[dep] = struct{}{}
97 }
98 for _, owner := range n.owners {
99 c.owners = append(c.owners, owner)
100 }
101 return c
102 }
103
104
105
106 func (n *node) markBeingDeleted() {
107 n.beingDeletedLock.Lock()
108 defer n.beingDeletedLock.Unlock()
109 n.beingDeleted = true
110 }
111
112 func (n *node) isBeingDeleted() bool {
113 n.beingDeletedLock.RLock()
114 defer n.beingDeletedLock.RUnlock()
115 return n.beingDeleted
116 }
117
118 func (n *node) markObserved() {
119 n.virtualLock.Lock()
120 defer n.virtualLock.Unlock()
121 n.virtual = false
122 }
123 func (n *node) isObserved() bool {
124 n.virtualLock.RLock()
125 defer n.virtualLock.RUnlock()
126 return !n.virtual
127 }
128
129 func (n *node) markDeletingDependents() {
130 n.deletingDependentsLock.Lock()
131 defer n.deletingDependentsLock.Unlock()
132 n.deletingDependents = true
133 }
134
135 func (n *node) isDeletingDependents() bool {
136 n.deletingDependentsLock.RLock()
137 defer n.deletingDependentsLock.RUnlock()
138 return n.deletingDependents
139 }
140
141 func (n *node) addDependent(dependent *node) {
142 n.dependentsLock.Lock()
143 defer n.dependentsLock.Unlock()
144 n.dependents[dependent] = struct{}{}
145 }
146
147 func (n *node) deleteDependent(dependent *node) {
148 n.dependentsLock.Lock()
149 defer n.dependentsLock.Unlock()
150 delete(n.dependents, dependent)
151 }
152
153 func (n *node) dependentsLength() int {
154 n.dependentsLock.RLock()
155 defer n.dependentsLock.RUnlock()
156 return len(n.dependents)
157 }
158
159
160
161
162 func (n *node) getDependents() []*node {
163 n.dependentsLock.RLock()
164 defer n.dependentsLock.RUnlock()
165 var ret []*node
166 for dep := range n.dependents {
167 ret = append(ret, dep)
168 }
169 return ret
170 }
171
172
173
174
175
176
177
178 func (n *node) blockingDependents() []*node {
179 dependents := n.getDependents()
180 var ret []*node
181 for _, dep := range dependents {
182 for _, owner := range dep.owners {
183 if owner.UID == n.identity.UID && owner.BlockOwnerDeletion != nil && *owner.BlockOwnerDeletion {
184 ret = append(ret, dep)
185 }
186 }
187 }
188 return ret
189 }
190
191
192
193 func ownerReferenceCoordinates(ref metav1.OwnerReference) metav1.OwnerReference {
194 return metav1.OwnerReference{
195 UID: ref.UID,
196 Name: ref.Name,
197 Kind: ref.Kind,
198 APIVersion: ref.APIVersion,
199 }
200 }
201
202
203
204 func ownerReferenceMatchesCoordinates(a, b metav1.OwnerReference) bool {
205 return a.UID == b.UID && a.Name == b.Name && a.Kind == b.Kind && a.APIVersion == b.APIVersion
206 }
207
208
209
210 func (n *node) String() string {
211 n.dependentsLock.RLock()
212 defer n.dependentsLock.RUnlock()
213 return fmt.Sprintf("%#v", n)
214 }
215
216 type concurrentUIDToNode struct {
217 uidToNodeLock sync.RWMutex
218 uidToNode map[types.UID]*node
219 }
220
221 func (m *concurrentUIDToNode) Write(node *node) {
222 m.uidToNodeLock.Lock()
223 defer m.uidToNodeLock.Unlock()
224 m.uidToNode[node.identity.UID] = node
225 }
226
227 func (m *concurrentUIDToNode) Read(uid types.UID) (*node, bool) {
228 m.uidToNodeLock.RLock()
229 defer m.uidToNodeLock.RUnlock()
230 n, ok := m.uidToNode[uid]
231 return n, ok
232 }
233
234 func (m *concurrentUIDToNode) Delete(uid types.UID) {
235 m.uidToNodeLock.Lock()
236 defer m.uidToNodeLock.Unlock()
237 delete(m.uidToNode, uid)
238 }
239
View as plain text