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 }