scheduler: adding various iterators

This commit is contained in:
Armon Dadgar 2015-08-11 18:27:54 -07:00
parent e49f1d4da6
commit 9943b83463
3 changed files with 175 additions and 0 deletions

View file

@ -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
}

76
scheduler/rank.go Normal file
View file

@ -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
}
}

62
scheduler/select.go Normal file
View file

@ -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
}