github.com/kubewharf/katalyst-core@v0.5.3/pkg/custom-metric/store/data/object_store.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 data
    18  
    19  import (
    20  	"bytes"
    21  	"hash/fnv"
    22  	"sync"
    23  
    24  	"github.com/kubewharf/katalyst-core/pkg/custom-metric/store/data/internal"
    25  	"github.com/kubewharf/katalyst-core/pkg/custom-metric/store/data/types"
    26  )
    27  
    28  type ObjectMetricStoreType string
    29  
    30  const (
    31  	ObjectMetricStoreTypeSimple ObjectMetricStoreType = "simple"
    32  	ObjectMetricStoreTypeBucket ObjectMetricStoreType = "bucket"
    33  )
    34  
    35  type ObjectMetricStore interface {
    36  	Add(objectMeta types.ObjectMetaImp) error
    37  	ObjectExists(objectMeta types.ObjectMetaImp) (bool, error)
    38  	GetInternalMetricImp(objectMeta types.ObjectMetaImp) (*internal.MetricImp, error)
    39  
    40  	// Iterate is read only, please do not perform any write operation like add/delete to this object
    41  	Iterate(f func(internalMetric *internal.MetricImp))
    42  	Purge()
    43  	Len() int
    44  }
    45  
    46  type simpleObjectMetricStore struct {
    47  	metricMeta types.MetricMetaImp
    48  	objectMap  map[types.ObjectMeta]*internal.MetricImp
    49  	sync.RWMutex
    50  }
    51  
    52  func NewSimpleObjectMetricStore(metricMeta types.MetricMetaImp) ObjectMetricStore {
    53  	return &simpleObjectMetricStore{
    54  		metricMeta: metricMeta,
    55  		objectMap:  make(map[types.ObjectMeta]*internal.MetricImp),
    56  	}
    57  }
    58  
    59  func (s *simpleObjectMetricStore) Add(objectMeta types.ObjectMetaImp) error {
    60  	s.Lock()
    61  	defer s.Unlock()
    62  
    63  	if _, ok := s.objectMap[objectMeta]; !ok {
    64  		s.objectMap[objectMeta] = internal.NewInternalMetric(s.metricMeta, objectMeta)
    65  	}
    66  
    67  	return nil
    68  }
    69  
    70  func (s *simpleObjectMetricStore) ObjectExists(objectMeta types.ObjectMetaImp) (bool, error) {
    71  	s.RLock()
    72  	defer s.RUnlock()
    73  
    74  	_, exist := s.objectMap[objectMeta]
    75  	return exist, nil
    76  }
    77  
    78  func (s *simpleObjectMetricStore) GetInternalMetricImp(objectMeta types.ObjectMetaImp) (*internal.MetricImp, error) {
    79  	s.RLock()
    80  	defer s.RUnlock()
    81  
    82  	return s.objectMap[objectMeta], nil
    83  }
    84  
    85  func (s *simpleObjectMetricStore) Iterate(f func(internalMetric *internal.MetricImp)) {
    86  	s.RLock()
    87  	defer s.RUnlock()
    88  
    89  	for _, InternalMetricImp := range s.objectMap {
    90  		f(InternalMetricImp)
    91  	}
    92  }
    93  
    94  func (s *simpleObjectMetricStore) Purge() {
    95  	s.Lock()
    96  	defer s.Unlock()
    97  
    98  	for _, internalMetric := range s.objectMap {
    99  		if internalMetric.Empty() {
   100  			delete(s.objectMap, internalMetric.ObjectMetaImp)
   101  		}
   102  	}
   103  }
   104  
   105  func (s *simpleObjectMetricStore) Len() int {
   106  	s.RLock()
   107  	defer s.RUnlock()
   108  	return len(s.objectMap)
   109  }
   110  
   111  type bucketObjectMetricStore struct {
   112  	bucketSize int
   113  	buckets    map[int]ObjectMetricStore
   114  }
   115  
   116  func NewBucketObjectMetricStore(bucketSize int, metricMeta types.MetricMetaImp) ObjectMetricStore {
   117  	buckets := make(map[int]ObjectMetricStore, bucketSize)
   118  	for i := 0; i < bucketSize; i++ {
   119  		index := i
   120  		buckets[index] = NewSimpleObjectMetricStore(metricMeta)
   121  	}
   122  
   123  	return &bucketObjectMetricStore{
   124  		bucketSize: bucketSize,
   125  		buckets:    buckets,
   126  	}
   127  }
   128  
   129  func (b *bucketObjectMetricStore) getIndex(objectMeta types.ObjectMetaImp) (int, error) {
   130  	buffer := bytes.Buffer{}
   131  	buffer.WriteString(objectMeta.GetObjectNamespace())
   132  	buffer.WriteString(":")
   133  	buffer.WriteString(objectMeta.GetObjectName())
   134  	namespacedName := make([]byte, buffer.Len())
   135  	_, err := buffer.Read(namespacedName)
   136  	if err != nil {
   137  		return -1, err
   138  	}
   139  
   140  	h := fnv.New64()
   141  	_, err = h.Write(namespacedName)
   142  	if err != nil {
   143  		return -1, err
   144  	}
   145  	return int(h.Sum64() % uint64(b.bucketSize)), nil
   146  }
   147  
   148  func (b *bucketObjectMetricStore) Add(objectMeta types.ObjectMetaImp) error {
   149  	index, err := b.getIndex(objectMeta)
   150  	if err != nil {
   151  		return err
   152  	}
   153  	return b.buckets[index].Add(objectMeta)
   154  }
   155  
   156  func (b *bucketObjectMetricStore) ObjectExists(objectMeta types.ObjectMetaImp) (bool, error) {
   157  	index, err := b.getIndex(objectMeta)
   158  	if err != nil {
   159  		return false, err
   160  	}
   161  	return b.buckets[index].ObjectExists(objectMeta)
   162  }
   163  
   164  func (b *bucketObjectMetricStore) GetInternalMetricImp(objectMeta types.ObjectMetaImp) (*internal.MetricImp, error) {
   165  	index, err := b.getIndex(objectMeta)
   166  	if err != nil {
   167  		return nil, err
   168  	}
   169  
   170  	return b.buckets[index].GetInternalMetricImp(objectMeta)
   171  }
   172  
   173  func (b *bucketObjectMetricStore) Iterate(f func(internalMetric *internal.MetricImp)) {
   174  	for i := range b.buckets {
   175  		b.buckets[i].Iterate(f)
   176  	}
   177  }
   178  
   179  func (b *bucketObjectMetricStore) Purge() {
   180  	for i := range b.buckets {
   181  		b.buckets[i].Purge()
   182  	}
   183  }
   184  
   185  func (b *bucketObjectMetricStore) Len() int {
   186  	var length int
   187  	for i := range b.buckets {
   188  		length += b.buckets[i].Len()
   189  	}
   190  	return length
   191  }