switch to logrus for logging. replaced old logging library with a wrapper around logrus. We now just need to use the exported Log(...) and Logf(...) from the logging/ package that wraps around a set of loggers constituting a chain (following COR). Loggers are configured using a YAML file that specifies the following. 1. enabled/disabled 2. whether the message should be logged on console. 3. filename extension. 4. minimum log level. Retrofitted source code to now use the updated logging library. Updated the documentation with information regarding the specification of the log config file. Currently, the log format in the config file is not adhered to. This is going to be addressed in a future commit.
140 lines
4.6 KiB
Go
140 lines
4.6 KiB
Go
// Copyright (C) 2018 spdfg
|
|
//
|
|
// This file is part of Elektron.
|
|
//
|
|
// Elektron is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// Elektron is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with Elektron. If not, see <http://www.gnu.org/licenses/>.
|
|
//
|
|
|
|
package schedulers
|
|
|
|
import (
|
|
"encoding/json"
|
|
"os"
|
|
"sort"
|
|
|
|
sched "github.com/mesos/mesos-go/api/v0/scheduler"
|
|
"github.com/pkg/errors"
|
|
"github.com/spdfg/elektron/utilities"
|
|
)
|
|
|
|
// Names of different scheduling policies.
|
|
const (
|
|
ff = "first-fit"
|
|
bp = "bin-packing"
|
|
mgm = "max-greedymins"
|
|
mm = "max-min"
|
|
)
|
|
|
|
// Scheduling policy factory
|
|
var SchedPolicies map[string]SchedPolicyState = map[string]SchedPolicyState{
|
|
ff: &FirstFit{},
|
|
bp: &BinPackSortedWatts{},
|
|
mgm: &MaxGreedyMins{},
|
|
mm: &MaxMin{},
|
|
}
|
|
|
|
// Scheduling policies to choose when switching
|
|
var schedPoliciesToSwitch map[int]struct {
|
|
spName string
|
|
sp SchedPolicyState
|
|
} = make(map[int]struct {
|
|
spName string
|
|
sp SchedPolicyState
|
|
})
|
|
|
|
// Initialize scheduling policy characteristics using the provided config file.
|
|
func InitSchedPolicyCharacteristics(schedPoliciesConfigFilename string) error {
|
|
var schedPolConfig map[string]baseSchedPolicyState
|
|
if file, err := os.Open(schedPoliciesConfigFilename); err != nil {
|
|
return errors.Wrap(err, "Error opening file")
|
|
} else {
|
|
err := json.NewDecoder(file).Decode(&schedPolConfig)
|
|
if err != nil {
|
|
return errors.Wrap(err, "Error unmarshalling")
|
|
}
|
|
|
|
// Initializing.
|
|
// TODO: Be able to unmarshal a schedPolConfig JSON into any number of scheduling policies.
|
|
for schedPolName, schedPolState := range SchedPolicies {
|
|
switch t := schedPolState.(type) {
|
|
case *FirstFit:
|
|
t.TaskDistribution = schedPolConfig[schedPolName].TaskDistribution
|
|
t.VarianceCpuSharePerTask = schedPolConfig[schedPolName].VarianceCpuSharePerTask
|
|
case *BinPackSortedWatts:
|
|
t.TaskDistribution = schedPolConfig[schedPolName].TaskDistribution
|
|
t.VarianceCpuSharePerTask = schedPolConfig[schedPolName].VarianceCpuSharePerTask
|
|
case *MaxMin:
|
|
t.TaskDistribution = schedPolConfig[schedPolName].TaskDistribution
|
|
t.VarianceCpuSharePerTask = schedPolConfig[schedPolName].VarianceCpuSharePerTask
|
|
case *MaxGreedyMins:
|
|
t.TaskDistribution = schedPolConfig[schedPolName].TaskDistribution
|
|
t.VarianceCpuSharePerTask = schedPolConfig[schedPolName].VarianceCpuSharePerTask
|
|
}
|
|
}
|
|
|
|
// Initialize schedPoliciesToSwitch to allow binary searching for scheduling policy switching.
|
|
spInformation := map[string]float64{}
|
|
for spName, sp := range SchedPolicies {
|
|
spInformation[spName] = sp.GetInfo().taskDist
|
|
}
|
|
spInformationPairList := utilities.GetPairList(spInformation)
|
|
// Sorting spInformationPairList in non-increasing order of taskDist.
|
|
sort.SliceStable(spInformationPairList, func(i, j int) bool {
|
|
return spInformationPairList[i].Value < spInformationPairList[j].Value
|
|
})
|
|
// Initializing scheduling policies that are setup for switching.
|
|
index := 0
|
|
for _, spInformationPair := range spInformationPairList {
|
|
if spInformationPair.Value != 0 {
|
|
schedPoliciesToSwitch[index] = struct {
|
|
spName string
|
|
sp SchedPolicyState
|
|
}{
|
|
spName: spInformationPair.Key,
|
|
sp: SchedPolicies[spInformationPair.Key],
|
|
}
|
|
index++
|
|
}
|
|
}
|
|
|
|
// Initializing the next and previous policy based on the the round-robin ordering.
|
|
// The next policy for policy at N would correspond to the value at index N+1 in schedPoliciesToSwitch.
|
|
for curPolicyIndex := 0; curPolicyIndex < len(schedPoliciesToSwitch); curPolicyIndex++ {
|
|
info := struct {
|
|
nextPolicyName string
|
|
prevPolicyName string
|
|
}{}
|
|
if curPolicyIndex == 0 {
|
|
info.prevPolicyName = schedPoliciesToSwitch[len(schedPoliciesToSwitch)-1].spName
|
|
} else {
|
|
info.prevPolicyName = schedPoliciesToSwitch[curPolicyIndex-1].spName
|
|
}
|
|
info.nextPolicyName = schedPoliciesToSwitch[(curPolicyIndex+1)%len(schedPoliciesToSwitch)].spName
|
|
schedPoliciesToSwitch[curPolicyIndex].sp.UpdateLinks(info)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// build the scheduler with the options being applied
|
|
func buildScheduler(s sched.Scheduler, opts ...SchedulerOptions) {
|
|
s.(ElectronScheduler).init(opts...)
|
|
}
|
|
|
|
func SchedFactory(opts ...SchedulerOptions) sched.Scheduler {
|
|
s := &BaseScheduler{}
|
|
buildScheduler(s, opts...)
|
|
return s
|
|
}
|