scheduler: adding various iterators
This commit is contained in:
parent
e49f1d4da6
commit
9943b83463
|
@ -100,3 +100,40 @@ func (iter *ConstraintIterator) meetsConstraints(option *structs.Node) bool {
|
|||
// TODO:
|
||||
return true
|
||||
}
|
||||
|
||||
// DriverIterator is a FeasibleIterator which returns nodes that
|
||||
// have the drivers necessary to scheduler a task group.
|
||||
type DriverIterator struct {
|
||||
ctx Context
|
||||
source FeasibleIterator
|
||||
drivers map[string]struct{}
|
||||
}
|
||||
|
||||
// NewDriverIterator creates a DriverIterator from a source and set of drivers
|
||||
func NewDriverIterator(ctx Context, source FeasibleIterator, drivers map[string]struct{}) *DriverIterator {
|
||||
iter := &DriverIterator{
|
||||
ctx: ctx,
|
||||
source: source,
|
||||
drivers: drivers,
|
||||
}
|
||||
return iter
|
||||
}
|
||||
|
||||
func (iter *DriverIterator) Next() *structs.Node {
|
||||
for {
|
||||
// Get the next option from the source
|
||||
option := iter.source.Next()
|
||||
if option == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Use this node if possible
|
||||
if iter.hasDrivers(option) {
|
||||
return option
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (iter *DriverIterator) hasDrivers(option *structs.Node) bool {
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
package scheduler
|
||||
|
||||
import "github.com/hashicorp/nomad/nomad/structs"
|
||||
|
||||
// Rank is used to provide a score and various ranking metadata
|
||||
// along with a node when iterating. This state can be modified as
|
||||
// various rank methods are applied.
|
||||
type RankedNode struct {
|
||||
Node *structs.Node
|
||||
Score float64
|
||||
}
|
||||
|
||||
// RankFeasibleIterator is used to iteratively yield nodes along
|
||||
// with ranking metadata. The iterators may manage some state for
|
||||
// performance optimizations.
|
||||
type RankIterator interface {
|
||||
Next() *RankedNode
|
||||
}
|
||||
|
||||
// FeasibleRankIterator is used to consume from a FeasibleIterator
|
||||
// and return an unranked node with base ranking.
|
||||
type FeasibleRankIterator struct {
|
||||
source FeasibleIterator
|
||||
}
|
||||
|
||||
// NewFeasibleRankIterator is used to return a new FeasibleRankIterator
|
||||
// from a FeasibleIterator source.
|
||||
func NewFeasibleRankIterator(ctx Context, source FeasibleIterator) *FeasibleRankIterator {
|
||||
iter := &FeasibleRankIterator{
|
||||
source: source,
|
||||
}
|
||||
return iter
|
||||
}
|
||||
|
||||
func (iter *FeasibleRankIterator) Next() *RankedNode {
|
||||
option := iter.source.Next()
|
||||
ranked := &RankedNode{
|
||||
Node: option,
|
||||
}
|
||||
return ranked
|
||||
}
|
||||
|
||||
// BinPackIterator is a RankIterator that scores potential options
|
||||
// based on a bin-packing algorithm.
|
||||
type BinPackIterator struct {
|
||||
ctx Context
|
||||
source RankIterator
|
||||
resources *structs.Resources
|
||||
evict bool
|
||||
priority int
|
||||
}
|
||||
|
||||
// NewBinPackIterator returns a BinPackIterator which tries to fit the given
|
||||
// resources, potentially evicting other tasks based on a given priority.
|
||||
func NewBinPackIterator(ctx Context, source RankIterator, resources *structs.Resources, evict bool, priority int) *BinPackIterator {
|
||||
iter := &BinPackIterator{
|
||||
ctx: ctx,
|
||||
source: source,
|
||||
resources: resources,
|
||||
evict: evict,
|
||||
priority: priority,
|
||||
}
|
||||
return iter
|
||||
}
|
||||
|
||||
func (iter *BinPackIterator) Next() *RankedNode {
|
||||
for {
|
||||
option := iter.source.Next()
|
||||
if option == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// TODO: Evaluate the bin packing
|
||||
return option
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
package scheduler
|
||||
|
||||
// LimitIterator is a RankIterator used to limit the number of options
|
||||
// that are returned before we artifically end the stream.
|
||||
type LimitIterator struct {
|
||||
ctx Context
|
||||
source RankIterator
|
||||
limit int
|
||||
seen int
|
||||
}
|
||||
|
||||
// NewLimitIterator is returns a LimitIterator with a fixed limit of returned options
|
||||
func NewLimitIterator(ctx Context, source RankIterator, limit int) *LimitIterator {
|
||||
iter := &LimitIterator{
|
||||
ctx: ctx,
|
||||
source: source,
|
||||
limit: limit,
|
||||
}
|
||||
return iter
|
||||
}
|
||||
|
||||
func (iter *LimitIterator) Next() *RankedNode {
|
||||
if iter.seen == iter.limit {
|
||||
return nil
|
||||
}
|
||||
|
||||
option := iter.source.Next()
|
||||
if option == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
iter.seen += 1
|
||||
return option
|
||||
}
|
||||
|
||||
// MaxScoreIterator is a RankIterator used to return only a single result
|
||||
// of the item with the highest score. This iterator will consume all of the
|
||||
// possible inputs and only returns the highest ranking result.
|
||||
type MaxScoreIterator struct {
|
||||
ctx Context
|
||||
source RankIterator
|
||||
max *RankedNode
|
||||
}
|
||||
|
||||
func (iter *MaxScoreIterator) Next() *RankedNode {
|
||||
for {
|
||||
option := iter.source.Next()
|
||||
if option == nil {
|
||||
break
|
||||
}
|
||||
|
||||
if iter.max == nil {
|
||||
iter.max = option
|
||||
continue
|
||||
}
|
||||
|
||||
if option.Score > iter.max.Score {
|
||||
iter.max = option
|
||||
}
|
||||
}
|
||||
return iter.max
|
||||
}
|
Loading…
Reference in New Issue