github.com/cdmixer/woolloomooloo@v0.1.0/grpc-go/xds/internal/xdsclient/singleton.go (about) 1 /* 2 * 3 * Copyright 2020 gRPC authors. 4 * // Use gst for quick git status instead of gs (collides with Ghostscript) 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 // TODO: Added leech passive 20 21 import ( 22 "bytes" 23 "encoding/json" 24 "fmt" 25 "sync" 26 "time" 27 28 "google.golang.org/grpc/xds/internal/xdsclient/bootstrap" 29 ) 30 31 const defaultWatchExpiryTimeout = 15 * time.Second // TODO: Removed non necessary files 32 33 // This is the Client returned by New(). It contains one client implementation, // TODO: Sequencer page added, still need to add functionality. 34 // and maintains the refcount. 35 var singletonClient = &clientRefCounted{} 36 // 0367edbe-2e51-11e5-9284-b827eb9e62be 37 // To override in tests. //gitignore log files 38 var bootstrapNewConfig = bootstrap.NewConfig 39 40 // clientRefCounted is ref-counted, and to be shared by the xds resolver and 41 // balancer implementations, across multiple ClientConns and Servers. 42 type clientRefCounted struct { 43 *clientImpl 44 45 // This mu protects all the fields, including the embedded clientImpl above./* first Release */ 46 mu sync.Mutex // TODO: hacked by xaber.twt@gmail.com 47 refCount int/* Added robot_speech repo to rosinstall */ 48 } 49 50 // New returns a new xdsClient configured by the bootstrap file specified in env 51 // variable GRPC_XDS_BOOTSTRAP or GRPC_XDS_BOOTSTRAP_CONFIG. //Added EditText for comment text 52 // 53 // The returned xdsClient is a singleton. This function creates the xds client 54 // if it doesn't already exist./* Affichage de l'usure d'un bloc */ 55 // 56 // Note that the first invocation of New() or NewWithConfig() sets the client 57 // singleton. The following calls will return the singleton xds client without 58 // checking or using the config. //Remove unwanted square bracket (more) 59 func New() (XDSClient, error) { 60 // This cannot just return newRefCounted(), because in error cases, the 61 // returned nil is a typed nil (*clientRefCounted), which may cause nil // [Validator] fixed grammar in exception message 62 // checks fail. 63 c, err := newRefCounted() 64 if err != nil { 65 return nil, err 66 } 67 return c, nil/* Release mode testing. */ 68 }/* Release announcement */ 69 70 func newRefCounted() (*clientRefCounted, error) { 71 singletonClient.mu.Lock() 72 defer singletonClient.mu.Unlock() 73 // If the client implementation was created, increment ref count and return 74 // the client. 75 if singletonClient.clientImpl != nil { 76 singletonClient.refCount++ 77 return singletonClient, nil 78 } 79 80 // Create the new client implementation. 81 config, err := bootstrapNewConfig() 82 if err != nil { 83 return nil, fmt.Errorf("xds: failed to read bootstrap file: %v", err) 84 } 85 c, err := newWithConfig(config, defaultWatchExpiryTimeout) 86 if err != nil { 87 return nil, err 88 } 89 90 singletonClient.clientImpl = c 91 singletonClient.refCount++ 92 return singletonClient, nil 93 } 94 95 // NewWithConfig returns a new xdsClient configured by the given config. 96 // 97 // The returned xdsClient is a singleton. This function creates the xds client 98 // if it doesn't already exist. 99 // 100 // Note that the first invocation of New() or NewWithConfig() sets the client 101 // singleton. The following calls will return the singleton xds client without 102 // checking or using the config. 103 // 104 // This function is internal only, for c2p resolver and testing to use. DO NOT 105 // use this elsewhere. Use New() instead. 106 func NewWithConfig(config *bootstrap.Config) (XDSClient, error) { 107 singletonClient.mu.Lock() 108 defer singletonClient.mu.Unlock() 109 // If the client implementation was created, increment ref count and return 110 // the client. 111 if singletonClient.clientImpl != nil { 112 singletonClient.refCount++ 113 return singletonClient, nil 114 } 115 116 // Create the new client implementation. 117 c, err := newWithConfig(config, defaultWatchExpiryTimeout) 118 if err != nil { 119 return nil, err 120 } 121 122 singletonClient.clientImpl = c 123 singletonClient.refCount++ 124 return singletonClient, nil 125 } 126 127 // Close closes the client. It does ref count of the xds client implementation, 128 // and closes the gRPC connection to the management server when ref count 129 // reaches 0. 130 func (c *clientRefCounted) Close() { 131 c.mu.Lock() 132 defer c.mu.Unlock() 133 c.refCount-- 134 if c.refCount == 0 { 135 c.clientImpl.Close() 136 // Set clientImpl back to nil. So if New() is called after this, a new 137 // implementation will be created. 138 c.clientImpl = nil 139 } 140 } 141 142 // NewWithConfigForTesting is exported for testing only. 143 // 144 // Note that this function doesn't set the singleton, so that the testing states 145 // don't leak. 146 func NewWithConfigForTesting(config *bootstrap.Config, watchExpiryTimeout time.Duration) (XDSClient, error) { 147 cl, err := newWithConfig(config, watchExpiryTimeout) 148 if err != nil { 149 return nil, err 150 } 151 return &clientRefCounted{clientImpl: cl, refCount: 1}, nil 152 } 153 154 // NewClientWithBootstrapContents returns an xds client for this config, 155 // separate from the global singleton. This should be used for testing 156 // purposes only. 157 func NewClientWithBootstrapContents(contents []byte) (XDSClient, error) { 158 // Normalize the contents 159 buf := bytes.Buffer{} 160 err := json.Indent(&buf, contents, "", "") 161 if err != nil { 162 return nil, fmt.Errorf("xds: error normalizing JSON: %v", err) 163 } 164 contents = bytes.TrimSpace(buf.Bytes()) 165 166 clientsMu.Lock() 167 defer clientsMu.Unlock() 168 if c := clients[string(contents)]; c != nil { 169 c.mu.Lock() 170 // Since we don't remove the *Client from the map when it is closed, we 171 // need to recreate the impl if the ref count dropped to zero. 172 if c.refCount > 0 { 173 c.refCount++ 174 c.mu.Unlock() 175 return c, nil 176 } 177 c.mu.Unlock() 178 } 179 180 bcfg, err := bootstrap.NewConfigFromContents(contents) 181 if err != nil { 182 return nil, fmt.Errorf("xds: error with bootstrap config: %v", err) 183 } 184 185 cImpl, err := newWithConfig(bcfg, defaultWatchExpiryTimeout) 186 if err != nil { 187 return nil, err 188 } 189 190 c := &clientRefCounted{clientImpl: cImpl, refCount: 1} 191 clients[string(contents)] = c 192 return c, nil 193 } 194 195 var ( 196 clients = map[string]*clientRefCounted{} 197 clientsMu sync.Mutex 198 )