Rework graph & builder
Make nodes persist through runs (easier re-running).
This commit is contained in:
@@ -64,9 +64,7 @@ func (b *graphBuilder) Build(ctx context.Context, rr ...resource.Interface) (*gr
|
||||
}
|
||||
}
|
||||
|
||||
// @todo fixme..
|
||||
g.invert()
|
||||
g.DryRun()
|
||||
|
||||
// Do any dep. related preprocessing
|
||||
var state *ExecState
|
||||
@@ -93,13 +91,12 @@ func (b *graphBuilder) Build(ctx context.Context, rr ...resource.Interface) (*gr
|
||||
}
|
||||
}()
|
||||
|
||||
g.Relink()
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// @todo fixme..
|
||||
g.invert()
|
||||
g.ProdRun()
|
||||
|
||||
g.reset()
|
||||
return g, nil
|
||||
}
|
||||
|
||||
+76
-34
@@ -8,15 +8,18 @@ import (
|
||||
)
|
||||
|
||||
type (
|
||||
nodeMap map[*node]bool
|
||||
|
||||
graph struct {
|
||||
nn nodeSet
|
||||
nn nodeSet
|
||||
resIndex map[resource.Interface]*node
|
||||
|
||||
// Config flags
|
||||
inverted bool
|
||||
dry bool
|
||||
|
||||
processed nodeSet
|
||||
conflicting nodeSet
|
||||
processed nodeMap
|
||||
conflicting nodeMap
|
||||
}
|
||||
|
||||
ExecState struct {
|
||||
@@ -26,18 +29,27 @@ type (
|
||||
DepResources []resource.Interface
|
||||
ParentResources []resource.Interface
|
||||
}
|
||||
|
||||
// Provides a filter for graph iterator
|
||||
iterFilter struct {
|
||||
resourceType string
|
||||
}
|
||||
)
|
||||
|
||||
func newGraph() *graph {
|
||||
return &graph{
|
||||
nn: make(nodeSet, 0, 100),
|
||||
resIndex: make(map[resource.Interface]*node),
|
||||
inverted: false,
|
||||
processed: make(nodeSet, 0, 100),
|
||||
conflicting: make(nodeSet, 0, 100),
|
||||
processed: make(nodeMap),
|
||||
conflicting: make(nodeMap),
|
||||
}
|
||||
}
|
||||
|
||||
func (g *graph) addNode(nn ...*node) {
|
||||
for _, n := range nn {
|
||||
g.resIndex[n.res] = n
|
||||
}
|
||||
g.nn = g.nn.add(nn...)
|
||||
}
|
||||
|
||||
@@ -49,16 +61,6 @@ func (g *graph) invert() {
|
||||
g.inverted = !g.inverted
|
||||
}
|
||||
|
||||
func (g *graph) DryRun() {
|
||||
g.dry = true
|
||||
g.purge(true)
|
||||
}
|
||||
|
||||
func (g *graph) ProdRun() {
|
||||
g.dry = false
|
||||
g.purge(true)
|
||||
}
|
||||
|
||||
func (g *graph) childNodes(n *node) nodeSet {
|
||||
if g.inverted {
|
||||
return n.pp
|
||||
@@ -86,12 +88,55 @@ func (g *graph) markConflicting(n *node) {
|
||||
g.conflicting = g.conflicting.add(n)
|
||||
}
|
||||
|
||||
func (g *graph) Relink() {
|
||||
for res := range g.resIndex {
|
||||
n := g.resIndex[res]
|
||||
if n == nil {
|
||||
return
|
||||
}
|
||||
|
||||
refs := res.Refs()
|
||||
cc := g.childNodes(n)
|
||||
|
||||
for _, ref := range refs {
|
||||
// If it's already linked, skip it
|
||||
if cc.findByRef(ref) != nil {
|
||||
continue
|
||||
}
|
||||
// else find the node and link to it (if we can)
|
||||
m := g.nn.findByRef(ref)
|
||||
if m != nil {
|
||||
g.addChild(n, m)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (g *graph) Next(ctx context.Context) (s *ExecState, err error) {
|
||||
return g.next(ctx, nil)
|
||||
}
|
||||
|
||||
func (g *graph) NextOf(ctx context.Context, resTrype string) (s *ExecState, err error) {
|
||||
return g.next(ctx, &iterFilter{resourceType: resTrype})
|
||||
}
|
||||
|
||||
func (g *graph) next(ctx context.Context, f *iterFilter) (s *ExecState, err error) {
|
||||
upNN := g.removeProcessed(g.nodes())
|
||||
|
||||
if f != nil {
|
||||
upC := make(nodeSet, 0, len(upNN))
|
||||
if f.resourceType != "" {
|
||||
for _, n := range upNN {
|
||||
if n.res.ResourceType() == f.resourceType {
|
||||
upC = append(upC, n)
|
||||
}
|
||||
}
|
||||
}
|
||||
upNN = upC
|
||||
}
|
||||
|
||||
// We are done here
|
||||
if len(upNN) <= 0 {
|
||||
g.purge(g.dry)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@@ -112,17 +157,6 @@ func (g *graph) Next(ctx context.Context) (s *ExecState, err error) {
|
||||
es := g.prepExecState(nx, false)
|
||||
|
||||
g.markProcessed(nx)
|
||||
pp := g.parentNodes(nx)
|
||||
g.removeParent(nx)
|
||||
|
||||
for _, p := range pp {
|
||||
g.removeChild(p, nx)
|
||||
if len(g.childNodes(p)) <= 0 && g.processed.has(p) {
|
||||
g.removeNode(p)
|
||||
g.processed = g.processed.remove(p)
|
||||
g.conflicting = g.conflicting.remove(p)
|
||||
}
|
||||
}
|
||||
|
||||
return es, nil
|
||||
}
|
||||
@@ -148,13 +182,9 @@ func (g *graph) Next(ctx context.Context) (s *ExecState, err error) {
|
||||
}
|
||||
}
|
||||
|
||||
func (g *graph) purge(partial bool) {
|
||||
g.conflicting = nil
|
||||
g.processed = nil
|
||||
|
||||
if !partial {
|
||||
g.nn = nil
|
||||
}
|
||||
func (g *graph) reset() {
|
||||
g.conflicting = make(nodeMap)
|
||||
g.processed = make(nodeMap)
|
||||
}
|
||||
|
||||
// util
|
||||
@@ -258,3 +288,15 @@ func (g *graph) prepExecState(n *node, conflicting bool) *ExecState {
|
||||
Conflicting: conflicting,
|
||||
}
|
||||
}
|
||||
|
||||
func (nm nodeMap) add(n *node) nodeMap {
|
||||
nm[n] = true
|
||||
return nm
|
||||
}
|
||||
func (nm nodeMap) has(n *node) bool {
|
||||
return nm[n]
|
||||
}
|
||||
func (nm nodeMap) remove(n *node) nodeMap {
|
||||
delete(nm, n)
|
||||
return nm
|
||||
}
|
||||
|
||||
@@ -37,6 +37,18 @@ func (nn nodeSet) filter(f func(n *node) bool) nodeSet {
|
||||
return mm
|
||||
}
|
||||
|
||||
func (nn nodeSet) findByRef(ref *resource.Ref) *node {
|
||||
for _, n := range nn {
|
||||
if n.res.ResourceType() == ref.ResourceType {
|
||||
if n.res.Identifiers().HasAny(ref.Identifiers.StringSlice()...) {
|
||||
return n
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (nn nodeSet) has(m *node) bool {
|
||||
for _, n := range nn {
|
||||
if n == m {
|
||||
|
||||
Reference in New Issue
Block a user