graph.go 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. /*
  2. Copyright 2016 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package garbagecollector
  14. import (
  15. "fmt"
  16. "sync"
  17. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  18. "k8s.io/apimachinery/pkg/types"
  19. )
  20. type objectReference struct {
  21. metav1.OwnerReference
  22. // This is needed by the dynamic client
  23. Namespace string
  24. }
  25. func (s objectReference) String() string {
  26. return fmt.Sprintf("[%s/%s, namespace: %s, name: %s, uid: %s]", s.APIVersion, s.Kind, s.Namespace, s.Name, s.UID)
  27. }
  28. // The single-threaded GraphBuilder.processGraphChanges() is the sole writer of the
  29. // nodes. The multi-threaded GarbageCollector.attemptToDeleteItem() reads the nodes.
  30. // WARNING: node has different locks on different fields. setters and getters
  31. // use the respective locks, so the return values of the getters can be
  32. // inconsistent.
  33. type node struct {
  34. identity objectReference
  35. // dependents will be read by the orphan() routine, we need to protect it with a lock.
  36. dependentsLock sync.RWMutex
  37. // dependents are the nodes that have node.identity as a
  38. // metadata.ownerReference.
  39. dependents map[*node]struct{}
  40. // this is set by processGraphChanges() if the object has non-nil DeletionTimestamp
  41. // and has the FinalizerDeleteDependents.
  42. deletingDependents bool
  43. deletingDependentsLock sync.RWMutex
  44. // this records if the object's deletionTimestamp is non-nil.
  45. beingDeleted bool
  46. beingDeletedLock sync.RWMutex
  47. // this records if the object was constructed virtually and never observed via informer event
  48. virtual bool
  49. virtualLock sync.RWMutex
  50. // when processing an Update event, we need to compare the updated
  51. // ownerReferences with the owners recorded in the graph.
  52. owners []metav1.OwnerReference
  53. }
  54. // An object is on a one way trip to its final deletion if it starts being
  55. // deleted, so we only provide a function to set beingDeleted to true.
  56. func (n *node) markBeingDeleted() {
  57. n.beingDeletedLock.Lock()
  58. defer n.beingDeletedLock.Unlock()
  59. n.beingDeleted = true
  60. }
  61. func (n *node) isBeingDeleted() bool {
  62. n.beingDeletedLock.RLock()
  63. defer n.beingDeletedLock.RUnlock()
  64. return n.beingDeleted
  65. }
  66. func (n *node) markObserved() {
  67. n.virtualLock.Lock()
  68. defer n.virtualLock.Unlock()
  69. n.virtual = false
  70. }
  71. func (n *node) isObserved() bool {
  72. n.virtualLock.RLock()
  73. defer n.virtualLock.RUnlock()
  74. return !n.virtual
  75. }
  76. func (n *node) markDeletingDependents() {
  77. n.deletingDependentsLock.Lock()
  78. defer n.deletingDependentsLock.Unlock()
  79. n.deletingDependents = true
  80. }
  81. func (n *node) isDeletingDependents() bool {
  82. n.deletingDependentsLock.RLock()
  83. defer n.deletingDependentsLock.RUnlock()
  84. return n.deletingDependents
  85. }
  86. func (n *node) addDependent(dependent *node) {
  87. n.dependentsLock.Lock()
  88. defer n.dependentsLock.Unlock()
  89. n.dependents[dependent] = struct{}{}
  90. }
  91. func (n *node) deleteDependent(dependent *node) {
  92. n.dependentsLock.Lock()
  93. defer n.dependentsLock.Unlock()
  94. delete(n.dependents, dependent)
  95. }
  96. func (n *node) dependentsLength() int {
  97. n.dependentsLock.RLock()
  98. defer n.dependentsLock.RUnlock()
  99. return len(n.dependents)
  100. }
  101. // Note that this function does not provide any synchronization guarantees;
  102. // items could be added to or removed from ownerNode.dependents the moment this
  103. // function returns.
  104. func (n *node) getDependents() []*node {
  105. n.dependentsLock.RLock()
  106. defer n.dependentsLock.RUnlock()
  107. var ret []*node
  108. for dep := range n.dependents {
  109. ret = append(ret, dep)
  110. }
  111. return ret
  112. }
  113. // blockingDependents returns the dependents that are blocking the deletion of
  114. // n, i.e., the dependent that has an ownerReference pointing to n, and
  115. // the BlockOwnerDeletion field of that ownerReference is true.
  116. // Note that this function does not provide any synchronization guarantees;
  117. // items could be added to or removed from ownerNode.dependents the moment this
  118. // function returns.
  119. func (n *node) blockingDependents() []*node {
  120. dependents := n.getDependents()
  121. var ret []*node
  122. for _, dep := range dependents {
  123. for _, owner := range dep.owners {
  124. if owner.UID == n.identity.UID && owner.BlockOwnerDeletion != nil && *owner.BlockOwnerDeletion {
  125. ret = append(ret, dep)
  126. }
  127. }
  128. }
  129. return ret
  130. }
  131. // String renders node as a string using fmt. Acquires a read lock to ensure the
  132. // reflective dump of dependents doesn't race with any concurrent writes.
  133. func (n *node) String() string {
  134. n.dependentsLock.RLock()
  135. defer n.dependentsLock.RUnlock()
  136. return fmt.Sprintf("%#v", n)
  137. }
  138. type concurrentUIDToNode struct {
  139. uidToNodeLock sync.RWMutex
  140. uidToNode map[types.UID]*node
  141. }
  142. func (m *concurrentUIDToNode) Write(node *node) {
  143. m.uidToNodeLock.Lock()
  144. defer m.uidToNodeLock.Unlock()
  145. m.uidToNode[node.identity.UID] = node
  146. }
  147. func (m *concurrentUIDToNode) Read(uid types.UID) (*node, bool) {
  148. m.uidToNodeLock.RLock()
  149. defer m.uidToNodeLock.RUnlock()
  150. n, ok := m.uidToNode[uid]
  151. return n, ok
  152. }
  153. func (m *concurrentUIDToNode) Delete(uid types.UID) {
  154. m.uidToNodeLock.Lock()
  155. defer m.uidToNodeLock.Unlock()
  156. delete(m.uidToNode, uid)
  157. }