A-Tune/common/checker/checker.go

167 lines
4.1 KiB
Go
Raw Normal View History

/*
* Copyright (c) 2019 Huawei Technologies Co., Ltd.
* A-Tune is licensed under the Mulan PSL v1.
* You can use this software according to the terms and conditions of the Mulan PSL v1.
* You may obtain a copy of Mulan PSL v1 at:
* http://license.coscl.org.cn/MulanPSL
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
* PURPOSE.
* See the Mulan PSL v1 for more details.
* Create: 2019-10-29
*/
package checker
import (
PB "atune/api/profile"
"atune/common/log"
"atune/common/utils"
"encoding/xml"
"fmt"
"io/ioutil"
"os"
"regexp"
"strconv"
)
// MemTopo represent the memory topology type
type MemTopo struct {
Path string
}
type children struct {
ID string `xml:"id"`
Class string `xml:"class"`
Claimed bool `xml:"claimed"`
Handle string `xml:"handle"`
Description string `xml:"description"`
Product string `xml:"product"`
Vendor string `xml:"vendor"`
Physid string `xml:"physid"`
Serial string `xml:"serial"`
Slot string `xml:"slot"`
Units string `xml:"units"`
Size int64 `xml:"size"`
Width int `xml:"width"`
Clock int64 `xml:"clock"`
}
type memorysInfo struct {
ID string `xml:"id"`
Physid string `xml:"physid"`
Childrens []children `xml:"children"`
}
type topology struct {
XMLName xml.Name `xml:"topology"`
Memorys []memorysInfo `xml:"memorys"`
}
/*
Check method check the memory topolog, whether the memory interpolation is balanced.
*/
func (m *MemTopo) Check(ch chan *PB.AckCheck) error {
file, err := os.Open(m.Path)
if err != nil {
return err
}
defer file.Close()
data, err := ioutil.ReadAll(file)
if err != nil {
return err
}
topology := topology{}
err = xml.Unmarshal(data, &topology)
if err != nil {
return err
}
reg := regexp.MustCompile(`DIMM.*?(\d)(\d)(\d)\s.*`)
var size int64
memNum := 0
size = 0
maxSocket := 0
maxChannel := 0
maxSlot := 0
for _, memory := range topology.Memorys {
for _, child := range memory.Childrens {
if params := reg.FindStringSubmatch(child.Slot); params != nil {
socket, _ := strconv.Atoi(params[1])
channel, _ := strconv.Atoi(params[2])
slot, _ := strconv.Atoi(params[3])
if socket > maxSocket {
maxSocket = socket
}
if channel > maxChannel {
maxChannel = channel
}
if slot > maxSlot {
maxSlot = slot
}
}
}
}
memTotal := (maxSocket + 1) * (maxChannel + 1) * (maxSlot + 1)
memLocation := make([]bool, memTotal)
for _, memory := range topology.Memorys {
for _, child := range memory.Childrens {
if child.Size != 0 {
if params := reg.FindStringSubmatch(child.Slot); params != nil {
socket, _ := strconv.Atoi(params[1])
channel, _ := strconv.Atoi(params[2])
slot, _ := strconv.Atoi(params[3])
index := socket*(maxChannel+1)*(maxSlot+1) + channel*(maxSlot+1) + slot
memLocation[index] = true
}
memNum++
if size != 0 && child.Size != size {
sendChanToAdm(ch, "memory sieze", utils.FAILD, "memory size is not the same")
} else if size == 0 {
size = child.Size
}
}
}
}
log.Infof("memory total num is : %d", memNum)
log.Info("memory location is:", memNum)
if memNum == memTotal {
sendChanToAdm(ch, "memory number", utils.SUCCESS, fmt.Sprintf("memory num is %d", memNum))
return nil
}
if memNum%(maxChannel+1) != 0 {
sendChanToAdm(ch, "memory number", utils.FAILD, fmt.Sprintf("memory num is %d, not recommend, recommand 8,16 or 32", memNum))
return nil
}
memHalf := memTotal / 2
for i := 0; i < memHalf; i++ {
if memLocation[i] != memLocation[i+memHalf] {
sendChanToAdm(ch, "memory location", utils.FAILD, fmt.Sprintf("memory location maybe not balanced"))
return nil
}
}
sendChanToAdm(ch, "memory location", utils.SUCCESS, "OK")
return nil
}
func sendChanToAdm(ch chan *PB.AckCheck, item string, status string, description string) {
if ch == nil {
return
}
ch <- &PB.AckCheck{Name: item, Status: status, Description: description}
}