Add fast path to node authorizer for node/edge removal

This commit is contained in:
Jordan Liggitt 2020-02-10 13:24:27 -05:00
parent 3e0c0792d7
commit 8a3f587b04

View File

@ -175,7 +175,7 @@ func (g *Graph) deleteVertex_locked(vertexType vertexType, namespace, name strin
// find existing neighbors with a single edge (meaning we are their only neighbor) // find existing neighbors with a single edge (meaning we are their only neighbor)
neighborsToRemove := []graph.Node{} neighborsToRemove := []graph.Node{}
neighborsToRecompute := []graph.Node{} edgesToRemoveFromIndexes := []graph.Edge{}
g.graph.VisitFrom(vertex, func(neighbor graph.Node) bool { g.graph.VisitFrom(vertex, func(neighbor graph.Node) bool {
// this downstream neighbor has only one edge (which must be from us), so remove them as well // this downstream neighbor has only one edge (which must be from us), so remove them as well
if g.graph.Degree(neighbor) == 1 { if g.graph.Degree(neighbor) == 1 {
@ -188,8 +188,8 @@ func (g *Graph) deleteVertex_locked(vertexType vertexType, namespace, name strin
// this upstream neighbor has only one edge (which must be to us), so remove them as well // this upstream neighbor has only one edge (which must be to us), so remove them as well
neighborsToRemove = append(neighborsToRemove, neighbor) neighborsToRemove = append(neighborsToRemove, neighbor)
} else { } else {
// recompute the destination edge index on this neighbor // decrement the destination edge index on this neighbor if the edge between us was a destination edge
neighborsToRecompute = append(neighborsToRecompute, neighbor) edgesToRemoveFromIndexes = append(edgesToRemoveFromIndexes, g.graph.EdgeBetween(vertex, neighbor))
} }
return true return true
}) })
@ -202,9 +202,9 @@ func (g *Graph) deleteVertex_locked(vertexType vertexType, namespace, name strin
g.removeVertex_locked(neighbor.(*namedVertex)) g.removeVertex_locked(neighbor.(*namedVertex))
} }
// recompute destination indexes for neighbors that dropped outbound edges // remove edges from destination indexes for neighbors that dropped outbound edges
for _, neighbor := range neighborsToRecompute { for _, edge := range edgesToRemoveFromIndexes {
g.recomputeDestinationIndex_locked(neighbor) g.removeEdgeFromDestinationIndex_locked(edge)
} }
} }
@ -220,19 +220,17 @@ func (g *Graph) deleteEdges_locked(fromType, toType vertexType, toNamespace, toN
// delete all edges between vertices of fromType and toVert // delete all edges between vertices of fromType and toVert
neighborsToRemove := []*namedVertex{} neighborsToRemove := []*namedVertex{}
neighborsToRecompute := []*namedVertex{} edgesToRemove := []graph.Edge{}
g.graph.VisitTo(toVert, func(from graph.Node) bool { g.graph.VisitTo(toVert, func(from graph.Node) bool {
fromVert := from.(*namedVertex) fromVert := from.(*namedVertex)
if fromVert.vertexType != fromType { if fromVert.vertexType != fromType {
return true return true
} }
// remove the edge // this neighbor has only one edge (which must be to us), so remove them as well
g.graph.RemoveEdge(simple.Edge{F: fromVert, T: toVert}) if g.graph.Degree(fromVert) == 1 {
// track vertexes that changed edges
if g.graph.Degree(fromVert) == 0 {
neighborsToRemove = append(neighborsToRemove, fromVert) neighborsToRemove = append(neighborsToRemove, fromVert)
} else { } else {
neighborsToRecompute = append(neighborsToRecompute, fromVert) edgesToRemove = append(edgesToRemove, g.graph.EdgeBetween(from, toVert))
} }
return true return true
}) })
@ -242,9 +240,30 @@ func (g *Graph) deleteEdges_locked(fromType, toType vertexType, toNamespace, toN
g.removeVertex_locked(v) g.removeVertex_locked(v)
} }
// recompute destination indexes for neighbors that dropped outbound edges // remove edges and decrement destination indexes for neighbors that dropped outbound edges
for _, v := range neighborsToRecompute { for _, edge := range edgesToRemove {
g.recomputeDestinationIndex_locked(v) g.graph.RemoveEdge(edge)
g.removeEdgeFromDestinationIndex_locked(edge)
}
}
// A fastpath for recomputeDestinationIndex_locked for "removing edge" case.
func (g *Graph) removeEdgeFromDestinationIndex_locked(e graph.Edge) {
n := e.From()
// don't maintain indices for nodes with few edges
edgeCount := g.graph.Degree(n)
if edgeCount < g.destinationEdgeThreshold {
delete(g.destinationEdgeIndex, n.ID())
return
}
// decrement the nodeID->destinationID refcount in the index, if the index exists
index := g.destinationEdgeIndex[n.ID()]
if index == nil {
return
}
if destinationEdge, ok := e.(*destinationEdge); ok {
index.decrement(destinationEdge.DestinationID())
} }
} }
@ -300,12 +319,7 @@ func (g *Graph) recomputeDestinationIndex_locked(n graph.Node) {
} }
return true return true
}) })
g.destinationEdgeIndex[n.ID()] = index
if len(index.members) < g.destinationEdgeThreshold {
delete(g.destinationEdgeIndex, n.ID())
} else {
g.destinationEdgeIndex[n.ID()] = index
}
} }
// AddPod should only be called once spec.NodeName is populated. // AddPod should only be called once spec.NodeName is populated.