vitess.io/vitess@v0.16.2/go/vt/topotools/utils.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 topotools 18 19 import ( 20 "reflect" 21 "sync" 22 23 "context" 24 25 "vitess.io/vitess/go/vt/topo" 26 27 topodatapb "vitess.io/vitess/go/vt/proto/topodata" 28 ) 29 30 // FindTabletByHostAndPort searches within a tablet map for tablets. 31 func FindTabletByHostAndPort(tabletMap map[string]*topo.TabletInfo, addr, portName string, port int32) (*topodatapb.TabletAlias, error) { 32 for _, ti := range tabletMap { 33 if ti.Hostname == addr && ti.PortMap[portName] == port { 34 return ti.Alias, nil 35 } 36 } 37 return nil, topo.NewError(topo.NoNode, addr+":"+portName) 38 } 39 40 // GetTabletMapForCell returns a map of TabletInfo keyed by alias as string 41 func GetTabletMapForCell(ctx context.Context, ts *topo.Server, cell string) (map[string]*topo.TabletInfo, error) { 42 aliases, err := ts.GetTabletAliasesByCell(ctx, cell) 43 if err != nil { 44 return nil, err 45 } 46 tabletMap, err := ts.GetTabletMap(ctx, aliases) 47 if err != nil { 48 // we got another error than topo.ErrNoNode 49 return nil, err 50 } 51 return tabletMap, nil 52 } 53 54 // GetAllTabletsAcrossCells returns all tablets from known cells. 55 // If it returns topo.ErrPartialResult, then the list is valid, but partial. 56 func GetAllTabletsAcrossCells(ctx context.Context, ts *topo.Server) ([]*topo.TabletInfo, error) { 57 cells, err := ts.GetKnownCells(ctx) 58 if err != nil { 59 return nil, err 60 } 61 62 results := make([][]*topo.TabletInfo, len(cells)) 63 errors := make([]error, len(cells)) 64 wg := sync.WaitGroup{} 65 wg.Add(len(cells)) 66 for i, cell := range cells { 67 go func(i int, cell string) { 68 results[i], errors[i] = ts.GetTabletsByCell(ctx, cell) 69 wg.Done() 70 }(i, cell) 71 } 72 wg.Wait() 73 74 err = nil 75 var allTablets []*topo.TabletInfo 76 for i := range cells { 77 if errors[i] == nil { 78 allTablets = append(allTablets, results[i]...) 79 } else { 80 err = topo.NewError(topo.PartialResult, "") 81 } 82 } 83 return allTablets, err 84 } 85 86 // SortedTabletMap returns two maps: 87 // - The replicaMap contains all the non-primary non-scrapped hosts. 88 // This can be used as a list of replicas to fix up for reparenting 89 // - The primaryMap contains all the tablets without parents 90 // (scrapped or not). This can be used to special case 91 // the old primary, and any tablet in a weird state, left over, ... 92 func SortedTabletMap(tabletMap map[string]*topo.TabletInfo) (map[string]*topo.TabletInfo, map[string]*topo.TabletInfo) { 93 replicaMap := make(map[string]*topo.TabletInfo) 94 primaryMap := make(map[string]*topo.TabletInfo) 95 for alias, ti := range tabletMap { 96 if ti.Type == topodatapb.TabletType_PRIMARY { 97 primaryMap[alias] = ti 98 } else { 99 replicaMap[alias] = ti 100 } 101 } 102 return replicaMap, primaryMap 103 } 104 105 // CopyMapKeys copies keys from map m into a new slice with the 106 // type specified by typeHint. Reflection can't make a new slice type 107 // just based on the key type AFAICT. 108 func CopyMapKeys(m any, typeHint any) any { 109 mapVal := reflect.ValueOf(m) 110 keys := reflect.MakeSlice(reflect.TypeOf(typeHint), 0, mapVal.Len()) 111 for _, k := range mapVal.MapKeys() { 112 keys = reflect.Append(keys, k) 113 } 114 return keys.Interface() 115 } 116 117 // CopyMapValues copies values from map m into a new slice with the 118 // type specified by typeHint. Reflection can't make a new slice type 119 // just based on the key type AFAICT. 120 func CopyMapValues(m any, typeHint any) any { 121 mapVal := reflect.ValueOf(m) 122 vals := reflect.MakeSlice(reflect.TypeOf(typeHint), 0, mapVal.Len()) 123 for _, k := range mapVal.MapKeys() { 124 vals = reflect.Append(vals, mapVal.MapIndex(k)) 125 } 126 return vals.Interface() 127 } 128 129 // MapKeys returns an array with th provided map keys. 130 func MapKeys(m any) []any { 131 keys := make([]any, 0, 16) 132 mapVal := reflect.ValueOf(m) 133 for _, kv := range mapVal.MapKeys() { 134 keys = append(keys, kv.Interface()) 135 } 136 return keys 137 }