Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package domain
import (
"fmt"
"strconv"
"sync"
"time"
"ascend-common/common-utils/hwlog"
"ascend-common/common-utils/utils"
"container-manager/pkg/common"
"container-manager/pkg/devmgr"
)
const mockFaultAttr = -1
var faultCache *FaultCache = nil
var initOnce sync.Once
type FaultCache struct {
faults map[int32]map[int64]map[string]*common.DevFaultInfo
UpdateChan chan struct{}
mutex sync.Mutex
}
func GetFaultCache() *FaultCache {
initOnce.Do(
func() {
faultCache = &FaultCache{
faults: make(map[int32]map[int64]map[string]*common.DevFaultInfo),
UpdateChan: make(chan struct{}, 1),
mutex: sync.Mutex{},
}
},
)
return faultCache
}
func (fc *FaultCache) AddFault(newFault common.DevFaultInfo) {
moduleLayerKey := fmt.Sprintf("%d%d%d%d", newFault.ModuleType, newFault.ModuleID,
newFault.SubModuleType, newFault.SubModuleID)
switch newFault.Assertion {
case common.FaultOccur:
fc.dealFaultOccur(newFault, moduleLayerKey)
case common.FaultRecover:
fc.dealFaultRecover(newFault, moduleLayerKey)
default:
return
}
}
func (fc *FaultCache) dealFaultOccur(newFault common.DevFaultInfo, moduleLayerKey string) {
fc.mutex.Lock()
defer func() {
fc.mutex.Unlock()
fc.printFaults()
}()
codeLayer, ok := fc.faults[newFault.PhyID]
if !ok {
fc.faults[newFault.PhyID] = map[int64]map[string]*common.DevFaultInfo{
newFault.EventID: {moduleLayerKey: &newFault},
}
return
}
moduleLayer, ok := codeLayer[newFault.EventID]
if !ok {
codeLayer[newFault.EventID] = map[string]*common.DevFaultInfo{moduleLayerKey: &newFault}
return
}
_, ok = moduleLayer[moduleLayerKey]
if !ok {
moduleLayer[moduleLayerKey] = &newFault
return
}
}
func (fc *FaultCache) dealFaultRecover(newFault common.DevFaultInfo, moduleLayerKey string) {
fc.mutex.Lock()
defer func() {
fc.mutex.Unlock()
fc.printFaults()
}()
codeLayer, ok := fc.faults[newFault.PhyID]
if !ok {
return
}
moduleLayer, ok := codeLayer[newFault.EventID]
if !ok {
return
}
_, ok = moduleLayer[moduleLayerKey]
if !ok {
return
}
delete(moduleLayer, moduleLayerKey)
if len(moduleLayer) == 0 {
delete(codeLayer, newFault.EventID)
if len(codeLayer) == 0 {
delete(fc.faults, newFault.PhyID)
}
}
}
func (fc *FaultCache) printFaults() {
if len(fc.faults) == 0 {
hwlog.RunLog.Debug("no faults")
return
}
hwlog.RunLog.Debug("begin record faults")
for id, codeLayer := range fc.faults {
for code, moduleLayer := range codeLayer {
for moduleLayerKey, fault := range moduleLayer {
hwlog.RunLog.Debugf("id: %d, code: %s, module: %s, fault: %+v",
id, strconv.FormatInt(code, common.Hex), moduleLayerKey, fault)
}
}
}
hwlog.RunLog.Debug("record faults end")
}
func (fc *FaultCache) Notify() {
if len(fc.UpdateChan) == 0 {
fc.UpdateChan <- struct{}{}
}
}
func (fc *FaultCache) DeepCopy() (map[int32]map[int64]map[string]*common.DevFaultInfo, error) {
fc.mutex.Lock()
defer fc.mutex.Unlock()
result := new(map[int32]map[int64]map[string]*common.DevFaultInfo)
if err := common.DeepCopy(result, fc.faults); err != nil {
return nil, err
}
return *result, nil
}
func (fc *FaultCache) UpdateFaultsOnDev(id int32, faultCodes []int64) {
fc.mutex.Lock()
defer fc.mutex.Unlock()
if len(faultCodes) == 0 {
fc.faults[id] = make(map[int64]map[string]*common.DevFaultInfo)
return
}
var newCodeLayer = make(map[int64]map[string]*common.DevFaultInfo)
for code, codeLayer := range fc.faults[id] {
if utils.Contains(faultCodes, code) {
newCodeLayer[code] = codeLayer
}
}
fc.faults[id] = newCodeLayer
}
func ConstructMockModuleFault(phyId int32, faultCode int64) *common.DevFaultInfo {
return &common.DevFaultInfo{
EventID: faultCode,
LogicID: devmgr.DevMgr.GetLogicIdByPhyId(phyId),
ModuleType: mockFaultAttr,
ModuleID: mockFaultAttr,
SubModuleType: mockFaultAttr,
SubModuleID: mockFaultAttr,
Assertion: common.FaultOccur,
PhyID: phyId,
FaultLevel: GetFaultLevelByCode([]int64{faultCode}),
ReceiveTime: time.Now().Unix(),
}
}
func IsMockModuleFault(faultInfo *common.DevFaultInfo) bool {
return faultInfo.ModuleType == mockFaultAttr && faultInfo.ModuleID == mockFaultAttr &&
faultInfo.SubModuleType == mockFaultAttr && faultInfo.SubModuleID == mockFaultAttr
}