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  }