github.com/polarismesh/polaris@v1.17.8/cache/service/service_bucket.go (about)

     1  /**
     2   * Tencent is pleased to support the open source community by making Polaris available.
     3   *
     4   * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
     5   *
     6   * Licensed under the BSD 3-Clause License (the "License");
     7   * you may not use this file except in compliance with the License.
     8   * You may obtain a copy of the License at
     9   *
    10   * https://opensource.org/licenses/BSD-3-Clause
    11   *
    12   * Unless required by applicable law or agreed to in writing, software distributed
    13   * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
    14   * CONDITIONS OF ANY KIND, either express or implied. See the License for the
    15   * specific language governing permissions and limitations under the License.
    16   */
    17  
    18  package service
    19  
    20  import (
    21  	"crypto/sha1"
    22  	"encoding/hex"
    23  	"sort"
    24  	"sync"
    25  
    26  	"go.uber.org/zap"
    27  
    28  	"github.com/polarismesh/polaris/common/model"
    29  )
    30  
    31  type serviceAliasBucket struct {
    32  	lock sync.RWMutex
    33  	// aliase namespace->service->alias_id
    34  	alias map[string]map[string]map[string]*model.Service
    35  }
    36  
    37  func newServiceAliasBucket() *serviceAliasBucket {
    38  	return &serviceAliasBucket{
    39  		alias: make(map[string]map[string]map[string]*model.Service),
    40  	}
    41  }
    42  
    43  func (s *serviceAliasBucket) cleanServiceAlias(aliasFor *model.Service) {
    44  	s.lock.Lock()
    45  	defer s.lock.Unlock()
    46  
    47  	if _, ok := s.alias[aliasFor.Namespace]; !ok {
    48  		return
    49  	}
    50  	delete(s.alias[aliasFor.Namespace], aliasFor.Name)
    51  }
    52  
    53  func (s *serviceAliasBucket) addServiceAlias(alias, aliasFor *model.Service) {
    54  	s.lock.Lock()
    55  	defer s.lock.Unlock()
    56  
    57  	if _, ok := s.alias[aliasFor.Namespace]; !ok {
    58  		s.alias[aliasFor.Namespace] = map[string]map[string]*model.Service{}
    59  	}
    60  	if _, ok := s.alias[aliasFor.Namespace][aliasFor.Name]; !ok {
    61  		s.alias[aliasFor.Namespace][aliasFor.Name] = map[string]*model.Service{}
    62  	}
    63  
    64  	bucket := s.alias[aliasFor.Namespace][aliasFor.Name]
    65  	bucket[alias.ID] = alias
    66  }
    67  
    68  func (s *serviceAliasBucket) delServiceAlias(alias, aliasFor *model.Service) {
    69  	s.lock.Lock()
    70  	defer s.lock.Unlock()
    71  
    72  	if _, ok := s.alias[aliasFor.Namespace]; !ok {
    73  		return
    74  	}
    75  	if _, ok := s.alias[aliasFor.Namespace][aliasFor.Name]; !ok {
    76  		return
    77  	}
    78  
    79  	bucket := s.alias[aliasFor.Namespace][aliasFor.Name]
    80  	delete(bucket, alias.ID)
    81  }
    82  
    83  func (s *serviceAliasBucket) getServiceAliases(aliasFor *model.Service) []*model.Service {
    84  	s.lock.RLock()
    85  	defer s.lock.RUnlock()
    86  
    87  	ret := make([]*model.Service, 0, 8)
    88  	if _, ok := s.alias[aliasFor.Namespace]; !ok {
    89  		return ret
    90  	}
    91  	if _, ok := s.alias[aliasFor.Namespace][aliasFor.Name]; !ok {
    92  		return ret
    93  	}
    94  
    95  	bucket := s.alias[aliasFor.Namespace][aliasFor.Name]
    96  	for i := range bucket {
    97  		ret = append(ret, bucket[i])
    98  	}
    99  	return ret
   100  }
   101  
   102  type serviceNamespaceBucket struct {
   103  	lock     sync.RWMutex
   104  	revision string
   105  	names    map[string]*serviceNameBucket
   106  }
   107  
   108  func newServiceNamespaceBucket() *serviceNamespaceBucket {
   109  	return &serviceNamespaceBucket{
   110  		names: map[string]*serviceNameBucket{},
   111  	}
   112  }
   113  
   114  func (s *serviceNamespaceBucket) addService(svc *model.Service) {
   115  	s.lock.Lock()
   116  	defer s.lock.Unlock()
   117  
   118  	if _, ok := s.names[svc.Namespace]; !ok {
   119  		s.names[svc.Namespace] = &serviceNameBucket{
   120  			names: make(map[string]*model.Service),
   121  		}
   122  	}
   123  
   124  	s.names[svc.Namespace].addService(svc)
   125  }
   126  
   127  func (s *serviceNamespaceBucket) removeService(svc *model.Service) {
   128  	s.lock.Lock()
   129  	defer s.lock.Unlock()
   130  
   131  	if _, ok := s.names[svc.Namespace]; !ok {
   132  		s.names[svc.Namespace] = &serviceNameBucket{
   133  			names: make(map[string]*model.Service),
   134  		}
   135  	}
   136  
   137  	s.names[svc.Namespace].removeService(svc)
   138  }
   139  
   140  func (s *serviceNamespaceBucket) reloadRevision() {
   141  	s.lock.Lock()
   142  	defer s.lock.Unlock()
   143  
   144  	revisions := make([]string, 0, len(s.names))
   145  	for i := range s.names {
   146  		s.names[i].reloadRevision()
   147  		revisions = append(revisions, s.names[i].revisions)
   148  	}
   149  
   150  	sort.Strings(revisions)
   151  	h := sha1.New()
   152  	for i := range revisions {
   153  		if _, err := h.Write([]byte(revisions[i])); err != nil {
   154  			log.Error("[Cache][Service] rebuild service name all list revision", zap.Error(err))
   155  			return
   156  		}
   157  	}
   158  
   159  	s.revision = hex.EncodeToString(h.Sum(nil))
   160  }
   161  
   162  func (s *serviceNamespaceBucket) ListAllServices() (string, []*model.Service) {
   163  	s.lock.RLock()
   164  	defer s.lock.RUnlock()
   165  
   166  	ret := make([]*model.Service, 0, 32)
   167  	for namespace := range s.names {
   168  		_, val := s.ListServices(namespace)
   169  		ret = append(ret, val...)
   170  	}
   171  
   172  	return s.revision, ret
   173  }
   174  
   175  func (s *serviceNamespaceBucket) ListServices(namespace string) (string, []*model.Service) {
   176  	s.lock.RLock()
   177  	defer s.lock.RUnlock()
   178  
   179  	b, ok := s.names[namespace]
   180  	if !ok {
   181  		return "", []*model.Service{}
   182  	}
   183  
   184  	return b.listServices()
   185  }
   186  
   187  type serviceNameBucket struct {
   188  	lock      sync.RWMutex
   189  	revisions string
   190  	names     map[string]*model.Service
   191  }
   192  
   193  func (s *serviceNameBucket) addService(svc *model.Service) {
   194  	s.lock.Lock()
   195  	defer s.lock.Unlock()
   196  
   197  	s.names[svc.Name] = svc
   198  }
   199  
   200  func (s *serviceNameBucket) removeService(svc *model.Service) {
   201  	s.lock.Lock()
   202  	defer s.lock.Unlock()
   203  
   204  	delete(s.names, svc.Name)
   205  }
   206  
   207  func (s *serviceNameBucket) listServices() (string, []*model.Service) {
   208  	s.lock.RLock()
   209  	defer s.lock.RUnlock()
   210  
   211  	ret := make([]*model.Service, 0, len(s.names))
   212  	for i := range s.names {
   213  		ret = append(ret, s.names[i])
   214  	}
   215  
   216  	return s.revisions, ret
   217  }
   218  
   219  func (s *serviceNameBucket) reloadRevision() {
   220  	s.lock.Lock()
   221  	defer s.lock.Unlock()
   222  
   223  	revisions := make([]string, 0, len(s.names))
   224  	for i := range s.names {
   225  		revisions = append(revisions, s.names[i].Revision)
   226  	}
   227  
   228  	sort.Strings(revisions)
   229  
   230  	h := sha1.New()
   231  	for i := range revisions {
   232  		if _, err := h.Write([]byte(revisions[i])); err != nil {
   233  			log.Error("[Cache][Service] rebuild service name list revision", zap.Error(err))
   234  			return
   235  		}
   236  	}
   237  
   238  	s.revisions = hex.EncodeToString(h.Sum(nil))
   239  }