mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 11:50:44 +00:00
Replace virtual node with observed node if identity differs
If the graph contains a virtual node (because some child object referenced it in an OwnerRef), and a real informer event is observed for that uid at different coordinates, we want to fix the coordinates of the node in the graph to match the actual coordinates. The safe way to do this is to clone the node, replace the identity in the clone, then replace the node with the clone. Modifying the identity directly is not safe because it is accessed lock-free from many code paths. Replacing the node in the graph from processGraphChanges is safe because it is the only graph writer.
This commit is contained in:
parent
cb7b9ed532
commit
cae56bea0a
@ -61,6 +61,25 @@ type node struct {
|
||||
owners []metav1.OwnerReference
|
||||
}
|
||||
|
||||
// clone() must only be called from the single-threaded GraphBuilder.processGraphChanges()
|
||||
func (n *node) clone() *node {
|
||||
c := &node{
|
||||
identity: n.identity,
|
||||
dependents: make(map[*node]struct{}, len(n.dependents)),
|
||||
deletingDependents: n.deletingDependents,
|
||||
beingDeleted: n.beingDeleted,
|
||||
virtual: n.virtual,
|
||||
owners: make([]metav1.OwnerReference, 0, len(n.owners)),
|
||||
}
|
||||
for dep := range n.dependents {
|
||||
c.dependents[dep] = struct{}{}
|
||||
}
|
||||
for _, owner := range n.owners {
|
||||
c.owners = append(c.owners, owner)
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// An object is on a one way trip to its final deletion if it starts being
|
||||
// deleted, so we only provide a function to set beingDeleted to true.
|
||||
func (n *node) markBeingDeleted() {
|
||||
|
@ -567,6 +567,14 @@ func (gb *GraphBuilder) processGraphChanges() bool {
|
||||
// this marks the node as having been observed via an informer event
|
||||
// 1. this depends on graphChanges only containing add/update events from the actual informer
|
||||
// 2. this allows things tracking virtual nodes' existence to stop polling and rely on informer events
|
||||
observedIdentity := identityFromEvent(event, accessor)
|
||||
if observedIdentity != existingNode.identity {
|
||||
// make a copy (so we don't modify the existing node in place), store the observed identity, and replace the virtual node
|
||||
klog.V(2).Infof("replacing virtual node %s with observed node %s", existingNode.identity, observedIdentity)
|
||||
existingNode = existingNode.clone()
|
||||
existingNode.identity = observedIdentity
|
||||
gb.uidToNode.Write(existingNode)
|
||||
}
|
||||
existingNode.markObserved()
|
||||
}
|
||||
switch {
|
||||
|
Loading…
Reference in New Issue
Block a user