-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathplan_options.go
208 lines (188 loc) · 5.2 KB
/
plan_options.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
package running
import "fmt"
type Option func(*_DAG)
// AddNodes add nodes.
// typ declare node type, names declare name of each one.
// node must be added before other options.
var AddNodes = func(typ string, names ...string) Option {
return func(dag *_DAG) {
for _, name := range names {
if _, ok := dag.NodeRefs[name]; !ok {
dag.NodeRefs[name] = &_NodeRef{
NodeName: name,
NodeType: typ,
}
}
}
}
}
// AddVirtualNodes similar to AddNodes, except the nodes are virtual.
var AddVirtualNodes = func(names ...string) Option {
return func(dag *_DAG) {
for _, name := range names {
if _, ok := dag.NodeRefs[name]; !ok {
dag.NodeRefs[name] = &_NodeRef{
NodeName: name,
Virtual: true,
}
}
}
}
}
// MergeNodes merge other nodes as sub-node of the first node.
// example: MergeNodes("A", "B", "C").
// if node "A" implement the Cluster interface, node "B" and "C" will be injected,
// then "A" could use "B" and "C" as sub-nodes.
var MergeNodes = func(cluster string, subNodes ...string) Option {
return func(dag *_DAG) {
if clusterRef, ok := dag.NodeRefs[cluster]; !ok {
dag.Warning = append(dag.Warning, fmt.Sprintf("cluster %s ref not found", cluster))
return
} else {
for _, node := range subNodes {
if _, ok := dag.NodeRefs[node]; ok {
clusterRef.SubRefs = append(clusterRef.SubRefs, dag.NodeRefs[node])
} else {
dag.Warning = append(dag.Warning, fmt.Sprintf("sub node %s ref not found", node))
}
}
}
}
}
// WrapNodes wrap node to enhance it,
// wrapper:node type which implement Wrapper,
// targets:wrap targets
var WrapNodes = func(wrapper string, targets ...string) Option {
return func(dag *_DAG) {
for _, target := range targets {
if targetNodeRef := dag.NodeRefs[target]; targetNodeRef != nil {
targetNodeRef.Wrappers = append(targetNodeRef.Wrappers, wrapper)
} else {
dag.Warning = append(dag.Warning, fmt.Sprintf("wrap target node %s ref not found", target))
}
}
}
}
// WrapAllNodes wrap all nodes with single or multi wrappers,
// will only affect nodes added before this
var WrapAllNodes = func(wrappers ...string) Option {
return func(dag *_DAG) {
for _, wrapper := range wrappers {
for _, ref := range dag.NodeRefs {
if ref != nil {
ref.Wrappers = append(ref.Wrappers, wrapper)
}
}
}
}
}
// ReUseNodes reuse node to avoid unnecessary rebuilds,
// fits nodes whose properties do not change and implements the clone method
var ReUseNodes = func(nodes ...string) Option {
return func(dag *_DAG) {
for _, node := range nodes {
if dag.NodeRefs[node] != nil {
dag.NodeRefs[node].ReUse = true
}
}
}
}
// MarkNodes set label of nodes
var MarkNodes = func(label string, nodes ...string) Option {
return func(dag *_DAG) {
for _, node := range nodes {
if dag.NodeRefs[node] != nil {
ref := dag.NodeRefs[node]
if ref.Labels == nil {
ref.Labels = make(map[string]struct{})
}
ref.Labels[label] = struct{}{}
}
}
}
}
// LinkNodes link first node with others.
// example: LinkNodes("A", "B", "C") => A -> B, A -> C.
var LinkNodes = func(nodes ...string) Option {
return func(dag *_DAG) {
if len(nodes) < 1 {
return
}
for _, root := range nodes {
if _, ok := dag.Vertexes[root]; !ok {
if _, ok := dag.NodeRefs[root]; ok {
dag.Vertexes[root] = &_Vertex{
RefRoot: dag.NodeRefs[root],
}
} else {
dag.Warning = append(dag.Warning, fmt.Sprintf("link target node %s ref not found", root))
}
}
}
if dag.Vertexes[nodes[0]] != nil {
for _, node := range nodes[1:] {
if dag.Vertexes[node] != nil {
dag.Vertexes[nodes[0]].Next = append(dag.Vertexes[nodes[0]].Next, dag.Vertexes[node])
dag.Vertexes[node].Prev++
}
}
}
}
}
// SLinkNodes link nodes serially.
// example: SLinkNodes("A", "B", "C") => A -> B -> C.
var SLinkNodes = func(nodes ...string) Option {
return func(dag *_DAG) {
if len(nodes) < 1 {
return
}
for _, root := range nodes {
if _, ok := dag.Vertexes[root]; !ok {
if _, ok := dag.NodeRefs[root]; ok {
dag.Vertexes[root] = &_Vertex{
RefRoot: dag.NodeRefs[root],
}
} else {
dag.Warning = append(dag.Warning, fmt.Sprintf("Slink target node %s ref not found", root))
}
}
}
for i := range nodes {
if i < len(nodes)-1 {
prev, next := dag.Vertexes[nodes[i]], dag.Vertexes[nodes[i+1]]
if prev != nil && next != nil {
prev.Next = append(prev.Next, next)
next.Prev++
}
}
}
}
}
// RLinkNodes link first node with others.
// example: RLinkNodes("A", "B", "C") => B -> A, C -> A.
var RLinkNodes = func(nodes ...string) Option {
return func(dag *_DAG) {
if len(nodes) < 1 {
return
}
for _, root := range nodes {
if _, ok := dag.Vertexes[root]; !ok {
if _, ok := dag.NodeRefs[root]; ok {
dag.Vertexes[root] = &_Vertex{
RefRoot: dag.NodeRefs[root],
}
} else {
dag.Warning = append(dag.Warning, fmt.Sprintf("link target node %s ref not found", root))
}
}
}
if dag.Vertexes[nodes[0]] != nil {
for _, node := range nodes[1:] {
if dag.Vertexes[node] != nil {
dag.Vertexes[node].Next = append(dag.Vertexes[node].Next, dag.Vertexes[nodes[0]])
dag.Vertexes[nodes[0]].Prev++
}
}
}
}
}