-
Notifications
You must be signed in to change notification settings - Fork 1.7k
/
node_selector_priority_level.go
103 lines (85 loc) · 2.35 KB
/
node_selector_priority_level.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
package client
import (
"math"
"sort"
"sync/atomic"
)
type priorityLevelNodeSelector struct {
nodes []Node
roundRobinCount []atomic.Uint32
}
type nodeWithPriority struct {
node Node
priority int32
}
func NewPriorityLevelNodeSelector(nodes []Node) NodeSelector {
return &priorityLevelNodeSelector{
nodes: nodes,
roundRobinCount: make([]atomic.Uint32, nrOfPriorityTiers(nodes)),
}
}
func (s priorityLevelNodeSelector) Select() Node {
nodes := s.getHighestPriorityAliveTier()
if len(nodes) == 0 {
return nil
}
priorityLevel := nodes[len(nodes)-1].priority
// NOTE: Inc returns the number after addition, so we must -1 to get the "current" counter
count := s.roundRobinCount[priorityLevel].Add(1) - 1
idx := int(count % uint32(len(nodes)))
return nodes[idx].node
}
func (s priorityLevelNodeSelector) Name() string {
return NodeSelectionMode_PriorityLevel
}
// getHighestPriorityAliveTier filters nodes that are not in state NodeStateAlive and
// returns only the highest tier of alive nodes
func (s priorityLevelNodeSelector) getHighestPriorityAliveTier() []nodeWithPriority {
var nodes []nodeWithPriority
for _, n := range s.nodes {
if n.State() == NodeStateAlive {
nodes = append(nodes, nodeWithPriority{n, n.Order()})
}
}
if len(nodes) == 0 {
return nil
}
return removeLowerTiers(nodes)
}
// removeLowerTiers take a slice of nodeWithPriority and keeps only the highest tier
func removeLowerTiers(nodes []nodeWithPriority) []nodeWithPriority {
sort.SliceStable(nodes, func(i, j int) bool {
return nodes[i].priority > nodes[j].priority
})
var nodes2 []nodeWithPriority
currentPriority := nodes[len(nodes)-1].priority
for _, n := range nodes {
if n.priority == currentPriority {
nodes2 = append(nodes2, n)
}
}
return nodes2
}
// nrOfPriorityTiers calculates the total number of priority tiers
func nrOfPriorityTiers(nodes []Node) int32 {
highestPriority := int32(0)
for _, n := range nodes {
priority := n.Order()
if highestPriority < priority {
highestPriority = priority
}
}
return highestPriority + 1
}
// firstOrHighestPriority takes a list of nodes and returns the first one with the highest priority
func firstOrHighestPriority(nodes []Node) Node {
hp := int32(math.MaxInt32)
var node Node
for _, n := range nodes {
if n.Order() < hp {
hp = n.Order()
node = n
}
}
return node
}