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 }