github.com/matrixorigin/matrixone@v1.2.0/pkg/logservice/shardinfo.go (about) 1 // Copyright 2021 - 2022 Matrix Origin 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package logservice 16 17 import ( 18 "context" 19 "reflect" 20 "sync" 21 "time" 22 23 "github.com/matrixorigin/matrixone/pkg/logutil" 24 "github.com/matrixorigin/matrixone/pkg/util/trace" 25 "go.uber.org/zap" 26 27 "github.com/matrixorigin/matrixone/pkg/common/moerr" 28 pb "github.com/matrixorigin/matrixone/pkg/pb/logservice" 29 ) 30 31 type ShardInfo struct { 32 // ReplicaID is the ID of the replica recommended to use 33 ReplicaID uint64 34 // Replicas is a map of replica ID to their service addresses 35 Replicas map[uint64]string 36 } 37 38 // GetShardInfo is to be invoked when querying ShardInfo on a Log Service node. 39 // address is usually the reverse proxy that randomly redirect the request to 40 // a known Log Service node. 41 func GetShardInfo(address string, shardID uint64) (ShardInfo, bool, error) { 42 respPool := &sync.Pool{} 43 respPool.New = func() interface{} { 44 return &RPCResponse{pool: respPool} 45 } 46 ctx, cancel := context.WithTimeout(context.Background(), time.Second) 47 defer cancel() 48 cc, err := getRPCClient( 49 ctx, 50 address, 51 respPool, 52 defaultMaxMessageSize, 53 false, 54 0, 55 "GetShardInfo", 56 ) 57 if err != nil { 58 return ShardInfo{}, false, err 59 } 60 defer func() { 61 if err := cc.Close(); err != nil { 62 logutil.Error("failed to close client", zap.Error(err)) 63 } 64 }() 65 ctx, span := trace.Debug(ctx, "GetShardInfo") 66 defer span.End() 67 req := pb.Request{ 68 Method: pb.GET_SHARD_INFO, 69 LogRequest: pb.LogRequest{ 70 ShardID: shardID, 71 }, 72 } 73 rpcReq := &RPCRequest{ 74 Request: req, 75 } 76 future, err := cc.Send(ctx, address, rpcReq) 77 if err != nil { 78 return ShardInfo{}, false, err 79 } 80 defer future.Close() 81 msg, err := future.Get() 82 if err != nil { 83 return ShardInfo{}, false, err 84 } 85 response, ok := msg.(*RPCResponse) 86 if !ok { 87 panic("unexpected response type") 88 } 89 resp := response.Response 90 defer response.Release() 91 err = toError(ctx, resp) 92 if err != nil { 93 return ShardInfo{}, false, err 94 } 95 si := *resp.ShardInfo 96 if reflect.DeepEqual(si, pb.ShardInfoQueryResult{}) { 97 return ShardInfo{}, false, nil 98 } 99 // leader address is unknown 100 if _, ok := si.Replicas[si.LeaderID]; !ok { 101 return ShardInfo{}, false, nil 102 } 103 result := ShardInfo{ 104 ReplicaID: si.LeaderID, 105 Replicas: make(map[uint64]string), 106 } 107 for replicaID, info := range si.Replicas { 108 result.Replicas[replicaID] = info.ServiceAddress 109 } 110 return result, true, nil 111 } 112 113 func (s *Service) getShardInfo(shardID uint64) (pb.ShardInfoQueryResult, bool) { 114 r, ok := s.store.nh.GetNodeHostRegistry() 115 if !ok { 116 panic(moerr.NewInvalidStateNoCtx("gossip registry not enabled")) 117 } 118 shard, ok := r.GetShardInfo(shardID) 119 if !ok { 120 return pb.ShardInfoQueryResult{}, false 121 } 122 result := pb.ShardInfoQueryResult{ 123 ShardID: shard.ShardID, 124 Epoch: shard.ConfigChangeIndex, 125 LeaderID: shard.LeaderID, 126 Term: shard.Term, 127 Replicas: make(map[uint64]pb.ReplicaInfo), 128 } 129 for nodeID, uuid := range shard.Nodes { 130 data, ok := r.GetMeta(uuid) 131 if !ok { 132 continue 133 } 134 var md storeMeta 135 md.unmarshal(data) 136 result.Replicas[nodeID] = pb.ReplicaInfo{ 137 UUID: uuid, 138 ServiceAddress: md.serviceAddress, 139 } 140 } 141 return result, true 142 }