diff --git a/render/render.go b/render/render.go index c67fbdf7c9..48bd250d7e 100644 --- a/render/render.go +++ b/render/render.go @@ -163,7 +163,8 @@ func (cr conditionalRenderer) Render(rpt report.Report) Nodes { // joinResults is used by Renderers that join sets of nodes type joinResults struct { nodes report.Nodes - mapped map[string]string // input node ID -> output node ID + mapped map[string]string // input node ID -> output node ID - common case + multi map[string][]string // input node ID -> output node IDs - exceptional case } func newJoinResults(inputNodes report.Nodes) joinResults { @@ -172,12 +173,16 @@ func newJoinResults(inputNodes report.Nodes) joinResults { n.Adjacency = nil // result() assumes all nodes start with no adjacencies nodes[id] = n } - return joinResults{nodes: nodes, mapped: map[string]string{}} + return joinResults{nodes: nodes, mapped: map[string]string{}, multi: map[string][]string{}} } func (ret *joinResults) add(m report.Node, n report.Node) { ret.nodes[n.ID] = n - ret.mapped[m.ID] = n.ID + if _, ok := ret.mapped[m.ID]; !ok { + ret.mapped[m.ID] = n.ID + } else { + ret.multi[m.ID] = append(ret.multi[m.ID], n.ID) + } } // Add m as a child of the node at id, creating a new result node if @@ -222,19 +227,27 @@ func (ret *joinResults) result(input Nodes) Nodes { if !ok { continue } - out := ret.nodes[outID] - // for each adjacency in the original node, find out what it maps to (if any), - // and add that to the new node - for _, a := range n.Adjacency { - if mappedDest, found := ret.mapped[a]; found { - out.Adjacency = out.Adjacency.Add(mappedDest) - } + ret.rewriteAdjacency(outID, n.Adjacency) + for _, outID := range ret.multi[n.ID] { + ret.rewriteAdjacency(outID, n.Adjacency) } - ret.nodes[outID] = out } return Nodes{Nodes: ret.nodes} } +func (ret *joinResults) rewriteAdjacency(outID string, adjacency report.IDList) { + out := ret.nodes[outID] + // for each adjacency in the original node, find out what it maps + // to (if any), and add that to the new node + for _, a := range adjacency { + if mappedDest, found := ret.mapped[a]; found { + out.Adjacency = out.Adjacency.Add(mappedDest) + out.Adjacency = out.Adjacency.Add(ret.multi[a]...) + } + } + ret.nodes[outID] = out +} + // ResetCache blows away the rendered node cache, and known service // cache. func ResetCache() {