github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/swarmkit/manager/scheduler/pipeline.go (about) 1 package scheduler 2 3 import ( 4 "sort" 5 6 "github.com/docker/swarmkit/api" 7 ) 8 9 var ( 10 defaultFilters = []Filter{ 11 // Always check for readiness first. 12 &ReadyFilter{}, 13 &ResourceFilter{}, 14 &PluginFilter{}, 15 &ConstraintFilter{}, 16 &PlatformFilter{}, 17 &HostPortFilter{}, 18 &MaxReplicasFilter{}, 19 } 20 ) 21 22 type checklistEntry struct { 23 f Filter 24 enabled bool 25 26 // failureCount counts the number of nodes that this filter failed 27 // against. 28 failureCount int 29 } 30 31 type checklistByFailures []checklistEntry 32 33 func (c checklistByFailures) Len() int { return len(c) } 34 func (c checklistByFailures) Swap(i, j int) { c[i], c[j] = c[j], c[i] } 35 func (c checklistByFailures) Less(i, j int) bool { return c[i].failureCount < c[j].failureCount } 36 37 // Pipeline runs a set of filters against nodes. 38 type Pipeline struct { 39 // checklist is a slice of filters to run 40 checklist []checklistEntry 41 } 42 43 // NewPipeline returns a pipeline with the default set of filters. 44 func NewPipeline() *Pipeline { 45 p := &Pipeline{} 46 47 for _, f := range defaultFilters { 48 p.checklist = append(p.checklist, checklistEntry{f: f}) 49 } 50 51 return p 52 } 53 54 // Process a node through the filter pipeline. 55 // Returns true if all filters pass, false otherwise. 56 func (p *Pipeline) Process(n *NodeInfo) bool { 57 for i, entry := range p.checklist { 58 if entry.enabled && !entry.f.Check(n) { 59 // Immediately stop on first failure. 60 p.checklist[i].failureCount++ 61 return false 62 } 63 } 64 for i := range p.checklist { 65 p.checklist[i].failureCount = 0 66 } 67 return true 68 } 69 70 // SetTask sets up the filters to process a new task. Once this is called, 71 // Process can be called repeatedly to try to assign the task various nodes. 72 func (p *Pipeline) SetTask(t *api.Task) { 73 for i := range p.checklist { 74 p.checklist[i].enabled = p.checklist[i].f.SetTask(t) 75 p.checklist[i].failureCount = 0 76 } 77 } 78 79 // Explain returns a string explaining why a task could not be scheduled. 80 func (p *Pipeline) Explain() string { 81 var explanation string 82 83 // Sort from most failures to least 84 85 sortedByFailures := make([]checklistEntry, len(p.checklist)) 86 copy(sortedByFailures, p.checklist) 87 sort.Sort(sort.Reverse(checklistByFailures(sortedByFailures))) 88 89 for _, entry := range sortedByFailures { 90 if entry.failureCount > 0 { 91 if len(explanation) > 0 { 92 explanation += "; " 93 } 94 explanation += entry.f.Explain(entry.failureCount) 95 } 96 } 97 98 return explanation 99 }