1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00
moby--moby/vendor/github.com/docker/swarmkit/manager/scheduler/pipeline.go
Alexander Morozov f2614f2107 project: use vndr for vendoring
Signed-off-by: Alexander Morozov <lk4d4@docker.com>
2016-11-03 15:31:46 -07:00

101 lines
2.5 KiB
Go

package scheduler
import (
"sort"
"github.com/docker/swarmkit/api"
)
var (
defaultFilters = []Filter{
// Always check for readiness first.
&ReadyFilter{},
&ResourceFilter{},
// TODO(stevvooe): Do not filter based on plugins since they are lazy
// loaded in the engine. We can add this back when we can schedule
// plugins in the future.
// &PluginFilter{},
&ConstraintFilter{},
}
)
type checklistEntry struct {
f Filter
enabled bool
// failureCount counts the number of nodes that this filter failed
// against.
failureCount int
}
type checklistByFailures []checklistEntry
func (c checklistByFailures) Len() int { return len(c) }
func (c checklistByFailures) Swap(i, j int) { c[i], c[j] = c[j], c[i] }
func (c checklistByFailures) Less(i, j int) bool { return c[i].failureCount < c[j].failureCount }
// Pipeline runs a set of filters against nodes.
type Pipeline struct {
// checklist is a slice of filters to run
checklist []checklistEntry
}
// NewPipeline returns a pipeline with the default set of filters.
func NewPipeline() *Pipeline {
p := &Pipeline{}
for _, f := range defaultFilters {
p.checklist = append(p.checklist, checklistEntry{f: f})
}
return p
}
// Process a node through the filter pipeline.
// Returns true if all filters pass, false otherwise.
func (p *Pipeline) Process(n *NodeInfo) bool {
for i, entry := range p.checklist {
if entry.enabled && !entry.f.Check(n) {
// Immediately stop on first failure.
p.checklist[i].failureCount++
return false
}
}
for i := range p.checklist {
p.checklist[i].failureCount = 0
}
return true
}
// SetTask sets up the filters to process a new task. Once this is called,
// Process can be called repeatedly to try to assign the task various nodes.
func (p *Pipeline) SetTask(t *api.Task) {
for i := range p.checklist {
p.checklist[i].enabled = p.checklist[i].f.SetTask(t)
p.checklist[i].failureCount = 0
}
}
// Explain returns a string explaining why a task could not be scheduled.
func (p *Pipeline) Explain() string {
var explanation string
// Sort from most failures to least
sortedByFailures := make([]checklistEntry, len(p.checklist))
copy(sortedByFailures, p.checklist)
sort.Sort(sort.Reverse(checklistByFailures(sortedByFailures)))
for _, entry := range sortedByFailures {
if entry.failureCount > 0 {
if len(explanation) > 0 {
explanation += "; "
}
explanation += entry.f.Explain(entry.failureCount)
}
}
return explanation
}