1
0
Fork 0
cpu_ctrl/consumer/speed_controller.go

104 lines
2.5 KiB
Go

package consumer
import (
"fmt"
"os/exec"
"time"
zlog "amuz.es/src/infra/goutils/logger/zap"
"bytes"
"amuz.es/src/infra/goutils/handler"
"amuz.es/src/infra/cpu_ctrl/producer"
"go.uber.org/zap"
"github.com/alecthomas/chroma/lexers/m"
)
var ()
type fanControl struct {
processorCount int
handler *handler.Handler
fanSpeedConsumer chan producer.FanspeedInfo
sampleDuration time.Duration
logger *zap.SugaredLogger
}
type FanControl interface {
Consumer() chan<- producer.FanspeedInfo
StartControl()
}
func NewFanControl(processorCount int, sampleDuration time.Duration, handler *handler.Handler) FanControl {
return &fanControl{
processorCount: processorCount,
handler: handler,
fanSpeedConsumer: make(chan producer.FanspeedInfo, processorCount),
sampleDuration: sampleDuration,
logger: zlog.New(nil, "fanspeed"),
}
}
func (c *fanControl) Consumer() chan<- producer.FanspeedInfo { return c.fanSpeedConsumer }
func (c *fanControl) StartControl() {
defer c.handler.DecreaseWait()
defer func() {
if err := recover(); err != nil {
c.handler.NotifyError(err.(error))
}
}()
defer c.logger.Info("Fan control stopped")
c.logger.Info("Fan control started")
ticker := time.Tick(c.sampleDuration)
pastFanSpeedList, newFanSpeedList := make([]int, c.processorCount), make([]int, c.processorCount)
go func() {
for changedFanspeed := range c.fanSpeedConsumer {
newFanSpeedList[changedFanspeed.Id] = changedFanspeed.FanSpeed
}
}()
for {
select {
case <-ticker:
if !compareFanSpeed(pastFanSpeedList, newFanSpeedList) {
copy(pastFanSpeedList, newFanSpeedList)
go c.applyFanspeed(pastFanSpeedList)
}
case <-c.handler.Done():
return
}
}
}
func (c *fanControl) applyFanspeed(newFanSpeedList []int) {
args := make([]string, 0)
args = append(args, "raw", "0x3a", "0x01", )
for _, item := range newFanSpeedList {
args = append(args, fmt.Sprintf("0x%x", item))
}
args = append(args,
"0x0", "0x0", "0x0", "0x0", "0x0", "0x0",
)
cmd := exec.Command("ipmitool", args...)
if err := cmd.Run(); err != nil {
c.handler.NotifyError(err)
return
}
buf := bytes.NewBufferString("")
for _, item := range newFanSpeedList {
buf.WriteString(fmt.Sprintf("0x%x", item))
buf.WriteRune(' ')
}
c.logger.Infof("Commit fan speed with %s", buf.String())
}
func compareFanSpeed(old, new []int) bool {
new = new[:len(old)] // this line is the key
for i, v := range old {
if v != new[i] { // here is no bounds checking for b[i]
return false
}
}
return true
}