167 lines
4.1 KiB
Go
167 lines
4.1 KiB
Go
|
|
/*
|
||
|
|
* 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}
|
||
|
|
}
|