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  )