filter unconnected nodes after applying user-specified filters

...rather than before. That way, nodes which become unconnected during
filtering are removed, which is what we want. ATM we are depending on
some 'unconnected' filtering inside every filter, which is expensive
and largely redundant. We should soon be able to remove that.

downside: 'unconnected' filtering is no longer memoised.
This commit is contained in:
Matthias Radestock
2017-11-22 20:10:13 +00:00
parent 2d964b669a
commit 9dca7627b6
2 changed files with 18 additions and 24 deletions

View File

@@ -318,7 +318,7 @@ type APITopologyDesc struct {
id string
parent string
renderer render.Renderer
filter func(render.Renderer) render.Renderer
filter render.Transformer
Name string `json:"name"`
Rank int `json:"rank"`
@@ -447,7 +447,7 @@ func (r *Registry) Add(ts ...APITopologyDesc) {
defer r.Unlock()
for _, t := range ts {
t.URL = apiTopologyURL + t.id
t.renderer = render.Memoise(t.filter(t.renderer))
t.renderer = render.Memoise(t.renderer)
if t.parent != "" {
parent := r.items[t.parent]
@@ -541,8 +541,8 @@ func (r *Registry) RendererForTopology(topologyID string, values url.Values, rpt
topology = updateFilters(rpt, []APITopologyDesc{topology})[0]
if len(values) == 0 {
// Do not apply filtering if no options where provided
return topology.renderer, render.Transformers(nil), nil
// if no options where provided, only apply base filter
return topology.renderer, topology.filter, nil
}
var filters []render.FilterFunc
@@ -553,9 +553,9 @@ func (r *Registry) RendererForTopology(topologyID string, values url.Values, rpt
}
}
if len(filters) > 0 {
return topology.renderer, render.ComposeFilterFuncs(filters...), nil
return topology.renderer, render.Transformers([]render.Transformer{render.ComposeFilterFuncs(filters...), topology.filter}), nil
}
return topology.renderer, render.Transformers(nil), nil
return topology.renderer, topology.filter, nil
}
type reporterHandler func(context.Context, Reporter, http.ResponseWriter, *http.Request)

View File

@@ -175,12 +175,17 @@ func ColorConnected(r Renderer) Renderer {
}
}
func filterUnconnected(input Nodes, onlyPseudo bool) Nodes {
type filterUnconnected struct {
onlyPseudo bool
}
// Transform implements Transformer
func (f filterUnconnected) Transform(input Nodes) Nodes {
connected := connected(input.Nodes)
output := report.Nodes{}
filtered := input.Filtered
for id, node := range input.Nodes {
if _, ok := connected[id]; ok || (onlyPseudo && !IsPseudoTopology(node)) {
if _, ok := connected[id]; ok || (f.onlyPseudo && !IsPseudoTopology(node)) {
output[id] = node
} else {
filtered++
@@ -200,23 +205,12 @@ func filterUnconnected(input Nodes, onlyPseudo bool) Nodes {
return Nodes{Nodes: output, Filtered: filtered}
}
// FilterUnconnected produces a renderer that filters unconnected nodes
// from the given renderer
func FilterUnconnected(r Renderer) Renderer {
return CustomRenderer{
Renderer: r,
RenderFunc: func(input Nodes) Nodes { return filterUnconnected(input, false) },
}
}
// FilterUnconnected is a transformer that filters unconnected nodes
var FilterUnconnected = filterUnconnected{onlyPseudo: false}
// FilterUnconnectedPseudo produces a renderer that filters
// unconnected pseudo nodes from the given renderer
func FilterUnconnectedPseudo(r Renderer) Renderer {
return CustomRenderer{
Renderer: r,
RenderFunc: func(input Nodes) Nodes { return filterUnconnected(input, true) },
}
}
// FilterUnconnectedPseudo is a transformer that filters unconnected
// pseudo nodes
var FilterUnconnectedPseudo = filterUnconnected{onlyPseudo: true}
// Noop allows all nodes through
func Noop(_ report.Node) bool { return true }