vitess.io/vitess@v0.16.2/go/cmd/vtctldclient/cli/shards.go (about)

     1  /*
     2  Copyright 2021 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 cli
    18  
    19  import (
    20  	"sort"
    21  
    22  	"vitess.io/vitess/go/mysql"
    23  	"vitess.io/vitess/go/vt/topo/topoproto"
    24  
    25  	replicationdatapb "vitess.io/vitess/go/vt/proto/replicationdata"
    26  	topodatapb "vitess.io/vitess/go/vt/proto/topodata"
    27  	vtctldatapb "vitess.io/vitess/go/vt/proto/vtctldata"
    28  )
    29  
    30  // ParseKeyspaceShards takes a list of positional arguments and converts them to
    31  // vtctldatapb.Shard objects.
    32  func ParseKeyspaceShards(args []string) ([]*vtctldatapb.Shard, error) {
    33  	shards := make([]*vtctldatapb.Shard, 0, len(args))
    34  
    35  	for _, arg := range args {
    36  		keyspace, shard, err := topoproto.ParseKeyspaceShard(arg)
    37  		if err != nil {
    38  			return nil, err
    39  		}
    40  
    41  		shards = append(shards, &vtctldatapb.Shard{
    42  			Keyspace: keyspace,
    43  			Name:     shard,
    44  		})
    45  	}
    46  
    47  	return shards, nil
    48  }
    49  
    50  // ReplicatingTablet is a struct to group a Tablet together with its replication
    51  // Status.
    52  type ReplicatingTablet struct {
    53  	*replicationdatapb.Status
    54  	*topodatapb.Tablet
    55  }
    56  
    57  type rTablets []*ReplicatingTablet
    58  
    59  func (rts rTablets) Len() int      { return len(rts) }
    60  func (rts rTablets) Swap(i, j int) { rts[i], rts[j] = rts[j], rts[i] }
    61  func (rts rTablets) Less(i, j int) bool {
    62  	l, r := rts[i], rts[j]
    63  
    64  	// l or r ReplicationStatus would be nil if we failed to get
    65  	// the position (put them at the beginning of the list)
    66  	if l.Status == nil {
    67  		return r.Status != nil
    68  	}
    69  
    70  	if r.Status == nil {
    71  		return false
    72  	}
    73  
    74  	// the type proto has PRIMARY first, so sort by that. Will show
    75  	// the PRIMARY first, then each replica type sorted by
    76  	// replication position.
    77  	if l.Tablet.Type < r.Tablet.Type {
    78  		return true
    79  	}
    80  
    81  	if l.Tablet.Type > r.Tablet.Type {
    82  		return false
    83  	}
    84  
    85  	// then compare replication positions
    86  	lpos, err := mysql.DecodePosition(l.Status.Position)
    87  	if err != nil {
    88  		return true
    89  	}
    90  
    91  	rpos, err := mysql.DecodePosition(r.Status.Position)
    92  	if err != nil {
    93  		return false
    94  	}
    95  
    96  	return !lpos.AtLeast(rpos)
    97  }
    98  
    99  // SortedReplicatingTablets returns a sorted list of replicating tablets (which
   100  // is a struct grouping a Tablet together with its replication Status).
   101  //
   102  // The sorting order is:
   103  // 1. Tablets that do not have a replication Status.
   104  // 2. Any tablets of type PRIMARY.
   105  // 3. Remaining tablets sorted by comparing replication positions.
   106  func SortedReplicatingTablets(tabletMap map[string]*topodatapb.Tablet, replicationStatuses map[string]*replicationdatapb.Status) []*ReplicatingTablet {
   107  	rtablets := make([]*ReplicatingTablet, 0, len(tabletMap))
   108  
   109  	for alias, tablet := range tabletMap {
   110  		if status, ok := replicationStatuses[alias]; ok {
   111  			rtablets = append(rtablets, &ReplicatingTablet{
   112  				Status: status,
   113  				Tablet: tablet,
   114  			})
   115  		} else {
   116  			rtablets = append(rtablets, &ReplicatingTablet{Tablet: tablet})
   117  		}
   118  	}
   119  
   120  	sort.Sort(rTablets(rtablets))
   121  
   122  	return rtablets
   123  }