1 /* 2 * 3 * Copyright 2022 gRPC authors. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 19 package xdsclient 20 21 import ( 22 "sync" 23 "time" 24 25 "google.golang.org/grpc/internal/cache" 26 "google.golang.org/grpc/internal/grpclog" 27 "google.golang.org/grpc/internal/grpcsync" 28 "google.golang.org/grpc/internal/xds/bootstrap" 29 ) 30 31 var _ XDSClient = &clientImpl{} 32 33 // clientImpl is the real implementation of the xds client. The exported Client 34 // is a wrapper of this struct with a ref count. 35 type clientImpl struct { 36 done *grpcsync.Event 37 config *bootstrap.Config 38 logger *grpclog.PrefixLogger 39 watchExpiryTimeout time.Duration 40 serializer *grpcsync.CallbackSerializer 41 serializerClose func() 42 resourceTypes *resourceTypeRegistry 43 44 // authorityMu protects the authority fields. It's necessary because an 45 // authority is created when it's used. 46 authorityMu sync.Mutex 47 // authorities is a map from ServerConfig to authority. So that 48 // different authorities sharing the same ServerConfig can share the 49 // authority. 50 // 51 // The key is **ServerConfig.String()**, not the authority name. 52 // 53 // An authority is either in authorities, or idleAuthorities, 54 // never both. 55 authorities map[string]*authority 56 // idleAuthorities keeps the authorities that are not used (the last 57 // watch on it was canceled). They are kept in the cache and will be deleted 58 // after a timeout. The key is ServerConfig.String(). 59 // 60 // An authority is either in authorities, or idleAuthorities, 61 // never both. 62 idleAuthorities *cache.TimeoutCache 63 } 64 65 // BootstrapConfig returns the configuration read from the bootstrap file. 66 // Callers must treat the return value as read-only. 67 func (c *clientImpl) BootstrapConfig() *bootstrap.Config { 68 return c.config 69 } 70 71 // close closes the gRPC connection to the management server. 72 func (c *clientImpl) close() { 73 if c.done.HasFired() { 74 return 75 } 76 c.done.Fire() 77 // TODO: Should we invoke the registered callbacks here with an error that 78 // the client is closed? 79 80 c.authorityMu.Lock() 81 for _, a := range c.authorities { 82 a.close() 83 } 84 c.idleAuthorities.Clear(true) 85 c.authorityMu.Unlock() 86 c.serializerClose() 87 88 for _, f := range c.config.XDSServer.Cleanups { 89 f() 90 } 91 for _, a := range c.config.Authorities { 92 if a.XDSServer == nil { 93 // The server for this authority is the top-level one, cleaned up above. 94 continue 95 } 96 for _, f := range a.XDSServer.Cleanups { 97 f() 98 } 99 } 100 c.logger.Infof("Shutdown") 101 } 102