github.com/kubewharf/katalyst-core@v0.5.3/pkg/controller/spd/indicator-plugin/manager.go (about) 1 /* 2 Copyright 2022 The Katalyst Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package indicator_plugin 18 19 import ( 20 "sync" 21 22 "k8s.io/apimachinery/pkg/types" 23 "k8s.io/klog/v2" 24 25 apiworkload "github.com/kubewharf/katalyst-api/pkg/apis/workload/v1alpha1" 26 "github.com/kubewharf/katalyst-core/pkg/util" 27 ) 28 29 const ( 30 indicatorSpecQueueLen = 1000 31 indicatorStatusQueueLen = 1000 32 ) 33 34 // IndicatorUpdater is used by IndicatorPlugin as a unified implementation 35 // to trigger indicator updating logic. 36 type IndicatorUpdater interface { 37 // UpdateExtendedIndicatorSpec + UpdateBusinessIndicatorSpec + UpdateSystemIndicatorSpec + UpdateBusinessIndicatorStatus 38 // for indicator add functions, IndicatorUpdater will try to merge them in local stores. 39 UpdateExtendedIndicatorSpec(_ types.NamespacedName, _ []apiworkload.ServiceExtendedIndicatorSpec) 40 UpdateBusinessIndicatorSpec(_ types.NamespacedName, _ []apiworkload.ServiceBusinessIndicatorSpec) 41 UpdateSystemIndicatorSpec(_ types.NamespacedName, _ []apiworkload.ServiceSystemIndicatorSpec) 42 UpdateBusinessIndicatorStatus(_ types.NamespacedName, _ []apiworkload.ServiceBusinessIndicatorStatus) 43 } 44 45 // IndicatorGetter is used by spd controller as indicator notifier to trigger 46 // update real spd. 47 type IndicatorGetter interface { 48 // GetIndicatorSpecChan + GetIndicatorStatusChan 49 // returns a channel to obtain the whether an update action has been triggered. 50 GetIndicatorSpecChan() chan types.NamespacedName 51 GetIndicatorStatusChan() chan types.NamespacedName 52 53 // GetIndicatorSpec + GetIndicatorStatus 54 // for indicator get functions, IndicatorUpdater will return a channel to obtain the merged results. 55 GetIndicatorSpec(_ types.NamespacedName) *apiworkload.ServiceProfileDescriptorSpec 56 GetIndicatorStatus(_ types.NamespacedName) *apiworkload.ServiceProfileDescriptorStatus 57 } 58 59 type IndicatorManager struct { 60 specMtx sync.Mutex 61 specQueue chan types.NamespacedName 62 specMap map[types.NamespacedName]*apiworkload.ServiceProfileDescriptorSpec 63 64 statusMtx sync.Mutex 65 statusQueue chan types.NamespacedName 66 statusMap map[types.NamespacedName]*apiworkload.ServiceProfileDescriptorStatus 67 } 68 69 var ( 70 _ IndicatorUpdater = &IndicatorManager{} 71 _ IndicatorGetter = &IndicatorManager{} 72 ) 73 74 func NewIndicatorManager() *IndicatorManager { 75 return &IndicatorManager{ 76 specQueue: make(chan types.NamespacedName, indicatorSpecQueueLen), 77 specMap: make(map[types.NamespacedName]*apiworkload.ServiceProfileDescriptorSpec), 78 79 statusQueue: make(chan types.NamespacedName, indicatorStatusQueueLen), 80 statusMap: make(map[types.NamespacedName]*apiworkload.ServiceProfileDescriptorStatus), 81 } 82 } 83 84 func (u *IndicatorManager) UpdateExtendedIndicatorSpec(nn types.NamespacedName, indicators []apiworkload.ServiceExtendedIndicatorSpec) { 85 u.specMtx.Lock() 86 87 insert := false 88 if _, ok := u.specMap[nn]; !ok { 89 insert = true 90 u.specMap[nn] = initServiceProfileDescriptorSpec() 91 } 92 for _, indicator := range indicators { 93 util.InsertSPDExtendedIndicatorSpec(u.specMap[nn], &indicator) 94 } 95 u.specMtx.Unlock() 96 97 if insert { 98 u.specQueue <- nn 99 } 100 } 101 102 func (u *IndicatorManager) UpdateBusinessIndicatorSpec(nn types.NamespacedName, indicators []apiworkload.ServiceBusinessIndicatorSpec) { 103 u.specMtx.Lock() 104 105 insert := false 106 if _, ok := u.specMap[nn]; !ok { 107 insert = true 108 u.specMap[nn] = initServiceProfileDescriptorSpec() 109 } 110 for _, indicator := range indicators { 111 util.InsertSPDBusinessIndicatorSpec(u.specMap[nn], &indicator) 112 } 113 u.specMtx.Unlock() 114 115 if insert { 116 u.specQueue <- nn 117 } 118 } 119 120 func (u *IndicatorManager) UpdateSystemIndicatorSpec(nn types.NamespacedName, indicators []apiworkload.ServiceSystemIndicatorSpec) { 121 u.specMtx.Lock() 122 123 insert := false 124 if _, ok := u.specMap[nn]; !ok { 125 insert = true 126 u.specMap[nn] = initServiceProfileDescriptorSpec() 127 } 128 for _, indicator := range indicators { 129 util.InsertSPDSystemIndicatorSpec(u.specMap[nn], &indicator) 130 } 131 u.specMtx.Unlock() 132 133 if insert { 134 u.specQueue <- nn 135 } 136 } 137 138 func (u *IndicatorManager) UpdateBusinessIndicatorStatus(nn types.NamespacedName, indicators []apiworkload.ServiceBusinessIndicatorStatus) { 139 u.statusMtx.Lock() 140 141 insert := false 142 if _, ok := u.statusMap[nn]; !ok { 143 insert = true 144 u.statusMap[nn] = initServiceProfileDescriptorStatus() 145 } 146 for _, indicator := range indicators { 147 util.InsertSPDBusinessIndicatorStatus(u.statusMap[nn], &indicator) 148 } 149 150 u.statusMtx.Unlock() 151 152 if insert { 153 u.statusQueue <- nn 154 } 155 } 156 157 func (u *IndicatorManager) GetIndicatorSpecChan() chan types.NamespacedName { 158 return u.specQueue 159 } 160 161 func (u *IndicatorManager) GetIndicatorStatusChan() chan types.NamespacedName { 162 return u.statusQueue 163 } 164 165 func (u *IndicatorManager) GetIndicatorSpec(nn types.NamespacedName) *apiworkload.ServiceProfileDescriptorSpec { 166 u.specMtx.Lock() 167 defer func() { 168 delete(u.specMap, nn) 169 u.specMtx.Unlock() 170 }() 171 172 spec, ok := u.specMap[nn] 173 if !ok { 174 klog.Warningf("spd spec doesn't exist for key: %s", nn.String()) 175 return nil 176 } 177 return spec 178 } 179 180 func (u *IndicatorManager) GetIndicatorStatus(nn types.NamespacedName) *apiworkload.ServiceProfileDescriptorStatus { 181 u.statusMtx.Lock() 182 defer func() { 183 delete(u.statusMap, nn) 184 u.statusMtx.Unlock() 185 }() 186 187 status, ok := u.statusMap[nn] 188 if !ok { 189 klog.Warningf("spd status doesn't exist for key: %s", nn.String()) 190 return nil 191 } 192 return status 193 } 194 195 func initServiceProfileDescriptorSpec() *apiworkload.ServiceProfileDescriptorSpec { 196 return &apiworkload.ServiceProfileDescriptorSpec{ 197 ExtendedIndicator: []apiworkload.ServiceExtendedIndicatorSpec{}, 198 BusinessIndicator: []apiworkload.ServiceBusinessIndicatorSpec{}, 199 SystemIndicator: []apiworkload.ServiceSystemIndicatorSpec{}, 200 } 201 } 202 203 func initServiceProfileDescriptorStatus() *apiworkload.ServiceProfileDescriptorStatus { 204 return &apiworkload.ServiceProfileDescriptorStatus{ 205 BusinessStatus: []apiworkload.ServiceBusinessIndicatorStatus{}, 206 } 207 }