vitess.io/vitess@v0.16.2/go/vt/srvtopo/discover.go (about)

     1  /*
     2  Copyright 2019 The Vitess Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package srvtopo
    18  
    19  import (
    20  	"sync"
    21  
    22  	"context"
    23  
    24  	"vitess.io/vitess/go/vt/concurrency"
    25  	"vitess.io/vitess/go/vt/log"
    26  	"vitess.io/vitess/go/vt/topo"
    27  
    28  	querypb "vitess.io/vitess/go/vt/proto/query"
    29  	topodatapb "vitess.io/vitess/go/vt/proto/topodata"
    30  )
    31  
    32  // FindAllTargets goes through all serving shards in the topology
    33  // for the provided tablet types. It returns one Target object per
    34  // keyspace / shard / matching TabletType.
    35  func FindAllTargets(ctx context.Context, ts Server, cell string, tabletTypes []topodatapb.TabletType) ([]*querypb.Target, error) {
    36  	ksNames, err := ts.GetSrvKeyspaceNames(ctx, cell, true)
    37  	if err != nil {
    38  		return nil, err
    39  	}
    40  
    41  	var targets []*querypb.Target
    42  	var wg sync.WaitGroup
    43  	var mu sync.Mutex
    44  	var errRecorder concurrency.AllErrorRecorder
    45  	for _, ksName := range ksNames {
    46  		wg.Add(1)
    47  		go func(keyspace string) {
    48  			defer wg.Done()
    49  
    50  			// Get SrvKeyspace for cell/keyspace.
    51  			ks, err := ts.GetSrvKeyspace(ctx, cell, keyspace)
    52  			if err != nil {
    53  				if topo.IsErrType(err, topo.NoNode) {
    54  					// Possibly a race condition, or leftover
    55  					// crud in the topology service. Just log it.
    56  					log.Warningf("GetSrvKeyspace(%v, %v) returned ErrNoNode, skipping that SrvKeyspace", cell, keyspace)
    57  				} else {
    58  					// More serious error, abort.
    59  					errRecorder.RecordError(err)
    60  				}
    61  				return
    62  			}
    63  
    64  			// Get all shard names that are used for serving.
    65  			for _, ksPartition := range ks.Partitions {
    66  				// Check we're waiting for tablets of that type.
    67  				waitForIt := false
    68  				for _, tt := range tabletTypes {
    69  					if tt == ksPartition.ServedType {
    70  						waitForIt = true
    71  					}
    72  				}
    73  				if !waitForIt {
    74  					continue
    75  				}
    76  
    77  				// Add all the shards. Note we can't have
    78  				// duplicates, as there is only one entry per
    79  				// TabletType in the Partitions list.
    80  				mu.Lock()
    81  				for _, shard := range ksPartition.ShardReferences {
    82  					targets = append(targets, &querypb.Target{
    83  						Cell:       cell,
    84  						Keyspace:   keyspace,
    85  						Shard:      shard.Name,
    86  						TabletType: ksPartition.ServedType,
    87  					})
    88  				}
    89  				mu.Unlock()
    90  			}
    91  		}(ksName)
    92  	}
    93  	wg.Wait()
    94  	if errRecorder.HasErrors() {
    95  		return nil, errRecorder.Error()
    96  	}
    97  
    98  	return targets, nil
    99  }